ML Learning Hub
تطبيقيمتوسط

ضبط المعاملات الفائقة

أتمتة فن إيجاد المعاملات الصحيحة للضبط

البحث الشبكي والبحث العشوائي والتحسين البايزي والتنصيف المتتالي وOptuna — إيجاد أفضل تهيئة للنموذج دون الإفراط في ملاءمة مجموعة التحقق.

40 min
9 مخططات
7 المفاهيم المغطاة

المتطلبات الأساسية

Model Evaluation
Gradient Boosting

المفاهيم المغطاة

GridSearchCVRandomizedSearchCVBayesian OptimisationOptunaSuccessive HalvingCV ScoreOverfitting to Validation

الصيغ الرئيسية

بحث الشبكة

بحث شامل على جميع التركيبات في الشبكة المحددة مسبقاً

التنصيف المتتالي

استبعاد المرشحين الضعفاء تدريجياً مع تخصيص موارد أكثر للواعدين

التحسين المتوقع

دالة الاكتساب للتحسين البايزي — توازن الاستكشاف مقابل الاستغلال

محاكاة تفاعلية

Loading visualization…
🎯

لماذا تهم المعاملات الفائقة

motivation

غابة عشوائية مع max_depth=5 قد تسجل 0.72 AUC. نفس الخوارزم مع max_depth=12 وmin_samples_leaf=3 وmax_features='sqrt' يسجل 0.89 AUC. هذا الفارق البالغ 17 نقطة هو ضبط معاملات فائقة خالص — لم يتغير الخوارزم ولا البيانات. المعاملات الفائقة هي معاملات لا تُتعلَّم من البيانات؛ تتحكم في عملية التعلم نفسها. اختيارها جيداً غالباً هو الفرق بين نموذج متوسط ونموذج جاهز للإنتاج.

معدل التعلم هو أهم معامل فائق مفرد في معظم النماذج القائمة على التدرج. مرتفع جداً = تباعد. منخفض جداً = تقارب بطيء أو حدود دنيا محلية. اضبطه أولاً.

⚖️

شبكة مقابل عشوائي مقابل بايزي

comparison

تقيّم بحث الشبكة كل تركيبة في الجداء الديكارتي لقيم المعاملات — صحيح لكن مكلف أُسّياً. يأخذ البحث العشوائي n_iter تركيبات عشوائية — فعّال بشكل مفاجئ لأن معظم فضاءات المعاملات الفائقة لها بُعد فعلي قليل؛ العينات العشوائية تُغطيها بشكل أفضل من الشبكات. يحتفظ التحسين البايزي بنموذج احتمالي للسطح الهدف ويقترح تسلسلياً تهيئات تُعظِّم التحسين المتوقع — يتعلم من التقييمات السابقة ويتمركز حول المناطق الواعدة.

البحث العشوائي مع n_iter=60 يتفوق عادةً على بحث الشبكة مع 5× تقييمات أكثر. التحسين البايزي يتفوق على كليهما عند تكلف التقييمات (مثل تدريب شبكة عصبية كبيرة).

⚙️

حلقة التحسين البايزي

algorithm
1

ضبط نموذج بديل (عملية غاوسية) على الملاحظات السابقة (θ، الدرجة)

2

استخدام دالة الاكتساب (التحسين المتوقع، UCB) لاختيار θ التالي

3

TE: استكشاف حيث عدم اليقين مرتفع أو حيث الكسب المتوقع مرتفع

4

تقييم الهدف الفعلي: تدريب النموذج مع θ، حساب درجة التحقق المتقاطع

5

إضافة الملاحظة الجديدة لمجموعة البيانات، إعادة ضبط النموذج البديل

6

التكرار حتى نفاد الميزانية — إرجاع أفضل θ وُجد

🔬

البحث بالتنصيف: السرعة بلا تضحية

deepdive

تُنفِّذ HalvingGridSearchCV وHalvingRandomSearchCV التنصيف المتتالي: البدء بجميع المرشحين لكن موارد دنيا، الاحتفاظ بالكسر η الأعلى، مضاعفة الموارد، التكرار. شبكة من 1024 مرشحاً مع 4 جولات تنصيف تحتاج فقط 4096 تقييماً إجمالياً مقابل 1024×كل شيء لـGridSearchCV القياسي. هذا يعطي تسريعاً 10-100× لشبكات كبيرة مع فقدان جودة ضئيل.

للشبكات العصبية، استخدم Keras Tuner أو Optuna بدلاً من بحث sklearn — يدعمان التجارب المتوازية غير المتزامنة وتكامل التوقف المبكر وفضاءات البحث الخاصة بالشبكات.

</>

الأساليب الثلاثة في scikit-learn

code
python56 lines
from sklearn.model_selection import (GridSearchCV, RandomizedSearchCV,
                                       cross_val_score, train_test_split)
from sklearn.experimental import enable_halving_search_cv  class="tok-comment"># noqa
from sklearn.model_selection import HalvingRandomSearchCV
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import make_classification
from scipy.stats import uniform, randint
import optuna  class="tok-comment"># for Bayesian

