Feature Engineering چیست؟ آموزش مهندسی ویژگی و انتخاب ویژگی با پایتون

مهندسی ویژگی فرایند تبدیل داده خام به ورودی‌های معنادار برای مدل یادگیری ماشین است. در این راهنما ساخت، استخراج و انتخاب ویژگی را با Pipeline و مثال عملی پایتون یاد می‌گیرید.

Share
Feature Engineering چیست؟ آموزش مهندسی ویژگی و انتخاب ویژگی با پایتون

انتخاب الگوریتم قدرتمند به‌تنهایی تضمین نمی‌کند که یک پروژه یادگیری ماشین نتیجه خوبی داشته باشد. اگر داده خام نتواند اطلاعات موردنیاز را به‌شکل مناسبی در اختیار مدل قرار دهد، حتی الگوریتم‌های پیشرفته نیز عملکرد مطلوبی نخواهند داشت.

مهندسی ویژگی یا Feature Engineering فرایند تبدیل داده‌های خام به متغیرهایی است که مدل بتواند از آن‌ها الگوهای مفید یاد بگیرد.

برای مثال، زمان ثبت یک تیکت به‌صورت خام ممکن است فقط یک رشته تاریخ باشد:

2026-09-26 22:45:00

اما با مهندسی ویژگی می‌توان از آن اطلاعات معنادارتری استخراج کرد:

  • ساعت ثبت
  • روز هفته
  • تعطیل یا کاری بودن روز
  • ثبت در ساعت اداری یا خارج از ساعت اداری
  • فاصله زمانی از آخرین پیام مشتری

در بسیاری از پروژه‌ها، بهبود ویژگی‌ها بیشتر از تغییر الگوریتم باعث افزایش کیفیت مدل می‌شود.

در این مقاله می‌آموزید:

  • Feature Engineering چیست؟
  • تفاوت Feature Engineering، Feature Extraction و Feature Selection چیست؟
  • چگونه داده عددی و دسته‌ای را آماده کنیم؟
  • برای تاریخ، زمان و متن فارسی چه ویژگی‌هایی بسازیم؟
  • چگونه داده گمشده و مقادیر پرت را مدیریت کنیم؟
  • Feature Selection چگونه انجام می‌شود؟
  • چگونه از Data Leakage جلوگیری کنیم؟
  • چگونه یک Pipeline کامل با Scikit-learn بسازیم؟
  • چگونه از Embedding و API درواره برای استخراج ویژگی معنایی استفاده کنیم؟

ویژگی یا Feature چیست؟

Feature اطلاعاتی است که مدل برای پیش‌بینی از آن استفاده می‌کند.

فرض کنید هدف، پیش‌بینی فوری‌بودن یک درخواست پشتیبانی باشد. ورودی‌های احتمالی مدل می‌توانند شامل موارد زیر باشند:

  • متن پیام
  • نوع اشتراک مشتری
  • کانال ارسال پیام
  • تعداد تیکت‌های باز
  • مدت‌زمان عضویت
  • ساعت ثبت درخواست
  • تعداد خطاهای اخیر
  • مدت‌زمان گذشته از آخرین پاسخ
  • وجود واژه‌هایی مانند «قطع»، «خطا» یا «فوری»

هرکدام از این موارد می‌توانند یک ویژگی یا مجموعه‌ای از ویژگی‌ها باشند.

برچسبی که مدل باید پیش‌بینی کند Feature نیست و معمولاً با نام Target یا Label شناخته می‌شود.

Feature Engineering چیست؟

مهندسی ویژگی شامل ساخت، تبدیل، ترکیب و نمایش مناسب اطلاعات خام برای استفاده در مدل است.

نمونه‌های رایج:

  • استخراج ساعت و روز هفته از تاریخ
  • تبدیل مبلغ خام به بازه‌های قیمتی
  • محاسبه تعداد روزهای عضویت
  • محاسبه فاصله میان دو رخداد
  • تبدیل دسته‌ها به بردار عددی
  • استخراج طول متن
  • تبدیل متن به TF-IDF یا Embedding
  • ساخت نسبت میان دو متغیر
  • ترکیب نوع مشتری و کانال ارتباط
  • محدودکردن مقادیر پرت
  • تبدیل توزیع‌های بسیار نامتقارن

Scikit-learn ابزارهای مختلفی برای تبدیل بردار ویژگی خام به نمایش قابل استفاده برای مدل ارائه می‌کند.

تفاوت Feature Engineering و Data Preprocessing

این دو مفهوم هم‌پوشانی دارند، اما کاملاً یکسان نیستند.

Data Preprocessing

تمرکز آن بر تمیزکردن و آماده‌سازی داده است:

  • مدیریت مقدارهای گمشده
  • اصلاح نوع داده
  • حذف داده تکراری
  • استانداردسازی
  • کدگذاری دسته‌ها
  • هماهنگ‌کردن قالب‌ها

Feature Engineering

تمرکز آن بر ایجاد نمایش معنادارتر از مسئله است:

  • ساخت ویژگی جدید
  • ترکیب چند ستون
  • استخراج الگو از زمان
  • محاسبه سابقه و رفتار
  • تبدیل متن به ویژگی معنایی
  • نمایش بهتر رابطه داده با هدف

در عمل این مراحل معمولاً در یک Pipeline مشترک اجرا می‌شوند.

تفاوت Feature Engineering، Feature Extraction و Feature Selection

