XGBoost for Return Direction: Class Imbalance and Decision Thresholds

Return-direction classifiers are imbalanced problems, and 0.5 is the wrong decision threshold. Comparing scale_pos_weight, focal loss, and precision-constrained threshold optimization on crypto data - plus the engineering differences between XGBoost, LightGBM, and CatBoost.

درّب مصنفا للتنبؤ بما إذا كان عائد الساعة التالية يتجاوز ‎+0.5%‎، وستكتشف أنك لم تبن مسألة ثنائية متوازنة. في فترات هدوء العملات المشفرة، تقع 70--80% من الأشرطة تحت العتبة، ولذلك يستطيع النموذج تسجيل دقة 75% من دون توقع أي نتيجة موجبة. الدقة عديمة الفائدة هنا. وكذلك حد القرار الافتراضي 0.5، الذي لم يختره أحد عمدا — فهو ببساطة القيمة التي تستخدمها predict().

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

يقيس هذا المقال الطرق الثلاث على الطيات نفسها للتحقق المتحرك إلى الأمام بعد التطهير، باستخدام بيانات BTC وETH الساعية، ثم يتناول نتيجتين تترتبان على ذلك: لماذا يمثل min_child_weight عتبة لهسيان وليس عددا للصفوف (ولهذا تتغير قيمته المناسبة عند إعادة وزن الخسارة)، وأين تختلف XGBoost وLightGBM وCatBoost فعليا من الناحية الهندسية.

النهجالدقةالاستدعاءالصفقاتصافي الربح بعد التكاليفSharpe منكمش
خط الأساس (بلا تصحيح، thr=0.5)—————
scale_pos_weight = n_neg/n_pos—————
الخسارة البؤرية (γ=2, α=0.25)—————
تحسين العتبة (الحد الأدنى للدقة 0.55)—————

الطيات والميزات ونموذج التكاليف نفسها لكل صف. جرى تقليص Sharpe بسبب عدد الإعدادات المجربة، وفق Sharpe المنكمش والاختبارات المتعددة، بينما تتبع التكاليف نماذج الانزلاق والتكلفة.

معالجة اختلال الفئات في التنبؤ بالعوائد

حقل إشارة التنبؤ بالعوائد المتوازنة

النهج 1: scale_pos_weight

أبسط طريقة هي ضبط scale_pos_weight = n_negative / n_positive:

n_pos = y_train.sum()
n_neg = len(y_train) - n_pos
scale_pos_weight = n_neg / n_pos  # e.g., 3.0 if 75% negative

model = xgb.XGBClassifier(
    scale_pos_weight=scale_pos_weight,
    ...
)

يُكبّر هذا تدرج عينات الفئة الموجبة، ويخبر النموذج بأن تصنيف مثال موجب خطأ أسوأ kk مرات من تصنيف مثال سالب خطأ.

من السهل تفويت الأثر الجانبي: فهو يكبّر أيضا هسيانات الدالة. وبما أن min_child_weight عتبة على مجموع الهسيانات في الورقة (انظر أدناه)، فإن إعادة وزن الخسارة تغير بصمت مدى شدة انقسام الشجرة. فقيمة min_child_weight المضبوطة عند scale_pos_weight=1 لا تعني الشيء نفسه عند scale_pos_weight=3. أعد ضبط الاثنين معا، لا بالتتابع.

الأثر الجانبي الثاني أن احتمالات الخرج لا تعود معايرة. تعيد predict_proba قيمة رتيبة في الاحتمال الحقيقي لكنها لا تساويه، مما يجعل أي تحجيم لاحق للمراكز مبنيا على هذه الأرقام خاطئا.

النهج 2: الخسارة البؤرية

