ساخت خطوط لوله یادگیری ماشینی بدون وابستگی به الگوریتم

در هسته خود، MLarena به عنوان یک mlflow.pyfuncمدل سفارشی پیاده‌سازی شده است. این امر آن را کاملاً با اکوسیستم MLflow سازگار می‌کند و امکان ردیابی آزمایش قوی، نسخه‌بندی مدل و استقرار یکپارچه را صرف نظر از اینکه از کدام کتابخانه ML اساسی استفاده می‌کنید، فراهم می‌کند و در صورت لزوم، مهاجرت روان بین الگوریتم‌ها را امکان‌پذیر می‌سازد.

علاوه بر این، این پلتفرم به دنبال ایجاد تعادل بین اتوماسیون و بینش تخصصی در توسعه مدل است. بسیاری از ابزارها یا بیش از حد خلاصه‌سازی می‌کنند و درک آنچه در پشت صحنه اتفاق می‌افتد را دشوار می‌کنند، یا آنقدر به کدهای تکراری نیاز دارند که تکرار را کند می‌کنند. MLarena قصد دارد این شکاف را پر کند: این پلتفرم وظایف معمول یادگیری ماشین را با استفاده از بهترین شیوه‌ها خودکار می‌کند، در عین حال ابزارهایی را برای کاربران متخصص فراهم می‌کند تا مدل‌های خود را به طور مؤثرتری تشخیص، تفسیر و بهینه کنند.

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


۱. یک انتزاع سبک برای آموزش و ارزیابی

یکی از نقاط ضعف رایج در گردش‌های کاری یادگیری ماشین، حجم کدهای تکراری مورد نیاز برای ایجاد یک خط لوله عملیاتی است، به خصوص هنگام جابجایی بین الگوریتم‌ها یا چارچوب‌ها. MLarena یک انتزاع سبک را معرفی می‌کند که این فرآیند را استانداردسازی می‌کند و در عین حال با تخمین‌گرهای سبک scikit-learn سازگار است. 

در اینجا یک مثال ساده از نحوه MLPipelineعملکرد شیء اصلی آورده شده است:

from mlarena import MLPipeline, PreProcessor

# Define the pipeline
mlpipeline_rf = MLPipeline(
    model = RandomForestClassifier(), # works with any sklearn style algorithm
    preprocessor = PreProcessor() 
)
# Fit the pipeline
mlpipeline_rf.fit(X_train,y_train)
# Predict on new data and evaluate
results = mlpipeline_rf.evaluate(X_test, y_test)

این رابط، مراحل رایج پیش‌پردازش، آموزش مدل و ارزیابی را در کنار هم قرار می‌دهد. در داخل، نوع وظیفه (طبقه‌بندی یا رگرسیون) را به طور خودکار تشخیص می‌دهد، معیارهای مناسب را اعمال می‌کند و یک گزارش تشخیصی تولید می‌کند – همه اینها بدون از دست دادن انعطاف‌پذیری در نحوه تعریف مدل‌ها یا پیش‌پردازنده‌ها (بعداً در مورد گزینه‌های سفارشی‌سازی بیشتر صحبت خواهیم کرد).

MLarena به جای اینکه همه چیز را انتزاعی کند، بر روی آشکار کردن پیش‌فرض‌ها و بینش‌های معنادار تمرکز می‌کند. این evaluateروش فقط نمرات را برنمی‌گرداند، بلکه یک گزارش کامل متناسب با کار ارائه می‌دهد.

برای وظایف طبقه‌بندی، گزارش ارزیابی شامل معیارهای کلیدی مانند AUC، MCC، دقت، فراخوانی، F1 و F-beta (زمانی که betaمشخص شده باشد) است. خروجی‌های بصری شامل یک منحنی ROC-AUC (پایین سمت چپ)، یک ماتریس درهم‌ریختگی (پایین سمت راست) و یک نمودار دقت-فراخوانی-آستانه در بالا هستند. در این نمودار بالا، دقت (آبی)، فراخوانی (قرمز) و F-beta (سبز، با β = 1 به طور پیش‌فرض) در آستانه‌های طبقه‌بندی مختلف نشان داده شده‌اند، به همراه یک خط نقطه‌چین عمودی که آستانه فعلی را برای برجسته کردن بده‌بستان نشان می‌دهد. این تجسم‌ها نه تنها برای تشخیص فنی، بلکه برای پشتیبانی از بحث‌های پیرامون انتخاب آستانه با متخصصان حوزه نیز مفید هستند (بعداً در مورد بهینه‌سازی آستانه بیشتر صحبت خواهیم کرد).