class="tok-comment"># ── Sample data ────────────────────────────────────────────────────────
X, y = make_classification(n_samples=class="tok-num">600, n_features=class="tok-num">10, random_state=class="tok-num">42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=class="tok-num">0.2, random_state=class="tok-num">42)

class="tok-comment"># ── Parameter space ────────────────────────────────────────────────
param_grid = {
    class="tok-str">'n_estimators':     [class="tok-num">100, class="tok-num">200, class="tok-num">400],
    class="tok-str">'max_depth':        [class="tok-num">3, class="tok-num">5, class="tok-num">7, class="tok-num">9],
    class="tok-str">'learning_rate':    [class="tok-num">0.01, class="tok-num">0.05, class="tok-num">0.1, class="tok-num">0.2],
    class="tok-str">'subsample':        [class="tok-num">0.7, class="tok-num">0.8, class="tok-num">1.0],
    class="tok-str">'min_samples_leaf': [class="tok-num">1, class="tok-num">3, class="tok-num">5],
}

class="tok-comment"># ── class="tok-num">1. Grid Search (exhaustive, expensive) ─────────────────────────
gs = GridSearchCV(GradientBoostingClassifier(), param_grid,
                  cv=class="tok-num">5, scoring=class="tok-str">'roc_auc', n_jobs=-class="tok-num">1)
gs.fit(X_train, y_train)
print(fclass="tok-str">"Grid best: {gs.best_score_:.4f}  {gs.best_params_}")

class="tok-comment"># ── class="tok-num">2. Random Search (fast, almost-as-good) ────────────────────────
param_dist = {
    class="tok-str">'n_estimators':     randint(class="tok-num">50, class="tok-num">500),
    class="tok-str">'max_depth':        randint(class="tok-num">2, class="tok-num">12),
    class="tok-str">'learning_rate':    uniform(class="tok-num">0.005, class="tok-num">0.3),
    class="tok-str">'subsample':        uniform(class="tok-num">0.6, class="tok-num">0.4),
}
rs = RandomizedSearchCV(GradientBoostingClassifier(), param_dist,
                        n_iter=class="tok-num">60, cv=class="tok-num">5, scoring=class="tok-str">'roc_auc',
                        n_jobs=-class="tok-num">1, random_state=class="tok-num">42)
rs.fit(X_train, y_train)
print(fclass="tok-str">"Random best: {rs.best_score_:.4f}  {rs.best_params_}")

class="tok-comment"># ── class="tok-num">3. Optuna (Bayesian, best quality) ─────────────────────────────
def objective(trial):
    params = {
        class="tok-str">'n_estimators':   trial.suggest_int(class="tok-str">'n_estimators', class="tok-num">50, class="tok-num">500),
        class="tok-str">'max_depth':      trial.suggest_int(class="tok-str">'max_depth', class="tok-num">2, class="tok-num">12),
        class="tok-str">'learning_rate':  trial.suggest_float(class="tok-str">'learning_rate', class="tok-num">1e-3, class="tok-num">0.3, log=True),
        class="tok-str">'subsample':      trial.suggest_float(class="tok-str">'subsample', class="tok-num">0.5, class="tok-num">1.0),
    }
    model = GradientBoostingClassifier(**params)
    return cross_val_score(model, X_train, y_train, cv=class="tok-num">3, scoring=class="tok-str">'roc_auc').mean()

study = optuna.create_study(direction=class="tok-str">'maximize')
study.optimize(objective, n_trials=class="tok-num">100, n_jobs=class="tok-num">4)
print(fclass="tok-str">"Optuna best: {study.best_value:.4f}  {study.best_params}")
⚠️

مزالق ضبط المعاملات الفائقة

pitfall

الضبط على مجموعة الاختبار يُضخِّم تقديرات الأداء — دائماً اضبط باستخدام التحقق المتقاطع على بيانات التدريب فحسب. الثاني: التحقق المتقاطع المتداخل ضروري للتقدير غير المنحاز عند تطبيق اختيار النموذج وضبط المعاملات معاً. الثالث: 'لعنة الفائز' — مع 1000 تهيئة عشوائية، أفضلها ستكون متفائلة بالصدفة. استخدم مجموعة محتجزة للتحقق. الرابع: لا تضبط كل شيء معاً — ثبّت معدل التعلم أولاً ثم التنظيم ثم البنية.

الإفراط في التعلم على مجموعة التحقق حقيقي. مع ما يكفي من تجارب المعاملات، ستجد تهيئةً تُسجِّل جيداً عرضاً على أطواق التحقق لكن تُعمِّم بشكل سيئ. دائماً أجرِ تقييماً نهائياً على مجموعة اختبار محتجزة حقاً.

?اختبار المعرفة

يتم حفظ التقدم في متصفحك — لا حاجة لحساب.

تحتاج مهندس ذكاء اصطناعي أو عالم بيانات؟

أبني نماذج تعلم آلي مخصصة، ووكلاء ذكاء اصطناعي، ورؤية حاسوب، وأتمتة — من الفكرة إلى الإنتاج.