تخفض الخسارة البؤرية وزن الأمثلة السهلة بغض النظر عن الفئة، وتركز التدريب على العينات الصعبة والملتبسة. وهذا إطار جذاب للتنبؤ بالعوائد، حيث يكون الحد بين شريط +0.5% وشريط +0.4% ضجيجا في الغالب — مع أن "التركيز على الحالات الملتبسة" و"التركيز على الحالات غير القابلة للتعلم" هما التعليمات نفسها عندما تكون التسميات بهذا القدر من الضجيج، ولهذا يجب القياس لا الافتراض.

FL(pt)=−αt(1−pt)γlog⁡(pt)\text{FL}(p_t) = -\alpha_t (1 - p_t)^{\gamma} \log(p_t)

حيث إن ptp_t هو الاحتمال المتوقع للفئة الحقيقية، وαt\alpha_t يوازن أوزان الفئات، وγ\gamma (عادة 1--3) يتحكم في شدة تخفيض وزن الأمثلة السهلة.

def focal_loss_objective(y_true, y_pred, gamma=2.0, alpha=0.25):
    """
    Custom focal loss for XGBoost. Returns gradient and hessian.
    """
    p = 1.0 / (1.0 + np.exp(-y_pred))  # sigmoid

    g1 = alpha * y_true * (1 - p)**gamma * (gamma * p * np.log(p + 1e-9) + p - 1)
    g2 = (1 - alpha) * (1 - y_true) * p**gamma * (
        -gamma * (1 - p) * np.log(1 - p + 1e-9) - p
    )
    grad = -(g1 + g2)

    # NOTE: this is NOT the second derivative of focal loss. It is the
    # logistic Hessian form p(1-p) evaluated on `grad`, used as a positive
    # surrogate. It keeps the Newton step well-defined but changes the
    # effective step size, and therefore the meaning of min_child_weight.
    hess = np.maximum(grad * (1 - grad), 1e-6)

    return grad, hess


model = xgb.XGBClassifier(objective=focal_loss_objective, ...)

تحتاج الأهداف المخصصة إلى تدرج وهسيان موجب حتى تكون صيغة وزن الورقة خطوة هبوط. المشتق الثاني الدقيق للخسارة البؤرية ليس موجبا في كل المواضع، ولذلك تلجأ التطبيقات إلى بديل — لكن البديل الذي يختلف بعامل مقياس يغير أحجام الخطوات، ومن خلال مجموع الهسيان يغير ما الذي تقصه min_child_weight. وحده جدول المقارنة يبين ما إذا كان ذلك يكلف شيئا عمليا.

النهج 3: تحسين العتبة

اترك الخسارة كما هي، ودرب نموذجا معايرا، ثم حرك عتبة القرار على مجموعة التحقق:

from sklearn.metrics import precision_recall_curve

def optimize_threshold(y_true, y_proba, min_precision=0.55):
    """
    Find the threshold maximizing F1 subject to a minimum precision.
    """
    precisions, recalls, thresholds = precision_recall_curve(y_true, y_proba)
    f1_scores = 2 * (precisions * recalls) / (precisions + recalls + 1e-9)

    valid = precisions[:-1] >= min_precision
    if not valid.any():
        return 0.5  # fallback

    best_idx = np.argmax(f1_scores[:-1] * valid)
    return thresholds[best_idx]

أرضية الدقة هي ما يهم التداول. تعظيم F1 وحده يبادل الدقة بالاستدعاء، وهو ما يعني من ناحية صافي الربح مزيدا من الصفقات الهامشية التي تدفع السبريد كل مرة. إن تقييد الدقة وتعظيم الاستدعاء تحت هذا القيد يترجم إلى "تداول أقل، لكن مع الصواب عند التداول".

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

لماذا min_child_weight هو مجموع هسيان لا عدد صفوف

انقسام شجرة مدعوم بالانحناء

يبني التعزيز بالتدرج مجموعة إضافية. عند الخطوة tt يضيف شجرة ftf_t تقلل هدفا منظما، وتقربه XGBoost بتوسع تايلور من الرتبة الثانية:

L(t)≈∑i=1n[gift(xi)+12hift2(xi)]+Ω(ft)\mathcal{L}^{(t)} \approx \sum_{i=1}^{n} \Bigl[ g_i f_t(\mathbf{x}_i) + \frac{1}{2} h_i f_t^2(\mathbf{x}_i) \Bigr] + \Omega(f_t)

مع gi=∂l/∂y^i(t−1)g_i = \partial l / \partial \hat{y}_i^{(t-1)}، وhi=∂2l/∂(y^i(t−1))2h_i = \partial^2 l / \partial (\hat{y}_i^{(t-1)})^2، و

Ω(f)=γT+12λ∑j=1Twj2\Omega(f) = \gamma T + \frac{1}{2}\lambda \sum_{j=1}^{T} w_j^2

حيث إن TT هو عدد الأوراق، وwjw_j وزن الورقة، وγ\gamma عقوبة كل ورقة، وλ\lambda حد L2. ويعطي حل وزن الورقة الأمثل wj∗=−∑i∈jgi/(∑i∈jhi+λ)w_j^* = -\sum_{i \in j} g_i / (\sum_{i \in j} h_i + \lambda).

يوجد مجموع الهسيان في المقام، وهذه هي النقطة. يضع min_child_weight عتبة على ذلك المجموع، لا على عدد الصفوف في الورقة. في الخسارة اللوغاريتمية، hi=pi(1−pi)h_i = p_i(1 - p_i)، وهو أكبر ما يكون عند p=0.5p = 0.5 وينهار نحو الصفر كلما اقتربت التنبؤات من اليقين. لذلك تقص ورقة مليئة بأشرطة مصنفة بثقة بسبب مجموع هسيان صغير، بينما قد تبقى ورقة تحتوي على عدد قليل من الأشرطة الملتبسة فعليا.

بالنسبة إلى التسميات المالية المشوشة، هذا هو السلوك المطلوب، وهو يفسر النتائج العملية:

  • رفع min_child_weight يقص الأوراق القائمة على ملاحظات قليلة غير مؤكدة — وهي بالضبط الأكثر عرضة لمواءمة الضجيج. وهذا أدق من عد الصفوف على طريقة min_child_samples.
  • أي شيء يعيد تحجيم الخسارة يعيد تحجيم الهسيانات. فـscale_pos_weight والأهداف المخصصة وأوزان العينات كلها تغير min_child_weight الفعلي، رغم أن الرقم الذي كتبته لم يتغير.
  • مع استمرار التعزيز وازدياد حدة التنبؤات، تنكمش الهسيانات عالميا، ولذلك تقص قيمة min_child_weight الثابتة بقوة أكبر في الجولات اللاحقة. وهذا أثر تلدين مدمج، وهو سبب اختلاف معدلات التعلم المنخفضة مع عدد أكبر من الأشجار عن خطوات أقل وأكبر.

إن min_child_samples في LightGBM هو عدد صفوف، أي معلمة مختلفة فعلا رغم تشابه الاسم. ونظيره القائم على الهسيان هو min_sum_hessian_in_leaf. إن نقل الإعداد بين المكتبتين بمطابقة الأسماء طريقة شائعة لتغيير النموذج خطأ.

XGBoost مقابل LightGBM مقابل CatBoost: الفروق الهندسية

ثلاثة هياكل لتعزيز التدرج

تنفذ المكتبات الثلاث أشجار قرار معززة بالتدرج. الاختلافات في بناء الشجرة، وهي التي تظهر فعليا في زمن التدريب ونتيجة خارج العينة.

XGBoost ينمو مستوى بمستوى (من الاتساع إلى العمق): تقسم جميع الأوراق عند عمق معين قبل الانتقال إلى عمق أكبر. ينتج هذا أشجارا متوازنة، ويجعل max_depth أداة ذات معنى للتحكم في التعقيد، ويجعل الضبط أكثر قابلية للتنبؤ. لكنه يهدر العمل أيضا في تقسيم أوراق لم يعد فيها الكثير من الخسارة القابلة للتقليل.