این سه اصطلاح نباید به‌جای یکدیگر استفاده شوند.

مفهومهدفمثال
Feature Engineeringساخت یا تبدیل ویژگی معنادارمحاسبه سن حساب از تاریخ عضویت
Feature Extractionتبدیل داده پیچیده به نمایش عددیتبدیل متن به TF-IDF یا Embedding
Feature Selectionنگه‌داشتن ویژگی‌های مفیدحذف ستون‌های کم‌اثر یا تکراری

Scikit-learn، Feature Extraction را تبدیل داده‌هایی مانند متن یا تصویر به ویژگی‌های عددی قابل استفاده برای مدل تعریف می‌کند.

چرا مهندسی ویژگی مهم است؟

مهندسی ویژگی مناسب می‌تواند:

  • دقت مدل را افزایش دهد.
  • الگوهای پنهان را آشکار کند.
  • مدل ساده‌تری را قابل استفاده کند.
  • زمان آموزش را کاهش دهد.
  • تفسیر نتیجه را آسان‌تر کند.
  • نویز را کاهش دهد.
  • بیش‌برازش را محدود کند.
  • عملکرد مدل در محیط واقعی را پایدارتر کند.

بااین‌حال، ویژگی نامناسب می‌تواند نتیجه معکوس داشته باشد و باعث نشت داده، پیچیدگی غیرضروری یا وابستگی مدل به الگوهای موقت شود.

ویژگی خوب چه خصوصیتی دارد؟

یک ویژگی مناسب باید تا حد امکان:

  • هنگام پیش‌بینی در دسترس باشد.
  • ارتباط معناداری با هدف داشته باشد.
  • روی داده‌های جدید قابل محاسبه باشد.
  • تعریف ثابت و مستندی داشته باشد.
  • از اطلاعات آینده استفاده نکند.
  • میان Training و Production یکسان محاسبه شود.
  • بیش‌ازحد به شناسه‌های خاص وابسته نباشد.
  • کیفیت قابل اندازه‌گیری داشته باشد.
  • مقدار گمشده آن قابل مدیریت باشد.

مهم‌ترین پرسش برای هر Feature این است:

آیا این اطلاعات دقیقاً در لحظه‌ای که مدل باید پیش‌بینی کند در دسترس است؟

اگر پاسخ منفی باشد، احتمال Data Leakage وجود دارد.

شناخت انواع داده پیش از ساخت ویژگی

قبل از مهندسی ویژگی باید نوع هر ستون مشخص شود:

داده عددی

مانند:

  • مبلغ
  • تعداد درخواست
  • زمان پاسخ
  • مصرف توکن
  • تعداد روزهای عضویت

داده دسته‌ای

مانند:

  • نوع اشتراک
  • استان
  • کانال پشتیبانی
  • دسته محصول
  • وضعیت حساب

داده ترتیبی

مانند:

  • سطح رضایت: کم، متوسط، زیاد
  • اولویت: پایین، عادی، بالا، فوری
  • سطح اشتراک: پایه، حرفه‌ای، سازمانی

داده زمانی

مانند:

  • زمان ثبت درخواست
  • تاریخ خرید
  • زمان آخرین ورود
  • تاریخ تمدید

متن

مانند:

  • پیام مشتری
  • توضیحات محصول
  • دیدگاه کاربر
  • گزارش خطا

داده چندرسانه‌ای

مانند:

  • تصویر
  • صوت
  • ویدیو

هر نوع داده به روش تبدیل متفاوتی نیاز دارد.

مهندسی ویژگی برای داده عددی

مدیریت مقدارهای گمشده

برخی مدل‌ها نمی‌توانند با مقدار خالی کار کنند. روش‌های رایج عبارت‌اند از:

  • جایگزینی با میانه
  • جایگزینی با میانگین
  • جایگزینی با پرتکرارترین مقدار
  • مقدار ثابت
  • ساخت ستون نشان‌دهنده گمشده‌بودن
from sklearn.impute import SimpleImputer

numeric_imputer = SimpleImputer(
    strategy="median",
    add_indicator=True,
)

استفاده از میانه برای داده‌هایی که مقدار پرت دارند معمولاً مقاوم‌تر از میانگین است.

ویژگی نشان‌دهنده مقدار گمشده نیز می‌تواند مفید باشد؛ زیرا گاهی نبودن اطلاعات خود یک الگوی معنادار است.

Standardization

بعضی الگوریتم‌ها به مقیاس ویژگی‌ها حساس‌اند:

  • Logistic Regression
  • SVM
  • KNN
  • شبکه‌های عصبی
  • روش‌های مبتنی بر فاصله
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

StandardScaler ویژگی‌ها را در مقیاسی هماهنگ‌تر قرار می‌دهد. این تبدیل باید فقط روی داده آموزش Fit شود.

Min-Max Scaling

اگر به محدوده مشخصی نیاز دارید:

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

MinMaxScaler به مقادیر پرت حساس است. پیش از استفاده، توزیع داده را بررسی کنید.

Robust Scaling

برای داده دارای مقادیر پرت:

from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()

تبدیل توزیع نامتقارن

مقادیر مالی، تعداد درخواست و مصرف معمولاً توزیع نامتقارن دارند. تبدیل لگاریتمی می‌تواند اختلاف میان مقادیر بزرگ را کنترل کند:

import numpy as np

df["log_monthly_usage"] = np.log1p(
    df["monthly_usage"]
)