=== Classification Model Evaluation ===

1. Evaluation Parameters
----------------------------------------
• Threshold:   0.500    (Classification cutoff)
• Beta:        1.000    (F-beta weight parameter)

2. Core Performance Metrics
----------------------------------------
• Accuracy:    0.805    (Overall correct predictions)
• AUC:         0.876    (Ranking quality)
• Log Loss:    0.464    (Confidence-weighted error)
• Precision:   0.838    (True positives / Predicted positives)
• Recall:      0.703    (True positives / Actual positives)
• F1 Score:    0.765    (Harmonic mean of Precision & Recall)
• MCC:         0.608    (Matthews Correlation Coefficient)

3. Prediction Distribution
----------------------------------------
• Pos Rate:    0.378    (Fraction of positive predictions)
• Base Rate:   0.450    (Actual positive class rate)

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

=== Regression Model Evaluation ===

1. Error Metrics
----------------------------------------
• RMSE:         0.460      (Root Mean Squared Error)
• MAE:          0.305      (Mean Absolute Error)
• Median AE:    0.200      (Median Absolute Error)
• NRMSE Mean:   22.4%      (RMSE/mean)
• NRMSE Std:    40.2%      (RMSE/std)
• NRMSE IQR:    32.0%      (RMSE/IQR)
• MAPE:         17.7%      (Mean Abs % Error, excl. zeros)
• SMAPE:        15.9%      (Symmetric Mean Abs % Error)

2. Goodness of Fit
----------------------------------------
• R²:           0.839      (Coefficient of Determination)
• Adj. R²:      0.838      (Adjusted for # of features)

3. Improvement over Baseline
----------------------------------------
• vs Mean:      59.8%      (RMSE improvement)
• vs Median:    60.9%      (RMSE improvement)

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

تشخیص رگرسیون

⚠️ هشدارهای نسبت نمونه به ویژگی: هشدارهایی که n/k < 10 را نشان می‌دهند، که نشان‌دهنده ریسک بالای بیش‌برازش است.
ℹ️شفافیت MAPE: گزارش می‌دهد که چه تعداد مشاهده به دلیل مقادیر هدف صفر از MAPE حذف شده‌اند.

طبقه‌بندی تشخیصی

⚠️ تشخیص نشت داده‌ها: AUC نزدیک به کامل (>99٪) را که اغلب نشان‌دهنده نشت است، علامت‌گذاری می‌کند.
⚠️ هشدارهای بیش‌برازش: همان هشدارهای نسبت n/k مانند رگرسیون.
ℹ️آگاهی از عدم تعادل کلاس: توزیع‌های کلاسی به شدت نامتوازن را علامت‌گذاری می‌کند.

در زیر خلاصه‌ای از گزارش‌های ارزیابی MLarena برای هر دو وظیفه طبقه‌بندی و رگرسیون آمده است:

قابلیت توضیح در پروژه‌های یادگیری ماشین به دلایل مختلف بسیار مهم است:

  1. انتخاب مدل
    قابلیت توضیح‌پذیری با فراهم کردن امکان ارزیابی صحت استدلال مدل، به ما در انتخاب بهترین مدل کمک می‌کند. حتی اگر دو مدل معیارهای عملکرد مشابهی را نشان دهند، بررسی ویژگی‌هایی که به آنها متکی هستند توسط متخصصان حوزه می‌تواند نشان دهد که منطق کدام مدل با درک دنیای واقعی همسوتر است.
  2. عیب‌یابی
    تحلیل استدلال یک مدل، یک استراتژی عیب‌یابی قدرتمند برای بهبود است. برای مثال، با بررسی اینکه چرا یک مدل طبقه‌بندی با اطمینان اشتباه کرده است، می‌توانیم ویژگی‌های مؤثر را مشخص کرده و استدلال آن را اصلاح کنیم.
  3. نظارت بر مدل،
    فراتر از بررسی‌های معمول عملکرد و انحراف داده‌ها، نظارت بر استدلال مدل بسیار آموزنده است. آگاه شدن از تغییرات قابل توجه در ویژگی‌های کلیدی که تصمیمات یک مدل تولید را هدایت می‌کنند، به حفظ قابلیت اطمینان و مرتبط بودن آن کمک می‌کند.
  4. پیاده‌سازی مدل
    ارائه استدلال مدل در کنار پیش‌بینی‌ها می‌تواند برای کاربران نهایی فوق‌العاده ارزشمند باشد. به عنوان مثال، یک نماینده خدمات مشتری می‌تواند از امتیاز ریزش به همراه ویژگی‌های خاص مشتری که منجر به آن امتیاز می‌شود، برای حفظ بهتر مشتری استفاده کند.

برای پشتیبانی از تفسیرپذیری مدل، این explain_modelروش توضیحات کلی به شما می‌دهد و نشان می‌دهد کدام ویژگی‌ها بیشترین تأثیر را بر پیش‌بینی‌های مدل شما دارند.

mlpipeline.explain_model(X_test)

این explain_caseروش توضیحات محلی برای موارد خاص ارائه می‌دهد و به ما کمک می‌کند تا بفهمیم چگونه هر ویژگی در هر پیش‌بینی خاص نقش دارد.

mlpipeline.explain_case(5)

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

برای کاهش این اصطکاک، MLPipelineبه عنوان یک مدل سفارشی پیاده‌سازی می‌شود mlflow.pyfunc. این انتخاب طراحی اجازه می‌دهد تا کل خط لوله (شامل مراحل پیش‌پردازش و مدل آموزش‌دیده) به عنوان یک مصنوع واحد و قابل حمل بسته‌بندی شود.

هنگام ارزیابی یک خط لوله، می‌توانید با تنظیم موارد زیر، ثبت وقایع MLflow را فعال کنید log_model=True:

results = mlpipeline.evaluate(
    X_test, y_test, 
    log_model=True # to log the pipeline with mlflow
)

در پشت صحنه، این باعث ایجاد یک سری عملیات MLflow می‌شود:

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

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

۲. تنظیم مدل‌ها با در نظر گرفتن کارایی و پایداری

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

برای پرداختن به این مسائل، MLarena tuneروشی را در نظر گرفته است که فرآیند بهینه‌سازی ابرپارامتر را ساده می‌کند و در عین حال، استحکام و شفافیت را ارتقا می‌دهد. این روش بر اساس بهینه‌سازی بیزی – یک استراتژی جستجوی کارآمد که بر اساس نتایج قبلی سازگار می‌شود – ساخته شده و محافظ‌هایی را برای جلوگیری از مشکلات رایج مانند بیش‌برازش یا پوشش ناقص فضای جستجو اضافه می‌کند.

در اینجا مثالی از نحوه اجرای تنظیم با استفاده از LightGBM و یک فضای جستجوی سفارشی آورده شده است:

from mlarena import MLPipeline, PreProcessor
import lightgbm as lgb

lgb_param_ranges = {
    'learning_rate': (0.01, 0.1),  
    'n_estimators': (100, 1000),   
    'num_leaves': (20, 100),
    'max_depth': (5, 15),
    'colsample_bytree': (0.6, 1.0),
    'subsample': (0.6, 0.9)
}

# setting up with default settings, see customization below 
best_pipeline = MLPipeline.tune(
    X_train, 
    y_train,
    algorithm=lgb.LGBMClassifier, # works with any sklearn style algorithm
    preprocessor=PreProcessor(),
    param_ranges=lgb_param_ranges 
    )

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

best_pipeline = MLPipeline.tune(
    ... 
    max_evals=500,       # maximum optimization iterations
    early_stopping=50,   # stop if no improvement after 50 trials
    n_startup_trials=5,  # minimum trials before early stopping kicks in
    n_warmup_steps=0,    # steps per trial before pruning    
    )

برای اطمینان از نتایج قوی، MLarena در طول تنظیم هایپرپارامتر، اعتبارسنجی متقابل را اعمال می‌کند. این ابزار علاوه بر بهینه‌سازی برای عملکرد متوسط، به شما امکان می‌دهد واریانس بالا را در بین foldها با استفاده از cv_variance_penaltyپارامتر جریمه کنید. این امر به ویژه در سناریوهای دنیای واقعی که پایداری مدل می‌تواند به اندازه دقت خام مهم باشد، ارزشمند است.

best_pipeline = MLPipeline.tune(
    ...
    cv=5,                    # number of folds for cross-validation
    cv_variance_penalty=0.3, # penalize high variance across folds
    )

برای مثال، بین دو مدل با میانگین AUC یکسان، مدلی که واریانس کمتری در بین چین‌ها دارد، اغلب در تولید قابل اعتمادتر است. این مدل به دلیل امتیاز مؤثر بهترش، که برابر است با mean_auc - std * cv_variance_penalty:، توسط تنظیم MLarena انتخاب خواهد شد.

مدل میانگین AUC بیماری های مقاربتی امتیاز مؤثر
الف ۰.۸۵ ۰.۰۲ ۰.۸۵ – ۰.۰۲ *
۰.۳ (پنالتی)
ب ۰.۸۵ ۰.۱۰ ۰.۸۵ – ۰.۱۰ *
۰.۳ (پنالتی)

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

برای پشتیبانی از طراحی جستجوی آگاهانه‌تر، MLarena یک نمودار مختصات موازی را در نظر گرفته است که چگونگی ارتباط مقادیر مختلف هایپرپارامتر با عملکرد مدل را به تصویر می‌کشد:

  • شما می‌توانید روندها را تشخیص دهید ، مثلاً اینکه کدام محدوده‌ها learning_rateبه طور مداوم نتایج بهتری می‌دهند.
  • شما می‌توانید خوشه‌بندی لبه‌ای را شناسایی کنید ، که در آن آزمایش‌های با عملکرد بالا در مرز یک محدوده پارامتر جمع می‌شوند، که اغلب نشانه‌ای از نیاز به تنظیم محدوده است.
  • شما می‌توانید تعاملات بین چندین ابرپارامترها را مشاهده کنید، که به اصلاح شهود شما یا هدایت کاوش‌های بیشتر کمک می‌کند.

این نوع تجسم به کاربران کمک می‌کند تا فضاهای جستجو را به صورت تکراری اصلاح کنند و با تکرارهای کمتر به نتایج بهتری برسند.

best_pipeline = MLPipeline.tune(
    ...
    # to show parallel coordinate plot:
    visualize = True # default=True
    )

هدف از تنظیم همیشه یکسان نیست: در برخی موارد، شما می‌خواهید AUC را به حداکثر برسانید، در برخی دیگر، ممکن است بیشتر به حداقل رساندن RMSE یا SMAPE اهمیت دهید. اما معیارهای مختلف به جهت‌های بهینه‌سازی متفاوتی نیز نیاز دارند – و هنگامی که با جریمه واریانس اعتبارسنجی متقابل ترکیب می‌شوند، که بسته به جهت بهینه‌سازی، یا باید به میانگین CV اضافه شود یا از آن کم شود، محاسبات می‌تواند خسته‌کننده شود.😅

MLarena با پشتیبانی از طیف گسترده‌ای از معیارها برای طبقه‌بندی و رگرسیون، این کار را ساده می‌کند:

معیارهای طبقه‌بندی:

  • auc(پیش‌فرض)
  • f1
  • accuracy
  • log_loss
  • mcc

معیارهای رگرسیون:

  • rmse(پیش‌فرض)
  • mae
  • median_ae
  • smape
  • nrmse_mean، nrmse_iqr،nrmse_std

برای تغییر معیارها، کافیست tune_metricبه متد زیر ارسال کنید:

best_pipeline = MLPipeline.tune(
    ...
    tune_metric = "f1"
    )

MLarena بقیه کارها را انجام می‌دهد، به طور خودکار تعیین می‌کند که آیا معیار باید حداکثر یا حداقل شود و جریمه واریانس را به طور مداوم اعمال می‌کند.

۳. مقابله با چالش‌های پیش‌پردازش در دنیای واقعی

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

MLarena PreProcessorطوری طراحی شده است که این مرحله را قوی‌تر و کمتر موردی کند. این نرم‌افزار پیش‌فرض‌های معقولی را برای موارد استفاده رایج ارائه می‌دهد، در حالی که انعطاف‌پذیری و ابزار لازم برای سناریوهای پیچیده‌تر را نیز فراهم می‌کند.

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

from mlarena import PreProcessor

preprocessor = PreProcessor(
    num_impute_strategy="median",          # Numeric missing value imputation
    cat_impute_strategy="most_frequent",   # Categorical missing value imputation
    target_encode_cols=None,               # Columns for target encoding (optional)
    target_encode_smooth="auto",           # Smoothing for target encoding
    drop="if_binary",                      # Drop strategy for one-hot encoding
    sanitize_feature_names=True            # Clean up special characters in column names
)

X_train_prep = preprocessor.fit_transform(X_train)
X_test_prep = preprocessor.transform(X_test)

این پیش‌فرض‌ها اغلب برای تکرار سریع کافی هستند. اما مجموعه داده‌های دنیای واقعی به ندرت به طور کامل با پیش‌فرض‌ها مطابقت دارند. بنابراین بیایید برخی از وظایف پیش‌پردازش ظریف‌تری که PreProcessorپشتیبانی می‌کنند را بررسی کنیم.

ویژگی‌های دسته‌بندی با کاردینالیتی بالا یک چالش ایجاد می‌کنند: کدگذاری سنتی وان-هات می‌تواند منجر به صدها ستون پراکنده شود. کدگذاری هدف یک جایگزین فشرده ارائه می‌دهد و دسته‌ها را با میانگین‌های هموار شده متغیر هدف جایگزین می‌کند. با این حال، تنظیم پارامتر هموارسازی دشوار است: هموارسازی خیلی کم منجر به بیش‌برازش می‌شود، در حالی که هموارسازی خیلی زیاد سیگنال مفید را رقیق می‌کند.

MLarena رویکرد تجربی مبتنی بر بیز را در SKLearn TargetEncoderبرای هموارسازی زمانی اتخاذ می‌کند که target_encode_smooth="auto"، و همچنین به کاربران اجازه می‌دهد مقادیر عددی را مشخص کنند ( به سند sklearn TargetEncoder و Micci-Barrec، ۲۰۰۱ مراجعه کنید ).

preprocessor = PreProcessor(
    target_encode_cols=['city'],
    target_encode_smooth='auto'
)

برای کمک به هدایت این انتخاب، این plot_target_encoding_comparisonروش نشان می‌دهد که چگونه مقادیر هموارسازی مختلف بر کدگذاری دسته‌های نادر تأثیر می‌گذارند. برای مثال:

PreProcessor.plot_target_encoding_comparison(
    X_train, y_train,
    target_encode_col='city',
    smooth_params=['auto', 10, 20]
)

این امر به ویژه برای بررسی تأثیر بر روی دسته‌های کمتر نمایش داده شده (مثلاً شهری مانند «سیاتل» با تنها ۲۴ نمونه) مفید است. این تجسم نشان می‌دهد که پارامترهای هموارسازی مختلف منجر به تفاوت‌های قابل توجهی در مقدار کدگذاری شده سیاتل می‌شوند. چنین تصاویر واضحی به متخصصان داده و کارشناسان حوزه در داشتن بحث‌های معنادار و تصمیم‌گیری آگاهانه در مورد بهترین استراتژی کدگذاری کمک می‌کند.

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

این filter_feature_selectionروش به فیلتر کردن موارد زیر کمک می‌کند:

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

نحوه کار آن به این صورت است:

filter_fs = PreProcessor.filter_feature_selection(
    X_train,
    y_train,
    task='classification', # or 'regression'
    missing_threshold=0.2, # drop features with > 20% missing values
    mi_threshold=0.05,     # drop features with low mutual information
)

این خلاصه‌ای مانند زیر را برمی‌گرداند:

Filter Feature Selection Summary:
==========
Total features analyzed: 7

1. High missing ratio (>20.0%): 0 columns

2. Single value: 1 columns
   Columns: occupation

3. Low mutual information (<0.05): 3 columns
   Columns: age, tenure, occupation

Recommended drops: (3 columns in total)

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

selected_cols = fitler_fs['selected_cols']
X_train_selected = X_train[selected_cols]

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

وقتی کدگذاری وان-هات (one-hot encoding) روی ویژگی‌های دسته‌بندی‌شده اعمال می‌شود، نام ستون‌ها می‌توانند کاراکترهای خاصی مانند 'age_60+'یا را به ارث ببرند 'income_<$30K'. این کاراکترها می‌توانند خطوط لوله را در پایین‌دست، به‌ویژه هنگام ثبت وقایع، استقرار یا استفاده با MLflow، از کار بیندازند.

برای کاهش خطر خرابی‌های خاموش خط لوله، MLarena به طور خودکار و پیش‌فرض نام ویژگی‌ها را پاکسازی می‌کند:

preprocessor = PreProcessor(sanitize_feature_names=True)

کاراکترهایی مانند +، <، و % با جایگزین‌های امنی مطابق جدول زیر جایگزین شده‌اند که سازگاری با ابزارهای تولید را بهبود می‌بخشد. کاربرانی که نام‌های خام را ترجیح می‌دهند، می‌توانند به راحتی با تنظیم این رفتار را غیرفعال کنند sanitize_feature_names=False.

۴. حل چالش‌های روزمره در تمرین یادگیری ماشینی

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

مدل‌های طبقه‌بندی دودویی اغلب احتمالات را خروجی می‌دهند، اما تصمیمات دنیای واقعی نیاز به یک آستانه‌ی مشخص برای جداسازی مثبت‌ها از منفی‌ها دارند. این انتخاب بر دقت، فراخوانی و در نهایت، نتایج کسب‌وکار تأثیر می‌گذارد. با این حال، در عمل، آستانه‌ها اغلب در مقدار پیش‌فرض ۰.۵ باقی می‌مانند، حتی زمانی که با نیازهای دامنه همسو نباشند.

روش MLarena threshold_analysisبه دقیق‌تر و متناسب‌تر شدن این انتخاب کمک می‌کند. ما می‌توانیم:

  • تعادل دقت-فراخوانی را از طریق پارامتر بتا در امتیاز F-beta سفارشی کنید
  • با به حداکثر رساندن F-beta، آستانه طبقه‌بندی بهینه را بر اساس اهداف تجاری خود پیدا کنید.
  • برای تخمین‌های قوی و قابل اعتماد، از بوت‌استرپ یا اعتبارسنجی متقاطع k-fold طبقه‌بندی‌شده استفاده کنید.
# Perform threshold analysis using bootstrap method
results = MLPipeline.threshold_analysis(  
    y_train,                     # True labels for training data
    y_pred_proba,                # Predicted probabilities from model
    beta = 0.8,                  # F-beta score parameter (weights precision more than recall)
    method = "bootstrap",        # Use bootstrap resampling for robust results
    bootstrap_iterations=100)    # Number of bootstrap samples to generate

# utilize the optimal threshold identified on new data
best_pipeline.evaluate(
    X_test, y_test, beta=0.8, 
    threshold=results['optimal_threshold']
    )

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

مصورسازی‌های قوی نه تنها برای EDA، بلکه برای مشارکت ذینفعان و اعتبارسنجی یافته‌ها نیز ضروری هستند. MLarena شامل مجموعه‌ای از ابزارهای ترسیم است که برای تفسیرپذیری و وضوح طراحی شده‌اند.

۴.۲.۱ مقایسه توزیع‌ها در بین گروه‌ها

هنگام تجزیه و تحلیل داده‌های عددی در دسته‌های متمایز مانند مناطق، گروه‌های سنی یا گروه‌های درمانی، درک جامع به چیزی بیش از معیارهای گرایش مرکزی مانند میانگین یا میانه نیاز دارد. درک پراکندگی داده‌ها و شناسایی هرگونه داده پرت نیز بسیار مهم است. برای پرداختن به این موضوع، plot_box_scatterتابع Mlarena نمودارهای جعبه‌ای را با نقاط پراکندگی نامنظم همپوشانی می‌کند و اطلاعات توزیع غنی را در یک تجسم واحد و شهودی ارائه می‌دهد.

علاوه بر این، تکمیل بینش‌های بصری با تحلیل آماری قوی اغلب بسیار ارزشمند است. بنابراین، تابع رسم نمودار به صورت اختیاری آزمون‌های آماری مانند ANOVA، Welch’s ANOVA و Kruskal-Wallis را ادغام می‌کند و به ما این امکان را می‌دهد که نمودارهای خود را با نتایج آزمون آماری، همانطور که در زیر نشان داده شده است، حاشیه‌نویسی کنیم. 

import mlarena.utils.plot_utils as put

fig, ax, results = put.plot_box_scatter(
    data=df,
    x="item",
    y="value",
    title="Boxplot with Scatter Overlay (Demo for Crowded Data)",
    point_size=2,
    xlabel=" ",
    stat_test="anova",      # specify a statistical test
    show_stat_test=True
    )

روش‌های زیادی برای سفارشی‌سازی نمودار وجود دارد – یا با تغییر axشیء برگردانده شده یا با استفاده از پارامترهای داخلی تابع. برای مثال، می‌توانید نقاط را با استفاده از point_hueپارامتر، بر اساس متغیر دیگری رنگ‌آمیزی کنید.

fig, ax = put.plot_box_scatter(
    data=df,
    x="group",
    y="value",
    point_hue="source", # color points by source
    point_alpha=0.5,
    title="Boxplot with Scatter Overlay (Demo for Point Hue)",
)

۴.۲.۲ تجسم توزیع زمانی

متخصصان داده و کارشناسان حوزه مربوطه اغلب نیاز دارند که مشاهده کنند توزیع یک متغیر پیوسته چگونه در طول زمان تکامل می‌یابد تا تغییرات بحرانی، روندهای نوظهور یا ناهنجاری‌ها را تشخیص دهند.

این اغلب شامل وظایف تکراری و خسته‌کننده‌ای مانند جمع‌آوری داده‌ها بر اساس جزئیات زمانی دلخواه (ساعتی، هفتگی، ماهانه و غیره)، اطمینان از ترتیب زمانی صحیح و سفارشی‌سازی ظاهرها، مانند رنگ‌آمیزی نقاط بر اساس متغیر سوم مورد نظر، می‌شود. plot_distribution_over_timeتابع ما این پیچیدگی‌ها را به راحتی مدیریت می‌کند.

# automatically group data and format X-axis lable by specified granularity
fig, ax = put.plot_distribution_over_time(
    data=df,
    x='timestamp',
    y='heart_rate',
    freq='h',                                   # specify granularity
    point_hue=None,                             # set a variable to color points if desired
    title='Heart Rate Distribution Over Time',
    xlabel=' ',
    ylabel='Heart Rate (bpm)',
)

دموهای بیشتر از توابع رسم نمودار و مثال‌ها در مستندات plot_utils موجود است 🔗

اگر مثل من باشید، احتمالاً قبل از رسیدن به بخش‌های جذاب یادگیری ماشین، زمان زیادی را صرف تمیز کردن و عیب‌یابی داده‌ها می‌کنید. 😅داده‌های دنیای واقعی اغلب نامرتب، ناسازگار و پر از شگفتی هستند. به همین دلیل است که MLarena مجموعه‌ای رو به رشد از data_utilsتوابع را برای ساده‌سازی و روان‌سازی فرآیند EDA و آماده‌سازی داده‌ها در نظر گرفته است.

۴.۳.۱ اصلاح قالب‌های تاریخ ناسازگار

ستون‌های تاریخ همیشه با فرمت‌های ISO و تمیز ارائه نمی‌شوند و قالب‌بندی یا فرمت‌های نامتناسب می‌توانند واقعاً دردسرساز باشند. این transform_date_colsتابع به استانداردسازی ستون‌های تاریخ برای تحلیل‌های بعدی کمک می‌کند، حتی زمانی که مقادیر فرمت‌های نامنظمی مانند موارد زیر داشته باشند:

import mlarena.utils.data_utils as dut

df_raw = pd.DataFrame({
    ...
    "date": ["25Aug2024", "15OCT2024", "01Dec2024"],  # inconsistent casing
})

# transformed the specified date columns
df_transformed = dut.transform_date_cols(df_raw, 'date', "%d%b%Y")
df_transformed['date']
# 0   2024-08-25
# 1   2024-10-15
# 2   2024-12-01

این به طور خودکار تغییرات حروف بزرگ و کوچک را مدیریت می‌کند و ستون را به اشیاء تاریخ و زمان مناسب تبدیل می‌کند.

اگر گاهی اوقات کدهای قالب تاریخ پایتون را فراموش می‌کنید یا آنها را با کدهای اسپارک اشتباه می‌گیرید، تنها نیستید 😁. فقط کافیست برای یادآوری سریع، docstring تابع را بررسی کنید.

?dut.transform_date_cols  # check for docstring
Signature:
----------
dut.transform_date_cols(
    data: pandas.core.frame.DataFrame,
    date_cols: Union[str, List[str]],
    str_date_format: str = '%Y%m%d',
) -> pandas.core.frame.DataFrame
Docstring:
Transforms specified columns in a Pandas DataFrame to datetime format.

Parameters
----------
data : pd.DataFrame
    The input DataFrame.
date_cols : Union[str, List[str]]
    A column name or list of column names to be transformed to dates.
str_date_format : str, default="%Y%m%d"
    The string format of the dates, using Python's `strftime`/`strptime` directives.
    Common directives include:
        %d: Day of the month as a zero-padded decimal (e.g., 25)
        %m: Month as a zero-padded decimal number (e.g., 08)
        %b: Abbreviated month name (e.g., Aug)
        %B: Full month name (e.g., August)
        %Y: Four-digit year (e.g., 2024)
        %y: Two-digit year (e.g., 24)

۴.۳.۲ تأیید کلیدهای اصلی در داده‌های نامرتب

شناسایی یک کلید اصلی معتبر می‌تواند در مجموعه داده‌های دنیای واقعی و به‌هم‌ریخته چالش‌برانگیز باشد. در حالی که یک کلید اصلی سنتی ذاتاً باید در تمام ردیف‌ها منحصر به فرد باشد و هیچ مقدار از دست رفته‌ای نداشته باشد، ستون‌های کلید بالقوه اغلب حاوی مقادیر تهی هستند، به‌ویژه در مراحل اولیه یک خط لوله داده.

این is_primary_keyتابع یک رویکرد عملگرایانه برای این چالش اتخاذ می‌کند: کاربر را از هرگونه مقدار از دست رفته در ستون‌های کلیدی بالقوه مطلع می‌کند و سپس تأیید می‌کند که آیا ردیف‌های غیر تهی باقی مانده به طور منحصر به فرد قابل شناسایی هستند یا خیر.

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

– ارزیابی کیفیت داده‌ها : ارزیابی سریع کامل بودن و منحصر به فرد بودن فیلدهای کلیدی ما.
– آمادگی برای اتصال : شناسایی کلیدهای قابل اعتماد برای ادغام مجموعه داده‌ها، حتی زمانی که برخی از مقادیر در ابتدا وجود ندارند.
– اعتبارسنجی ETL : تأیید محدودیت‌های کلیدی در عین در نظر گرفتن نقص‌های داده‌های دنیای واقعی.
– طراحی طرحواره : برنامه‌ریزی قوی طرحواره پایگاه داده را با بینش‌های مشتق شده از ویژگی‌های کلیدی داده‌های واقعی، اطلاع‌رسانی کنید.

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

df = pd.DataFrame({
    # Single column primary key
    'id': [1, 2, 3, 4, 5],    
    # Column with duplicates
    'category': ['A', 'B', 'A', 'B', 'C'],    
    # Date column with some duplicates
    'date': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02', '2024-01-03'],
    # Column with null values
    'code': ['X1', None, 'X3', 'X4', 'X5'],    
    # Values column
    'value': [100, 200, 300, 400, 500]
})

print("\nTest 1: Column with duplicates")
dut.is_primary_key(df, ['category'])  # Should return False

print("\nTest 2: Column with null values")
dut.is_primary_key(df, ['code','date']) # Should return True
Test 1: Column with duplicates
✅ There are no missing values in column 'category'.
ℹ️ Total row count after filtering out missings: 5
ℹ️ Unique row count after filtering out missings: 3
❌ The column(s) 'category' do not form a primary key.

Test 2: Column with null values
⚠️ There are 1 row(s) with missing values in column 'code'.
✅ There are no missing values in column 'date'.
ℹ️ Total row count after filtering out missings: 4
ℹ️ Unique row count after filtering out missings: 4
🔑 The column(s) 'code', 'date' form a primary key after removing rows with missing values.

فراتر از آنچه که پوشش دادیم، این data_utilsماژول ابزارهای مفید دیگری نیز ارائه می‌دهد، از جمله مجموعه‌ای اختصاصی از سه تابع برای گردش کار حذف داده‌های تکراری «کشف → بررسی → حل»، که در بالا مورد بحث قرار گرفت، به عنوان گام اولیه عمل می‌کند. جزئیات بیشتر در نسخه آزمایشی data_utilsis_primary_key موجود است . 🔗

فهرست مطالب

پیمایش به بالا