LightGBM ينمو ورقة بورقة: يقسم الورقة التي تقدم أكبر خفض للخسارة، أيا كان موضعها. تصل انقسامات أقل إلى خسارة التدريب نفسها، لكن الأشجار تصبح عميقة وغير متوازنة، لذلك يتوقف max_depth عن كونه أداة التحكم الصحيحة — وتصبح num_leaves هي الأداة. وهناك حيلتان إضافيتان تقودان سرعته:

  • GOSS (أخذ عينات أحادي الجانب قائم على التدرج) يحتفظ بكل الحالات ذات التدرج الكبير، ويأخذ عينة عشوائية من الحالات ذات التدرج الصغير، مع زيادة أوزان الناجين لإبقاء تقدير التدرج غير متحيز. في البيانات المالية، الحالات ذات التدرج الكبير هي الأشرطة التي يخطئ فيها النموذج حاليا — وهي أيضا حيث يوجد ضجيج التسميات، لذلك يركز GOSS أخذ العينات حيث يكون الضجيج أسوأ. يجدر فحصه مقابل أخذ العينات العادي بدلا من افتراض تفوقه.
  • EFB (تجميع الميزات الحصرية) يحزم الميزات المتناثرة والمتنافية في ميزة واحدة ضمن فضاء الصناديق. وهو فعال في ترميزات one-hot، وعديم الفائدة تقريبا في الميزات المستمرة الكثيفة، وهي معظم مصفوفة الميزات الفنية.

CatBoost ينمو أشجارا متماثلة (غافلة): يستخدم كل عقدة عند عمق معين شرط الانقسام نفسه. وهذا منظم قوي ويجعل الاستدلال سريعا جدا — إذ تصبح الشجرة بحثا في فهرس — على حساب القدرة التعبيرية لكل شجرة. وآليتاه المميزتان هما:

  • التعزيز المرتب. يحسب التعزيز العادي البواقي لعينة باستخدام نموذج درب على تلك العينة، فيحرف الباقي — وهو "تحول التنبؤ". يقدر CatBoost البواقي لكل عينة باستخدام نموذج ملائم فقط للعينات السابقة لها في تبديل عشوائي. والبنية مناسبة طبيعيا للتفكير في السلاسل الزمنية، وتهم أكثر عندما تكون البيانات محدودة.
  • إحصاءات الهدف المرتبة للترميز الفئوي، إذ تحسب إحصاءات الهدف من العينات السابقة فقط، وتتجنب تسرب الهدف الذي يسببه ترميز المتوسط الساذج. وهذا هو السبب الصادق لاستخدام CatBoost عندما تحمل مجموعة الميزات تسميات للمنصة أو فئة الأصل أو النظام.
الخاصيةXGBoostLightGBMCatBoost
نمو الشجرةمستوى بمستوىورقة بورقةمتماثل (غافل)
أداة التعقيدmax_depthnum_leavesdepth
حارس حجم الورقةmin_child_weight (هسيان)min_child_samples (صفوف)min_data_in_leaf (صفوف)
الميزات الفئويةترميز يدويدعم أساسيأصلي، TS مرتب
التنظيمL1/L2 + gammaL1/L2 + num_leavesL2 + قوة عشوائية
الخسارة المخصصةمرنةمرنةمحدودة نسبيا
زمن التدريب، هذه البيانات——
خسارة OOS، الطيات نفسها——

الأسطر الوصفية حقائق عن المكتبات. أما السطران الأخيران فهما الوحيدان اللذان يجيبان عن سؤال "أي مكتبة أستخدم؟"، ولا بد أن يأتي الجواب من تشغيل على بياناتك — فعادة ما تكون الفروق بين التطبيقات المضبوطة جيدا صغيرة بما يكفي لأن شكل مجموعة البيانات هو الذي يحسم.

تبديل المكتبات في الغالب مجرد إعادة تسمية. دالة تدريب واحدة، مع إدراج المعلمات المختلفة بدلا من تكرارها:

import xgboost as xgb

def train_xgb_model(X_train, y_train, X_val, y_val, class_weight_ratio=1.0):
    """Train XGBoost classifier for return direction prediction."""
    model = xgb.XGBClassifier(
        n_estimators=2000,
        max_depth=5,
        learning_rate=0.01,
        subsample=0.7,
        colsample_bytree=0.7,
        min_child_weight=10,   # Hessian sum, not row count
        gamma=1.0,
        reg_alpha=0.1,
        reg_lambda=1.0,
        scale_pos_weight=class_weight_ratio,
        objective='binary:logistic',
        eval_metric='logloss',
        tree_method='hist',
        random_state=42,
        early_stopping_rounds=50,
    )
    model.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=False)
    return model
المفهومXGBoostLightGBMCatBoost
عدد الأشجارn_estimatorsn_estimatorsiterations
عقوبة L2reg_lambdareg_lambdal2_leaf_reg
أخذ عينات الأعمدةcolsample_bytreecolsample_bytreersm
اختلال الفئاتscale_pos_weightscale_pos_weightauto_class_weights='Balanced'
الإيقاف المبكرearly_stopping_roundsرد نداء lgb.early_stopping()early_stopping_rounds

أهمية SHAP عبر الطيات بوصفها كاشفا لتلاشي ألفا

تلاشي إسناد الميزات عبر الطيات

يغطي المدونة بالفعل SHAP على نموذج تعزيز بالتدرج — TreeExplainer ومخططات الملخص وكيفية قراءتها. ما لم يُغطَّ هو استخدام SHAP طوليا: مفسر واحد لكل طية من طيات المشي إلى الأمام، مع تتبع متوسط الإسناد المطلق لكل ميزة عبر الزمن.

def shap_over_time(models, test_sets, feature_names) -> pd.DataFrame:
    """
    Track SHAP-based feature importance across walk-forward folds.
    Rows are folds, columns are features.
    """
    importance_over_time = []
    for fold_idx, (model, X_test) in enumerate(zip(models, test_sets)):
        explainer = shap.TreeExplainer(model)
        shap_values = explainer.shap_values(X_test)
        mean_abs_shap = np.abs(shap_values).mean(axis=0)
        importance_over_time.append(
            pd.Series(mean_abs_shap, index=feature_names, name=fold_idx)
        )
    return pd.DataFrame(importance_over_time)

الخرج مصفوفة طيات × ميزات، وتظهر فيها ثلاثة أشكال مميزة:

  1. انخفاض رتيب — ميزة تتلاشى ميزتها. مرشحة للحذف أو للتحقيق في ما تغير في بنية السوق.
  2. تباين مرتفع بلا اتجاه — ميزة ضجيج يتعلق بها النموذج في بعض الأنظمة. وهذه الإشارة نفسها التي يقيسها تحليل الهضبة للمعلمات، مطبقة هنا على الميزات.
  3. تغير مرحلي بسبب النظام — تهبط الأهمية عند طية محددة وتبقى منخفضة. وغالبا ما يمكن ربط ذلك بحدث في منصة أو إدراج أو هيكل رسوم، لا بتلاشي ألفا.

الفخ أن SHAP المطلق المتوسط لا يقارن بين الطيات عندما تتغير ثقة النموذج العامة: فالنموذج الذي يتنبأ بقيم أقرب إلى 0.5 في كل مكان ينتج إسنادات أصغر لكل ميزة دفعة واحدة. طبّع أهمية كل طية بحيث يكون مجموعها 1 قبل المقارنة، حتى تقرأ تحولات الأهمية النسبية لا تحولات الثقة.

لماذا الأشجار، باختصار

شجرة قرار في مشهد سوق غير خطي