در این تبدیل باید از منفی‌نبودن مقدارها مطمئن شوید.

گوگل برای داده‌های عددی روش‌هایی مانند Scaling خطی، Z-score، Log Scaling و Clipping را معرفی می‌کند.

Binning

در Binning مقدارهای پیوسته به بازه تبدیل می‌شوند:

import pandas as pd

df["account_age_group"] = pd.cut(
    df["account_age_days"],
    bins=[
        0,
        30,
        90,
        365,
        float("inf"),
    ],
    labels=[
        "new",
        "growing",
        "established",
        "long_term",
    ],
)

Binning زمانی مفید است که رابطه میان مقدار عددی و هدف خطی نباشد.

نباید تعداد زیادی بازه بسیار کوچک بسازید؛ زیرا مدل ممکن است روی جزئیات تصادفی Overfit شود.

مدیریت مقادیر پرت

Outlier همیشه داده اشتباه نیست. مصرف بسیار زیاد ممکن است متعلق به مشتری سازمانی واقعی باشد.

پیش از حذف مقدار پرت بررسی کنید:

  • خطای ثبت است یا مقدار معتبر؟
  • هنگام Production نیز ممکن است رخ دهد؟
  • چه اثری بر مدل دارد؟
  • آیا متعلق به یک بخش مهم از کاربران است؟
  • حذف آن باعث تغییر مسئله می‌شود؟

روش‌های ممکن:

  • اصلاح داده ثبت‌شده اشتباه
  • محدودکردن به صدک‌های مشخص
  • تبدیل لگاریتمی
  • استفاده از RobustScaler
  • ساخت یک Feature برای مقدار بسیار بزرگ
  • استفاده از الگوریتم مقاوم‌تر
lower = df["monthly_usage"].quantile(0.01)
upper = df["monthly_usage"].quantile(0.99)

df["monthly_usage_clipped"] = (
    df["monthly_usage"]
    .clip(lower, upper)
)

مرزها باید فقط با Training Set محاسبه شوند.

مهندسی ویژگی برای داده دسته‌ای

مدل‌های زیادی نمی‌توانند رشته‌هایی مانند enterprise یا telegram را مستقیماً پردازش کنند.

One-Hot Encoding

برای دسته‌هایی که ترتیب ندارند:

from sklearn.preprocessing import OneHotEncoder

encoder = OneHotEncoder(
    handle_unknown="ignore",
)

handle_unknown="ignore" کمک می‌کند دسته جدید در Production باعث توقف Pipeline نشود.

گوگل One-hot Encoding و Feature Cross را از روش‌های کار با داده دسته‌ای معرفی می‌کند.

Ordinal Encoding

برای دسته‌های دارای ترتیب واقعی:

from sklearn.preprocessing import OrdinalEncoder

encoder = OrdinalEncoder(
    categories=[
        [
            "basic",
            "professional",
            "enterprise",
        ]
    ],
    handle_unknown="use_encoded_value",
    unknown_value=-1,
)

Ordinal Encoding برای دسته بدون ترتیب مناسب نیست. تبدیل شهرها به اعداد متوالی ممکن است رابطه‌ای غیرواقعی میان آن‌ها ایجاد کند.

دسته‌های با Cardinality بالا

ستون‌هایی مانند شناسه محصول، نام شرکت یا کد صفحه ممکن است هزاران مقدار متفاوت داشته باشند.

روش‌های ممکن:

  • گروه‌بندی دسته‌های کم‌تکرار
  • Hashing
  • Frequency Encoding
  • Target Encoding کنترل‌شده
  • Embedding
  • استخراج ویژگی‌های سطح بالاتر
  • حذف شناسه خام

Target Encoding باید داخل Cross-validation محاسبه شود. محاسبه آن روی کل داده باعث نشت Target به Feature خواهد شد.

Feature Cross چیست؟

Feature Cross یعنی ترکیب دو یا چند ویژگی برای نمایش یک تعامل.

مثال:

  • نوع اشتراک + کانال پشتیبانی
  • نوع دستگاه + نسخه سیستم‌عامل
  • دسته محصول + فصل
  • کشور + روش پرداخت
  • نوع مشتری + ساعت درخواست
df["plan_channel"] = (
    df["plan"].astype(str)
    + "__"
    + df["channel"].astype(str)
)

Feature Cross زمانی مفید است که اثر یک متغیر به متغیر دیگری وابسته باشد.

تعداد ترکیب‌ها را کنترل کنید؛ زیرا ترکیب دسته‌های پرتنوع می‌تواند فضای ویژگی بسیار بزرگی ایجاد کند.

مهندسی ویژگی برای تاریخ و زمان

تاریخ خام معمولاً برای مدل کافی نیست.

df["created_at"] = pd.to_datetime(
    df["created_at"],
    utc=True,
)

df["created_hour"] = (
    df["created_at"].dt.hour
)

df["created_weekday"] = (
    df["created_at"].dt.dayofweek
)

df["created_month"] = (
    df["created_at"].dt.month
)

df["is_weekend"] = (
    df["created_weekday"] >= 5
).astype(int)

ویژگی‌های قابل استخراج:

  • ساعت
  • روز هفته
  • ماه
  • فصل
  • تعطیل یا کاری
  • ساعت اداری
  • فاصله تا تمدید
  • مدت عضویت
  • زمان گذشته از آخرین فعالیت
  • تعداد رویداد در یک بازه

محاسبه مدت عضویت

reference_time = pd.Timestamp(
    "2026-09-26",
    tz="UTC",
)

df["account_age_days"] = (
    reference_time
    - df["registered_at"]
).dt.days

در پروژه واقعی بهتر است reference_time همان لحظه پیش‌بینی باشد، نه یک تاریخ ثابت داخل کد.

جلوگیری از نشت زمانی

این ویژگی ظاهراً مفید است:

تعداد تیکت‌های حل‌شده مشتری در ماه جاری

اما اگر مدل هنگام ثبت تیکت پیش‌بینی می‌کند، نباید رخدادهایی را که بعد از همان لحظه اتفاق افتاده‌اند ببیند.

برای هر Feature زمانی باید Cutoff مشخص باشد:

  • چه زمانی پیش‌بینی انجام می‌شود؟
  • تا آن لحظه چه داده‌ای در دسترس است؟
  • آیا Aggregation فقط از گذشته استفاده می‌کند؟
  • آیا رکوردهای آینده به محاسبه وارد شده‌اند؟

ویژگی‌های تجمیعی

اطلاعات رفتاری معمولاً از تجمیع رویدادها ساخته می‌شود:

  • تعداد درخواست در هفت روز گذشته
  • میانگین مصرف در ۳۰ روز گذشته
  • تعداد خطاهای اخیر
  • فاصله از آخرین خرید
  • تعداد ورود ناموفق
  • میانگین زمان پاسخ قبلی
  • تعداد ویژگی‌های استفاده‌شده
customer_features = (
    events
    .groupby("customer_id")
    .agg(
        ticket_count=(
            "ticket_id",
            "count",
        ),
        average_response_time=(
            "response_minutes",
            "mean",
        ),
        last_activity=(
            "created_at",
            "max",
        ),
    )
    .reset_index()
)

این محاسبات باید نسبت به زمان پیش‌بینی انجام شوند. استفاده از تمام تاریخچه، شامل آینده، نتیجه ارزیابی را غیرواقعی می‌کند.

مهندسی ویژگی برای متن فارسی

متن را می‌توان به روش‌های مختلف به ویژگی عددی تبدیل کرد.

ویژگی‌های ساده متنی

  • تعداد کاراکتر
  • تعداد کلمه
  • تعداد عدد
  • تعداد علامت سؤال
  • وجود URL
  • وجود کد خطا
  • نسبت حروف فارسی
  • وجود واژه‌های مرتبط با فوریت
df["message_length"] = (
    df["message"].str.len()
)

df["word_count"] = (
    df["message"]
    .str.split()
    .str.len()
)

df["question_mark_count"] = (
    df["message"]
    .str.count(r"\?")
)

df["contains_error_code"] = (
    df["message"]
    .str.contains(
        r"\b[45]\d{2}\b",
        regex=True,
        na=False,
    )
    .astype(int)
)

این ویژگی‌ها نباید جای فهم معنایی متن را بگیرند، اما می‌توانند مکمل مناسبی باشند.

نرمال‌سازی فارسی

در متن فارسی باید موارد زیر را بررسی کنید:

  • یکسان‌سازی «ی» و «ک»
  • مدیریت نیم‌فاصله
  • حذف فاصله‌های اضافی
  • تفاوت اعداد فارسی و انگلیسی
  • علائم نگارشی
  • شکل‌های مختلف URL
  • غلط‌های املایی پرتکرار
  • متن محاوره‌ای

نباید تمام علائم و اعداد را بدون بررسی حذف کنید. کد خطا، نسخه نرم‌افزار و مبلغ ممکن است اطلاعات مهمی باشند.

TF-IDF

from sklearn.feature_extraction.text import TfidfVectorizer

vectorizer = TfidfVectorizer(
    ngram_range=(1, 2),
    min_df=2,
    max_df=0.95,
    sublinear_tf=True,
)

TfidfVectorizer متن خام را به ماتریس ویژگی TF-IDF تبدیل می‌کند.

Word و Character N-gram

Character N-gram برای متن فارسی، غلط املایی و شکل‌های نوشتاری متفاوت می‌تواند مفید باشد:

character_vectorizer = TfidfVectorizer(
    analyzer="char_wb",
    ngram_range=(3, 5),
    min_df=2,
)

می‌توان ویژگی‌های کلمه و کاراکتر را با FeatureUnion ترکیب کرد.

Embedding به‌عنوان ویژگی

Embedding متن را به یک بردار عددی معنایی تبدیل می‌کند. پیام‌هایی با مفهوم مشابه می‌توانند بردارهای نزدیک‌تری داشته باشند، حتی اگر واژه‌های یکسانی نداشته باشند.

کاربردها:

  • طبقه‌بندی متن
  • جست‌وجوی معنایی
  • خوشه‌بندی پیام‌ها
  • پیشنهاد محتوای مشابه
  • تشخیص موضوع
  • بازیابی اسناد برای RAG

برای آشنایی مفصل‌تر می‌توانید مقاله Embedding چیست؟ را مطالعه کنید.

ساخت Embedding با API درواره

API درواره با ساختار سازگار با OpenAI امکان دسترسی یکپارچه به مدل‌های مختلف را فراهم می‌کند.

آدرس پایه:

https://api.darvareh.ir/v1

نصب کتابخانه:

pip install openai numpy scikit-learn

متغیرهای محیطی:

export DARVAREH_API_KEY="YOUR_API_KEY"
export DARVAREH_EMBEDDING_MODEL="YOUR_EMBEDDING_MODEL_ID"

کد نمونه:

import os

import numpy as np
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DARVAREH_API_KEY"],
    base_url="https://api.darvareh.ir/v1",
)

EMBEDDING_MODEL = os.environ[
    "DARVAREH_EMBEDDING_MODEL"
]


def create_embeddings(
    texts: list[str],
) -> np.ndarray:
    response = client.embeddings.create(
        model=EMBEDDING_MODEL,
        input=texts,
    )

    vectors = [
        item.embedding
        for item in response.data
    ]

    return np.asarray(
        vectors,
        dtype=np.float32,
    )

شناسه مدل را باید از فهرست فعلی مدل‌های درواره انتخاب کنید.

پس از ساخت بردارها می‌توان یک مدل طبقه‌بندی آموزش داد:

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold

X_embeddings = create_embeddings(
    messages
)

classifier = LogisticRegression(
    max_iter=1000,
)

cv = StratifiedKFold(
    n_splits=5,
    shuffle=True,
    random_state=42,
)

scores = cross_val_score(
    classifier,
    X_embeddings,
    labels,
    cv=cv,
    scoring="f1_macro",
)

print("Macro F1:", scores.mean())

برای جلوگیری از هزینه تکراری، Embedding هر متن را همراه با شناسه مدل و نسخه ورودی ذخیره کنید.

برای شروع اتصال می‌توانید مستندات API درواره را ببینید.

استفاده از مدل زبانی برای استخراج ویژگی ساختاریافته

مدل زبانی می‌تواند اطلاعات ساختاریافته‌ای از متن استخراج کند:

  • موضوع پیام
  • لحن
  • محصول اشاره‌شده
  • نیاز به پاسخ انسانی
  • وجود کد خطا
  • نوع اقدام درخواستی
  • خلاصه کوتاه

این اطلاعات سپس می‌توانند به‌عنوان Feature وارد مدل یا قواعد کسب‌وکار شوند.

import os
from typing import Literal

from openai import OpenAI
from pydantic import BaseModel

client = OpenAI(
    api_key=os.environ["DARVAREH_API_KEY"],
    base_url="https://api.darvareh.ir/v1",
)

MODEL_ID = os.environ["DARVAREH_MODEL"]


class MessageFeatures(BaseModel):
    topic: Literal[
        "sales",
        "technical",
        "billing",
        "feedback",
        "other",
    ]
    tone: Literal[
        "neutral",
        "negative",
        "positive",
    ]
    contains_error_code: bool
    requires_human_review: bool


def extract_message_features(
    message: str,
) -> MessageFeatures:
    completion = client.chat.completions.create(
        model=MODEL_ID,
        temperature=0,
        messages=[
            {
                "role": "system",
                "content": (
                    "از پیام مشتری ویژگی‌های خواسته‌شده "
                    "را استخراج کن و فقط JSON معتبر برگردان."
                ),
            },
            {
                "role": "user",
                "content": message,
            },
        ],
    )

    content = completion.choices[0].message.content

    if not content:
        raise ValueError(
            "مدل پاسخ خالی برگرداند."
        )

    return MessageFeatures.model_validate_json(
        content
    )

خروجی مدل زبانی را نباید حقیقت قطعی در نظر گرفت. دقت Featureهای استخراج‌شده باید روی مجموعه برچسب‌گذاری‌شده ارزیابی شود.

همچنین نسخه مدل، پرامپت و Schema باید ثبت شوند؛ زیرا تغییر هرکدام می‌تواند توزیع ویژگی‌ها را تغییر دهد.

ساخت Pipeline برای داده ترکیبی

فرض کنید دیتاست پشتیبانی شامل این ستون‌ها است:

  • message: متن پیام
  • plan: نوع اشتراک
  • channel: کانال ارتباطی
  • open_tickets: تعداد تیکت باز
  • account_age_days: مدت عضویت

یک Pipeline کامل:

from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler

numeric_features = [
    "open_tickets",
    "account_age_days",
]

categorical_features = [
    "plan",
    "channel",
]

text_feature = "message"

numeric_pipeline = Pipeline(
    [
        (
            "imputer",
            SimpleImputer(
                strategy="median",
                add_indicator=True,
            ),
        ),
        (
            "scaler",
            StandardScaler(),
        ),
    ]
)

categorical_pipeline = Pipeline(
    [
        (
            "imputer",
            SimpleImputer(
                strategy="most_frequent",
            ),
        ),
        (
            "encoder",
            OneHotEncoder(
                handle_unknown="ignore",
            ),
        ),
    ]
)

preprocessor = ColumnTransformer(
    transformers=[
        (
            "numeric",
            numeric_pipeline,
            numeric_features,
        ),
        (
            "categorical",
            categorical_pipeline,
            categorical_features,
        ),
        (
            "text",
            TfidfVectorizer(
                ngram_range=(1, 2),
                min_df=2,
            ),
            text_feature,
        ),
    ]
)

model = Pipeline(
    [
        (
            "preprocessor",
            preprocessor,
        ),
        (
            "classifier",
            LogisticRegression(
                max_iter=1000,
            ),
        ),
    ]
)

ColumnTransformer اجازه می‌دهد برای هر گروه از ستون‌ها تبدیل متفاوتی اعمال شود و Pipeline همه مراحل را همراه با مدل نگه می‌دارد.

Scikit-learn استفاده از Pipeline را برای اجرای متوالی Transformerها و مدل نهایی پشتیبانی می‌کند.

آموزش و ارزیابی Pipeline

from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_validate

cv = StratifiedKFold(
    n_splits=5,
    shuffle=True,
    random_state=42,
)

results = cross_validate(
    model,
    X,
    y,
    cv=cv,
    scoring=[
        "accuracy",
        "f1_macro",
    ],
    return_train_score=True,
    n_jobs=-1,
)

print(
    "Train F1:",
    results["train_f1_macro"].mean(),
)

print(
    "Validation F1:",
    results["test_f1_macro"].mean(),
)

قرارگرفتن تمام تبدیل‌ها داخل Pipeline از استفاده ناخواسته اطلاعات Fold اعتبارسنجی جلوگیری می‌کند.

Feature Selection چیست؟

Feature Selection یعنی انتخاب زیرمجموعه‌ای از ویژگی‌ها که بیشترین اطلاعات مفید را برای مدل دارند.

مزایای احتمالی:

  • کاهش بیش‌برازش
  • کاهش زمان آموزش
  • کاهش حافظه
  • ساده‌ترشدن مدل
  • افزایش توضیح‌پذیری
  • حذف نویز
  • کاهش هزینه جمع‌آوری داده

اما حذف ویژگی باید با Cross-validation ارزیابی شود. ویژگی‌ای که به‌تنهایی ضعیف است ممکن است در ترکیب با ویژگی دیگر مفید باشد.

انواع روش‌های انتخاب ویژگی

روش‌های Filter

ویژگی‌ها پیش از آموزش مدل و با معیار آماری رتبه‌بندی می‌شوند.

نمونه‌ها:

  • Variance Threshold
  • آزمون‌های آماری
  • Mutual Information
  • همبستگی

مزایا:

  • سریع
  • مستقل از مدل
  • مناسب داده دارای ویژگی زیاد

محدودیت:

  • تعامل پیچیده میان ویژگی‌ها را کمتر در نظر می‌گیرد.

روش‌های Wrapper

زیرمجموعه‌های مختلف ویژگی با آموزش مکرر مدل مقایسه می‌شوند.

نمونه:

  • Recursive Feature Elimination
  • Sequential Feature Selection

مزایا:

  • هماهنگ با مدل انتخاب‌شده

معایب:

  • هزینه محاسباتی بیشتر
  • خطر بیش‌برازش روی Validation
  • نامناسب برای تعداد بسیار زیاد ویژگی

روش‌های Embedded

انتخاب ویژگی بخشی از آموزش مدل است.

نمونه‌ها:

  • L1 Regularization
  • Decision Tree
  • Random Forest
  • Gradient Boosting

انتخاب ویژگی با SelectKBest

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import mutual_info_classif

selection_model = Pipeline(
    [
        (
            "preprocessor",
            preprocessor,
        ),
        (
            "selector",
            SelectKBest(
                score_func=mutual_info_classif,
                k=50,
            ),
        ),
        (
            "classifier",
            LogisticRegression(
                max_iter=1000,
            ),
        ),
    ]
)

مقدار k باید با Cross-validation انتخاب شود.

Scikit-learn انتخاب تک‌متغیره را روشی برای انتخاب ویژگی‌های بهتر بر اساس آزمون‌های آماری معرفی می‌کند.

حذف ویژگی کم‌تغییر

ویژگی‌ای که تقریباً در تمام ردیف‌ها مقدار یکسان دارد ممکن است اطلاعات کمی ارائه دهد:

from sklearn.feature_selection import VarianceThreshold

selector = VarianceThreshold(
    threshold=0.01,
)

این روش باید با توجه به نوع داده استفاده شود. یک Feature کم‌تکرار ممکن است برای تشخیص یک کلاس مهم ارزشمند باشد.

Recursive Feature Elimination

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

estimator = LogisticRegression(
    max_iter=1000,
)

selector = RFE(
    estimator=estimator,
    n_features_to_select=20,
    step=5,
)

RFE مدل را چند بار آموزش می‌دهد و به‌تدریج ویژگی‌های کم‌اهمیت‌تر را حذف می‌کند.

برای داده‌های بسیار بزرگ یا هزاران ویژگی متنی ممکن است هزینه آن زیاد باشد.

انتخاب ویژگی با L1

from sklearn.linear_model import LogisticRegression
from sklearn.feature_selection import SelectFromModel

selector = SelectFromModel(
    LogisticRegression(
        penalty="l1",
        solver="liblinear",
        max_iter=1000,
    )
)

L1 می‌تواند بخشی از ضرایب را به صفر نزدیک کند و مدل کم‌تراکم‌تری بسازد.

اهمیت ویژگی در مدل‌های درختی

from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel

selector = SelectFromModel(
    RandomForestClassifier(
        n_estimators=300,
        random_state=42,
    ),
    threshold="median",
)

اهمیت داخلی درخت‌ها همیشه تفسیر کاملی از اثر واقعی ویژگی ارائه نمی‌کند. ویژگی‌های هم‌بسته می‌توانند اهمیت را میان خود تقسیم کنند.

برای تحلیل مطمئن‌تر می‌توان از Permutation Importance روی داده اعتبارسنجی استفاده کرد.

Data Leakage در انتخاب ویژگی

این روش اشتباه است:

selector.fit(X, y)
X_selected = selector.transform(X)

scores = cross_val_score(
    model,
    X_selected,
    y,
    cv=5,
)

در اینجا Feature Selection پیش از Cross-validation روی کل داده انجام شده و اطلاعات تمام Labelها وارد انتخاب شده است.

روش درست:

pipeline = Pipeline(
    [
        (
            "selector",
            selector,
        ),
        (
            "model",
            model,
        ),
    ]
)

scores = cross_val_score(
    pipeline,
    X,
    y,
    cv=5,
)

Scikit-learn تأکید می‌کند انتخاب ویژگی نیز مانند سایر مراحل پیش‌پردازش باید فقط با داده آموزش انجام شود؛ استفاده از Test Set نتیجه‌ای خوش‌بینانه ایجاد می‌کند.

ویژگی‌های خطرناک که باید بررسی شوند

شناسه یکتا

ستون‌هایی مانند شماره تیکت معمولاً الگوی قابل تعمیمی ندارند.

اطلاعات آینده

وضعیت نهایی پرونده یا زمان حل نباید برای پیش‌بینی اولیه استفاده شود.

ویژگی ساخته‌شده از Target

اگر Feature مستقیماً یا غیرمستقیم Label را بازتاب دهد، نتیجه غیرواقعی خواهد بود.

داده پس از رخداد

برای پیش‌بینی لغو اشتراک، اطلاعات ثبت‌شده پس از لغو نباید وارد مدل شود.

متغیرهای واسطه‌ای

گاهی یک ستون نتیجه تصمیم انسانی قبلی است و Target را آشکار می‌کند.

داده ناسازگار با Production

اگر Feature فقط در محیط آزمایش قابل محاسبه باشد، مدل قابل استقرار نیست.

Feature Store چیست؟

Feature Store سامانه‌ای برای تعریف، محاسبه، نگهداری و ارائه Featureها است.

مزایای آن:

  • یکسان‌بودن محاسبه در Training و Production
  • استفاده مجدد از ویژگی‌ها
  • مدیریت نسخه
  • ثبت منبع داده
  • کنترل تازگی
  • کاهش Training-serving Skew
  • مستندسازی مالک و تعریف Feature

برای پروژه کوچک، جدول‌های نسخه‌بندی‌شده و Pipeline مشخص می‌توانند کافی باشند. با افزایش تعداد مدل‌ها و منابع داده، Feature Store ارزش بیشتری پیدا می‌کند.

Training-serving Skew چیست؟

Training-serving Skew زمانی رخ می‌دهد که Featureها در آموزش و Production به روش متفاوتی محاسبه شوند.

مثال:

  • در آموزش، مقدار خالی با میانه جایگزین شده است.
  • در Production، مقدار خالی صفر می‌شود.
  • در آموزش، زمان بر اساس UTC است.
  • در Production، زمان محلی استفاده می‌شود.
  • در آموزش، متن فارسی نرمال شده است.
  • در Production، متن خام وارد مدل می‌شود.

استفاده از Pipeline مشترک و تست خروجی Featureها این خطر را کاهش می‌دهد.

پایش Featureها پس از انتشار

پس از استقرار فقط کیفیت خروجی مدل را بررسی نکنید. توزیع Featureها نیز باید مانیتور شود.

موارد مهم:

  • درصد مقدار گمشده
  • مقدارهای جدید دسته‌ای
  • تغییر میانگین و پراکندگی
  • افزایش مقادیر خارج از محدوده
  • تغییر طول متن
  • تغییر سهم کانال‌ها
  • کاهش تازگی داده
  • تغییر توزیع Embedding
  • شکست فرایند محاسبه Feature
  • تغییر Schema

تغییر شدید توزیع ممکن است نشانه Data Drift یا خرابی Pipeline باشد.

اشتباهات رایج در Feature Engineering

ساخت ویژگی پیش از تعریف زمان پیش‌بینی

ابتدا باید لحظه تصمیم مدل مشخص شود.

استفاده از اطلاعات آینده

این خطا یکی از رایج‌ترین دلایل امتیاز غیرواقعی است.

Fit کردن Transformer روی کل داده

تمام Transformerها باید داخل Pipeline و فقط روی Training Fit شوند.

One-Hot کردن شناسه‌های پرتعداد

این کار می‌تواند هزاران ستون کم‌ارزش ایجاد کند.

حذف بی‌دلیل مقادیر پرت

مقادیر پرت ممکن است نماینده کاربران واقعی و مهم باشند.

Featureهای بسیار زیاد بدون ارزیابی

افزایش تعداد ویژگی لزوماً کیفیت را بهتر نمی‌کند.

استفاده از Target Encoding بدون Cross-validation

این کار باعث نشت Label می‌شود.

حذف علائم و اعداد از متن

کد خطا، مبلغ و نسخه می‌توانند اطلاعات اصلی پیام باشند.

محاسبه متفاوت در Production

کد Feature Engineering باید تا حد امکان میان آموزش و سرویس عملیاتی مشترک باشد.

انتخاب ویژگی با Test Set

Test Set فقط برای ارزیابی نهایی است.

اعتماد کامل به Feature استخراج‌شده توسط مدل زبانی

خروجی مدل باید اعتبارسنجی، نسخه‌بندی و مانیتور شود.

چک‌لیست مهندسی ویژگی

پیش از آموزش مدل بررسی کنید:

  • هدف و لحظه پیش‌بینی دقیقاً مشخص شده است.
  • نوع هر ستون تعیین شده است.
  • Feature فقط از اطلاعات در دسترس همان لحظه استفاده می‌کند.
  • داده‌های تکراری و ناسازگار بررسی شده‌اند.
  • مقدارهای گمشده مدیریت می‌شوند.
  • دسته جدید در Production باعث خطا نمی‌شود.
  • Featureهای زمانی فقط از گذشته ساخته می‌شوند.
  • پیش‌پردازش داخل Pipeline است.
  • Feature Selection داخل Cross-validation انجام می‌شود.
  • Training و Production منطق مشترک دارند.
  • نسخه و تعریف Featureها ثبت می‌شود.
  • تأثیر هر ویژگی با Ablation Test بررسی شده است.
  • هزینه محاسبه Feature در نظر گرفته شده است.
  • توزیع Featureها پس از انتشار مانیتور می‌شود.
  • Test Set در ساخت ویژگی دخالت نداشته است.

پرسش‌های متداول

Feature Engineering چیست؟

فرایند تبدیل داده خام به ویژگی‌های معنادار و قابل استفاده برای مدل یادگیری ماشین است.

تفاوت Feature و Label چیست؟

Feature ورودی مدل است. Label یا Target مقداری است که مدل باید آن را پیش‌بینی کند.

تفاوت Feature Engineering و Feature Selection چیست؟

در Feature Engineering ویژگی جدید ساخته یا تبدیل می‌شود. در Feature Selection بخشی از ویژگی‌های موجود انتخاب می‌شوند.

آیا مهندسی ویژگی فقط برای مدل‌های کلاسیک است؟

خیر. شبکه‌های عصبی، مدل‌های زبانی، سیستم‌های RAG و Agentها نیز به آماده‌سازی ورودی، استخراج اطلاعات و طراحی نمایش مناسب داده نیاز دارند.

آیا Scaling برای همه مدل‌ها لازم است؟

خیر. مدل‌هایی مانند درخت تصمیم معمولاً به Scaling حساس نیستند، اما SVM، KNN، Logistic Regression و شبکه‌های عصبی اغلب از مقیاس‌بندی مناسب سود می‌برند.

برای داده دسته‌ای از چه روشی استفاده کنیم؟

برای دسته‌های کم‌تعداد و بدون ترتیب، One-Hot Encoding انتخاب رایجی است. برای داده دارای ترتیب واقعی می‌توان از Ordinal Encoding استفاده کرد. دسته‌های بسیار پرتعداد به روش متفاوتی نیاز دارند.

TF-IDF بهتر است یا Embedding؟

TF-IDF ساده، سریع و برای بسیاری از مسائل طبقه‌بندی متن مؤثر است. Embedding اطلاعات معنایی بیشتری ثبت می‌کند. انتخاب نهایی باید با داده واقعی و Cross-validation انجام شود.

آیا Embedding یک Feature است؟

بله. هر بعد بردار Embedding بخشی از نمایش عددی متن، تصویر یا داده دیگر است و می‌تواند به‌عنوان ورودی مدل استفاده شود.

چگونه بهترین Featureها را پیدا کنیم؟

دانش دامنه، تحلیل داده، Cross-validation، Feature Importance، Selection و Ablation Test را با هم استفاده کنید.

Ablation Test چیست؟

در این آزمایش یک Feature یا گروه Feature حذف می‌شود و تغییر عملکرد مدل اندازه‌گیری می‌شود. این روش اثر واقعی گروه‌های ویژگی را بهتر نشان می‌دهد.

جمع‌بندی

Feature Engineering پلی میان داده خام و مدل یادگیری ماشین است. کیفیت این مرحله می‌تواند بیش از پیچیده‌ترکردن الگوریتم بر نتیجه پروژه اثر بگذارد.

برای اجرای اصولی:

  1. ابتدا زمان و هدف پیش‌بینی را مشخص کنید.
  2. نوع داده هر ستون را بشناسید.
  3. مقدارهای گمشده و پرت را آگاهانه مدیریت کنید.
  4. داده عددی را متناسب با الگوریتم مقیاس‌بندی کنید.
  5. دسته‌ها را بدون ایجاد ترتیب مصنوعی کدگذاری کنید.
  6. از تاریخ و زمان ویژگی‌های قابل تعمیم بسازید.
  7. متن فارسی را با حفظ اطلاعات مهم نرمال کنید.
  8. TF-IDF و Embedding را روی داده واقعی مقایسه کنید.
  9. Feature Selection را داخل Pipeline انجام دهید.
  10. از ورود اطلاعات آینده و Test Set جلوگیری کنید.
  11. محاسبات Training و Production را هماهنگ نگه دارید.
  12. کیفیت و توزیع Featureها را پس از انتشار پایش کنید.

با استفاده از API درواره می‌توانید مدل‌های Embedding و زبانی مختلف را با یک اتصال یکپارچه آزمایش کنید و از آن‌ها برای استخراج ویژگی معنایی، طبقه‌بندی متن و ساخت قابلیت‌های هوش مصنوعی در نرم‌افزار خود استفاده کنید.

مقالات مرتبط

منابع

این مقاله صرفاً با هدف آموزش و اطلاع‌رسانی تهیه شده است. پیش از استفاده عملی، مستندات رسمی سرویس‌ها و صفحه سلب مسئولیت را مطالعه کنید.

Read more