اختبر Grinsztajn وOyallon وVaroquaux (NeurIPS 2022) مجموعات الأشجار مقابل التعلم العميق عبر 45 مجموعة بيانات جدولية، وعزلوا ثلاث خصائص بنيوية تفضل الأشجار — وهي تصف البيانات المالية كلها:

  1. دوال هدف غير منتظمة. العوائد ليست ملساء؛ فيها انقطاعات وتغيرات أنظمة وتأثيرات عتبة. تلتقط الانقسامات المحاذية للمحاور هذه الخصائص من دون تقريب سطح أملس.
  2. ميزات غير مفيدة. يولد خط أنابيب ألفا مئات المرشحين ومعظمها ضجيج. تختار الأشجار في كل انقسام؛ بينما توزع الشبكات العصبية سعتها على كل المدخلات وتنفق المعلمات على الضجيج.
  3. عدم الثبات الدوراني. الحجم ليس قابلا للاستبدال بالتقلب. الشبكات العصبية ثابتة دورانيا افتراضيا، فتعامل التركيبات الخطية للميزات كأنها مكافئة للأصول — وهذا خطأ ببساطة للميزات ذات المعنى الدلالي المختلف.

بالنسبة إلى الجانب العملي لهذه المفاضلة — حجم البيانات، وزمن الاستجابة، وجهد هندسة الميزات، وقابلية التفسير، والتكيف مع الأنظمة — يملك المدونة بالفعل جدول قرار كاملا في نمذجة السبريد بالتعلم الآلي.

هندسة الميزات

تحول إشارات السوق إلى ميزات

import pandas as pd
import numpy as np

def build_features(df: pd.DataFrame) -> pd.DataFrame:
    """
    Build trading features from OHLCV data.

    Expects columns: open, high, low, close, volume, timestamp
    """
    feat = pd.DataFrame(index=df.index)

    # --- Price-based features ---
    feat['return_1'] = df['close'].pct_change(1)
    feat['return_5'] = df['close'].pct_change(5)
    feat['return_15'] = df['close'].pct_change(15)
    feat['return_60'] = df['close'].pct_change(60)

    # Realized volatility (rolling std of returns)
    log_ret = np.log(df['close'] / df['close'].shift(1))
    feat['volatility_20'] = log_ret.rolling(20).std()
    feat['volatility_60'] = log_ret.rolling(60).std()
    feat['vol_ratio'] = feat['volatility_20'] / feat['volatility_60']

    # Range-based volatility (Parkinson)
    feat['parkinson_vol'] = np.sqrt(
        (1 / (4 * np.log(2)))
        * (np.log(df['high'] / df['low']) ** 2).rolling(20).mean()
    )

    # --- Volume features ---
    feat['volume_sma_ratio'] = df['volume'] / df['volume'].rolling(20).mean()
    feat['volume_std_20'] = df['volume'].rolling(20).std()
    feat['obv'] = (np.sign(df['close'].diff()) * df['volume']).cumsum()
    feat['obv_slope'] = feat['obv'].diff(5) / feat['obv'].shift(5)

    # --- Microstructure features ---
    feat['high_low_range'] = (df['high'] - df['low']) / df['close']
    feat['close_position'] = (df['close'] - df['low']) / (df['high'] - df['low'])
    feat['gap'] = df['open'] / df['close'].shift(1) - 1

    # --- Momentum indicators ---
    delta = df['close'].diff()
    gain = delta.clip(lower=0).rolling(14).mean()
    loss = (-delta.clip(upper=0)).rolling(14).mean()
    feat['rsi_14'] = 100 - 100 / (1 + gain / loss)

    ema_12 = df['close'].ewm(span=12).mean()
    ema_26 = df['close'].ewm(span=26).mean()
    feat['macd'] = (ema_12 - ema_26) / df['close']
    feat['macd_signal'] = feat['macd'].ewm(span=9).mean()
    feat['macd_hist'] = feat['macd'] - feat['macd_signal']

    # --- Mean reversion features ---
    for window in [10, 20, 50]:
        sma = df['close'].rolling(window).mean()
        feat[f'distance_sma_{window}'] = (df['close'] - sma) / sma
        std = df['close'].rolling(window).std()
        feat[f'bb_position_{window}'] = (df['close'] - sma) / (2 * std)

    return feat

كل ميزة أعلاه سببية بحكم بنائها — عمليات متحركة وموسعة فقط، بلا إحصاءات على العينة كلها. وهذا مقصود: توحيد القياس على السلسلة كلها هو التسرب الأكثر شيوعا في هذا النوع من خطوط الأنابيب، وتأثيره في Sharpe المبلغ عنه مقاس في تصنيف انحياز النظر إلى المستقبل.

نطاقات المعلمات الفائقة لـ XGBoost على البيانات المالية

مدارات المعلمات الفائقة حول سطح معزز

الهدف ليس أقصى أداء داخل العينة، بل أقصى استقرار خارج العينة. التنظيم أولا، والتعقيد ثانيا:

المعلمةالنطاق المعتادالغرض
max_depth3--7يحد ترتيب التفاعلات. الأشجار الأعمق تنمذج تفاعلات أعلى رتبة لكنها تفرط في المواءمة أسرع. ابدأ بـ 4.
min_child_weight5--100الحد الأدنى لمجموع الهسيان في الورقة. أعد ضبطه كلما غيرت scale_pos_weight أو الهدف.
learning_rate0.005--0.05الانكماش. القيم الأقل تحتاج إلى أشجار أكثر لكنها تعمم أفضل.
subsample0.5--0.8أخذ عينات من الصفوف لكل شجرة. يضيف عشوائية ويقلل فرط المواءمة.
colsample_bytree0.5--0.8أخذ عينات من الأعمدة لكل شجرة. مهم مع كثرة الميزات المترابطة.
gamma0.5--5.0الحد الأدنى لخفض الخسارة من أجل انقسام. يعمل كعتبة تقليم.
reg_alpha (L1)0.01--1.0L1 على أوزان الأوراق. يشجع التناثر.
reg_lambda (L2)0.1--10.0L2 على أوزان الأوراق. يمنع قيم الأوراق الكبيرة.

بالنسبة إلى إجراء البحث نفسه — TPE، واستمرار الدراسة، ولماذا يتفوق البحث البايزي على الانحدار الإحداثي — انظر Optuna مقابل الانحدار الإحداثي. ويجب نقل عدد التجارب الذي تستخدمه هناك إلى تقليص Sharpe بعد ذلك.

ما يتركه هذا المقال عمدا للمقالات الأخرى

بوابات حدود البحث

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

تُذكر ثلاثة مخاطر إضافية هنا بوصفها فرضيات لا نتائج: انحياز البقاء الناتج عن التدريب على الأصول المدرجة فقط؛ وعدم استقرارية أهداف العوائد الخام، حيث قد تتصرف العوائد المتبقية من بيتا على نحو أفضل؛ ودورية إعادة التدريب، حيث يكون تشخيص SHAP عبر الطيات مراقب الانجراف الطبيعي.

الخلاصة

مشهد قرار معزز محسوم

تصنيف اتجاه العوائد مسألة مختلة الفئات، مع عتبة قرار لم يخترها أحد، والإصلاحات الثلاثة المعيارية ليست متبادلة. إن scale_pos_weight سطر واحد، لكنه يزيل معايرة الاحتمالات ويحرك min_child_weight بصمت. والخسارة البؤرية تحتاج إلى هسيان تقربه معظم التطبيقات. أما تحسين العتبة فيترك النموذج كما هو ويضع القيد المهم للتداول — الدقة — في موضعه الصحيح، لكن فقط إذا أعيد ضبط العتبة لكل طية على بيانات تأتي بعد التدريب.

أيها يفوز سؤال تجريبي عن بياناتك وعتبتك ونموذج تكلفتك. الجدول في الأعلى هو الإجابة لمجموعة بيانات واحدة؛ وتشغيله على بياناتك يكلف أقل من وقت الضبط الذي تنفقه في التخمين.


قراءات إضافية: