Machine Learning 📂 Supervised Learning · 19 of 19 216 min read

XGBoost Explained

A deep-dive into XGBoost covering the algorithm internals, all key hyperparameters, and four tuning strategies — Grid Search, Random Search, Optuna, and Bayesian Optimisation

🌐
SectionSection第 01 节

The Story That Explains XGBoostवह कहानी जो XGBoost समझाती है一个解释 XGBoost 的故事

The Kaizen Factory — Getting Better One Mistake at a TimeKaizen Factory — हर गलती के साथ थोड़ा बेहतर改善工厂 — 每次从一个错误中进步
Picture a car factory that never throws a bad part away. Every shift starts by studying yesterday's defects. Worker One fixes 70% of the problems. Worker Two does not start fresh: she looks only at what Worker One got wrong and fixes 70% of those. Worker Three does the same with what is still left. After twenty workers, almost no error remains (0.3²⁰ ≈ 0.000000003 of it).

This is gradient boosting, the idea behind XGBoost. Each model is not independent: each one corrects the leftover errors of the ones before it. XGBoost (eXtreme Gradient Boosting) is the engineering that makes this fast, regularised against overfitting, and very accurate.
एक car factory की कल्पना करें जो कभी खराब part नहीं फेंकती। हर shift कल की खामियों को पढ़कर शुरू होती है। Worker One 70% समस्याएँ ठीक करता है। Worker Two नए सिरे से शुरू नहीं करती: वह सिर्फ़ वह देखती है जो Worker One ने गलत छोड़ा, और उनमें से 70% ठीक करती है। Worker Three बचे हुए के साथ यही करता है। बीस workers के बाद लगभग कोई error नहीं बचती (0.3²⁰ ≈ 0.000000003 हिस्सा)।

यही gradient boosting है, XGBoost के पीछे का विचार। हर model independent नहीं है: हर एक अपने से पहले वालों की बची हुई errors ठीक करता है। XGBoost (eXtreme Gradient Boosting) वह engineering है जो इसे तेज़, overfitting के ख़िलाफ़ regularised, और बहुत सटीक बनाती है।
想象一家从不丢弃坏零件的汽车工厂。每个班次都从研究昨天的缺陷开始。第一位工人修好 70% 的问题。第二位工人不是从头开始,她只看第一位工人没修好的部分,并修好其中的 70%。第三位工人对剩下的问题做同样的事。经过二十位工人后,几乎没有误差剩下(只剩 0.3²⁰ ≈ 0.000000003)。

这就是 XGBoost 背后的思想:梯度提升。每个 model 都不是独立的,每一个都在修正前面所有 model 留下的误差。XGBoost(eXtreme Gradient Boosting)是让这个过程变得快速、带正则化防止过拟合、并且非常准确的工程实现。

XGBoost was created by Tianqi Chen in 2014 and led Kaggle leaderboards for years. It is still one of the strongest tools for tabular data. It combines gradient boosting with regularisation, missing-value handling and fast parallel computation.

XGBoost को Tianqi Chen ने 2014 में बनाया और यह सालों तक Kaggle leaderboards पर आगे रहा। Tabular data के लिए यह अब भी सबसे मज़बूत tools में से एक है। यह gradient boosting को regularisation, missing values संभालने और तेज़ parallel computation के साथ जोड़ता है।

XGBoost 由陈天奇于 2014 年创建,多年来一直领跑 Kaggle 排行榜,至今仍是处理表格数据最强的工具之一。它把梯度提升与正则化、缺失值处理和快速的并行计算结合在一起。

🌿
The Core Idea in One Sentenceएक वाक्य में मुख्य विचार一句话核心思想

XGBoost builds decision trees one after another. Each new tree fits the negative gradient of the loss left by all the earlier trees, and adds a small correction to the prediction.

XGBoost decision trees एक के बाद एक बनाता है। हर नया tree पिछले सभी trees के बाद बचे loss के negative gradient को fit करता है, और prediction में एक छोटा सुधार जोड़ता है।

XGBoost 一棵接一棵地构建决策树。每棵新树拟合前面所有树留下的 loss 负梯度,并给预测加上一个小小的修正。


SectionSection第 02 节

XGBoost in Pictures — Understand It Before the Mathsतस्वीरों में XGBoost — गणित से पहले समझें图解 XGBoost — 先理解,再学数学

Before any formula, here is the whole idea in four pictures. If you understand these, the rest of the page is just details.

किसी भी formula से पहले, पूरा विचार चार तस्वीरों में। अगर ये समझ आ गईं, तो बाकी page सिर्फ़ details है।

在任何公式之前,先用四张图讲清楚整个思想。看懂了这些,页面其余部分只是细节。

🖼️ PICTURE 1 — ONE TREE vs A TEAM OF TREESतस्वीर 1 — एक TREE vs TREES की TEAM图 1 — 一棵树 vs 一队树
Boosting as a team of trees ONE TREE = A FLOWCHART OF QUESTIONSएक TREE = सवालों का FLOWCHART一棵树 = 一张问题流程图 Size > 120 m²?Size > 120 m²?面积 > 120 m²? noनहीं否yesहाँ是 ₹40 L ₹75 L Easy to read, but too rough alone.पढ़ना आसान, पर अकेले बहुत मोटा अनुमान।容易看懂,但单独用太粗糙。 XGBOOST = A TEAM: EACH TREE FIXES THE LAST MISTAKEXGBOOST = एक TEAM: हर TREE पिछली गलती ठीक करता हैXGBOOST = 一个团队:每棵树修正上一个错误 ₹60L Start: averageशुरुआत: average起点:平均值 +18 Tree 1Tree 1树 1 -6 Tree 2Tree 2树 2 +3 Tree 3Tree 3树 3 ₹75L FinalFinal最终 true price ₹76 Lअसली कीमत ₹76 L真实价格 ₹76 L Prediction = average + tree 1 + tree 2 + tree 3 + … (each correction is small)Prediction = average + tree 1 + tree 2 + tree 3 + … (हर सुधार छोटा है)预测 = 平均值 + 树 1 + 树 2 + 树 3 + …(每次修正都很小)

A single tree gives a rough answer. XGBoost starts from the average and adds many small trees. Each new tree only tries to fix what is still wrong.

एक अकेला tree मोटा जवाब देता है। XGBoost average से शुरू करके बहुत सारे छोटे trees जोड़ता है। हर नया tree सिर्फ़ वह ठीक करने की कोशिश करता है जो अभी भी गलत है।

单独一棵树只能给出粗略的答案。XGBoost 从平均值出发,加上很多小树。每棵新树只负责修正仍然错误的部分。

LIVELIVE互动Picture 2 — Watch Boosting Build a Model, One Tree at a Timeतस्वीर 2 — Boosting को एक-एक tree से model बनाते देखें图 2 — 看 Boosting 一棵树一棵树地构建 model

Top: the data (green dots) and the current prediction (blue line). Bottom: the mistakes that are still left (red bars). Each new tree looks only at the red bars, fits a small staircase to them (orange), and adds a fraction of it to the blue line.

ऊपर: data (हरे dots) और मौजूदा prediction (नीली line)। नीचे: अभी बची गलतियाँ (लाल bars)। हर नया tree सिर्फ़ लाल bars देखता है, उन पर एक छोटी सीढ़ी fit करता है (नारंगी), और उसका एक हिस्सा नीली line में जोड़ता है।

上方:数据(绿点)和当前预测(蓝线)。下方:仍然存在的错误(红柱)。每棵新树只看红柱,给它们拟合一个小阶梯(橙色),再把其中一部分加到蓝线上。

TreesTrees树的数量
—
Train errorTrain error训练误差
—

Try learning_rate 0.1: each tree fixes only 10% of the mistake, so you need many more trees. Try max_depth 3: each tree asks more questions and fixes more at once.

learning_rate 0.1 आज़माएँ: हर tree गलती का सिर्फ़ 10% ठीक करता है, इसलिए बहुत ज़्यादा trees चाहिए। max_depth 3 आज़माएँ: हर tree ज़्यादा सवाल पूछता है और एक बार में ज़्यादा ठीक करता है।

试试 learning_rate 0.1:每棵树只修正 10% 的错误,所以需要多得多的树。试试 max_depth 3:每棵树问更多问题,一次修正更多。

💡
So What Is a "Gradient"?तो "Gradient" क्या है?那么"梯度"是什么?

The red bars are the "gradient" in gradient boosting. For the usual squared-error loss they are simply actual − predicted. For other losses (like log-loss for yes/no problems) the formula changes, but the idea is the same: the gradient tells each new tree which way, and how much, to push every prediction. XGBoost also uses the second derivative (the Hessian) to choose a good step size for every leaf.

लाल bars ही gradient boosting का "gradient" हैं। आम squared-error loss में ये बस असली − अनुमान हैं। दूसरे losses (जैसे हाँ/ना problems के लिए log-loss) में formula बदलता है, पर विचार वही है: gradient हर नए tree को बताता है कि हर prediction को किस तरफ़ और कितना धकेलना है। XGBoost दूसरा derivative (Hessian) भी इस्तेमाल करता है ताकि हर leaf के लिए अच्छा step size चुने।

红柱就是梯度提升中的"梯度"。对常用的平方误差 loss,它就是真实值 − 预测值。对其他 loss(比如是/否问题的 log-loss),公式会变,但思想一样:梯度告诉每棵新树把每个预测往哪个方向推、推多少。XGBoost 还使用二阶导数(Hessian)为每个叶子选择合适的步长。

Picture 3 — The Knobs (Hyperparameters) in Everyday Wordsतस्वीर 3 — Knobs (Hyperparameters) रोज़ की भाषा में图 3 — 用日常语言解释旋钮(超参数)

👥
n_estimators
how many workersकितने workers多少个工人
The number of trees in the team. Too few: mistakes are left unfixed. Too many: later trees start "fixing" noise. Early stopping finds the right number for you.
Team में trees की संख्या। बहुत कम: गलतियाँ बची रह जाती हैं। बहुत ज़्यादा: बाद के trees noise को "ठीक" करने लगते हैं। Early stopping सही संख्या खुद खोजता है।
团队里树的数量。太少:错误没修完。太多:后面的树开始"修正"噪声。Early stopping 会帮你找到合适的数量。
👣
learning_rate
size of each stepहर कदम का आकार每一步的大小
How much we trust each new tree. 0.1 means "take only 10% of its advice". Small steps need more trees but are safer, like walking carefully instead of jumping.
हर नए tree पर कितना भरोसा। 0.1 का मतलब "उसकी सलाह का सिर्फ़ 10% लें"। छोटे कदमों को ज़्यादा trees चाहिए पर वे सुरक्षित हैं, जैसे कूदने की जगह संभलकर चलना।
我们有多信任每棵新树。0.1 表示"只采纳它 10% 的建议"。小步需要更多树但更安全,就像小心走路而不是跳。
❓
max_depth
questions per treeहर tree के सवाल每棵树问几个问题
How many questions in a row one tree may ask. Depth 2 = simple rules. Depth 10 = very detailed rules that can memorise the training data.
एक tree लगातार कितने सवाल पूछ सकता है। Depth 2 = सरल नियम। Depth 10 = बहुत detailed नियम जो training data रट सकते हैं।
一棵树最多能连续问几个问题。深度 2 = 简单规则。深度 10 = 非常细的规则,可能把训练数据背下来。
🎲
subsample · colsample_bytree
each worker sees a partहर worker एक हिस्सा देखता है每个工人只看一部分
Each tree is trained on a random share of the rows (subsample) and columns (colsample). Like asking different people for advice: the team becomes less fragile.
हर tree rows (subsample) और columns (colsample) के random हिस्से पर train होता है। जैसे अलग-अलग लोगों से सलाह लेना: team कम नाज़ुक बनती है।
每棵树只用随机一部分行(subsample)和列(colsample)训练。就像向不同的人征求意见:团队变得更稳健。
🛑
reg_lambda · reg_alpha · gamma
the brakesब्रेक刹车
They stop trees from making wild corrections. lambda and alpha shrink leaf values. gamma refuses a new split unless it improves the loss by at least gamma.
ये trees को बहुत बड़े सुधार करने से रोकते हैं। lambda और alpha leaf values को छोटा करते हैं। gamma नया split तभी मानता है जब वह loss को कम से कम gamma जितना सुधारे।
它们阻止树做出过猛的修正。lambda 和 alpha 收缩叶子值;gamma 要求新分裂至少让 loss 改善 gamma,否则不分裂。
⏱️
early_stopping_rounds
the coachcoach教练
Watches a validation set after every tree. If the score has not improved for this many rounds, training stops and the best round is kept.
हर tree के बाद validation set देखता है। अगर इतने rounds तक score नहीं सुधरा, तो training रुक जाती है और best round रखा जाता है।
每加一棵树就看一次验证集。如果连续这么多轮分数都没有提高,就停止训练并保留最佳轮次。
LIVELIVE互动Knob Lab — Underfit, Good Fit, OverfitKnob Lab — Underfit, Good Fit, Overfit旋钮实验室 — 欠拟合、良好拟合、过拟合

Turn the knobs and watch the blue model curve. Green dots = training data the model sees. Orange rings = new validation data it never sees. A good model follows the dashed true pattern, not every dot.

Knobs घुमाएँ और नीला model curve देखें। हरे dots = training data जो model देखता है। नारंगी छल्ले = नया validation data जो वह कभी नहीं देखता। अच्छा model dashed असली pattern के साथ चलता है, हर dot के पीछे नहीं।

转动旋钮,观察蓝色的 model 曲线。绿点 = model 看到的训练数据;橙色圆圈 = 它从没见过的新验证数据。好的 model 跟随虚线表示的真实规律,而不是每一个点。

Presets:
Train error
—
Validation error
—

The noise in this data has variance 0.30, so no model can get validation error much below 0.3. The best settings here reach about 0.36.

इस data के noise का variance 0.30 है, इसलिए कोई भी model validation error को 0.3 से बहुत नीचे नहीं ला सकता। यहाँ सबसे अच्छी settings लगभग 0.36 तक पहुँचती हैं।

这份数据的噪声方差是 0.30,所以任何 model 的验证误差都不可能比 0.3 低太多。这里最好的参数大约能达到 0.36。

🔄 PICTURE 4 — WHAT "HYPERPARAMETER TUNING" MEANSतस्वीर 4 — "HYPERPARAMETER TUNING" का मतलब图 4 — "超参数调优"是什么意思
The tuning loop 1. Pick settings1. Settings चुनें1. 选参数 depth=4, lr=0.1 … 2. Train2. Train करें2. 训练 on 4 of 5 folds5 में से 4 folds पर在 5 折中的 4 折上 3. Score3. Score करें3. 打分 on the held-out foldबचे हुए fold पर在留出的那一折上 4. Remember4. याद रखें4. 记录 settings → scoresettings → score参数 → 分数 repeat 20–200 times, then keep the best settings20–200 बार दोहराएँ, फिर सबसे अच्छी settings रखें重复 20–200 次,然后保留最好的参数 Grid: tries a fixed list · Random: tries random points · Optuna / Bayesian: learns from step 4 where to look nextGrid: तय list आज़माता है · Random: random points · Optuna / Bayesian: step 4 से सीखता है कि आगे कहाँ देखना है网格:按固定列表尝试 · 随机:随机取点 · Optuna / 贝叶斯:从第 4 步学习下一步去哪里找 The only difference between the four strategies is step 1: how the next settings are chosen.चारों strategies में फ़र्क सिर्फ़ step 1 का है: अगली settings कैसे चुनी जाती हैं।四种策略唯一的区别在第 1 步:如何选择下一组参数。

Tuning is just this loop: try some knob settings, measure them honestly with cross-validation, remember the score, and try again.

Tuning बस यह loop है: कुछ knob settings आज़माएँ, cross-validation से ईमानदारी से मापें, score याद रखें, और फिर आज़माएँ।

调参就是这个循环:试一组旋钮设置,用交叉验证诚实地打分,记下分数,然后再试。

Finding the Best Chai Recipeसबसे अच्छी चाय की Recipe खोजना寻找最好喝的奶茶配方
You want the perfect cup of chai. You can change three things: tea leaves, sugar and boiling time. Each cup takes 10 minutes to make and taste.

Grid search makes every combination from a fixed list: 5 × 5 × 5 = 125 cups (almost 21 hours!).
Random search makes 30 cups with random amounts. It covers more different values of each ingredient for far less work.
Optuna / Bayesian tastes each cup and thinks: "the last two good cups had less sugar; let me try around there." It finds a great cup in fewer tries.

XGBoost tuning is the same: each "cup" is one model trained with cross-validation, and the "taste" is the validation score.
आपको सबसे अच्छी चाय चाहिए। आप तीन चीज़ें बदल सकते हैं: चाय पत्ती, चीनी और उबालने का समय। हर कप बनाने और चखने में 10 मिनट लगते हैं।

Grid search तय list की हर combination बनाता है: 5 × 5 × 5 = 125 कप (लगभग 21 घंटे!)।
Random search random मात्राओं के साथ 30 कप बनाता है। बहुत कम मेहनत में यह हर ingredient की ज़्यादा अलग-अलग values आज़मा लेता है।
Optuna / Bayesian हर कप चखकर सोचता है: "पिछले दो अच्छे कपों में चीनी कम थी; उसके आसपास आज़माता हूँ।" यह कम कोशिशों में बढ़िया कप खोज लेता है।

XGBoost tuning भी ऐसा ही है: हर "कप" cross-validation से train हुआ एक model है, और "स्वाद" validation score है।
你想泡出一杯完美的奶茶,可以调整三样东西:茶叶量、糖量和煮的时间。每杯从制作到品尝要 10 分钟。

网格搜索把固定列表里的每种组合都做一遍:5 × 5 × 5 = 125 杯(将近 21 小时!)。
随机搜索用随机的用量做 30 杯,花的功夫少得多,却能试到每种原料更多不同的取值。
Optuna / 贝叶斯每喝一杯都会想:"上两杯好喝的糖都比较少,我在那附近再试试。"它用更少的次数找到一杯好茶。

XGBoost 调参也是一样:每"一杯"是用交叉验证训练出的一个 model,"味道"就是验证分数。

SectionSection第 03 节

How Gradient Boosting Works — Step by StepGradient Boosting कैसे काम करता है — Step by Step梯度提升如何工作 — 逐步讲解

Before XGBoost's engineering, you need its mathematical heart: gradient boosting. Each tree is built to lower a loss function, using its gradient (the direction of fastest improvement).

XGBoost की engineering से पहले उसका गणितीय दिल समझें: gradient boosting. हर tree एक loss function को घटाने के लिए बनता है, उसके gradient (सबसे तेज़ सुधार की दिशा) की मदद से।

在了解 XGBoost 的工程实现之前,先要理解它的数学核心:梯度提升。每棵树都借助损失函数的梯度(改进最快的方向)来降低损失。

01
Start with a constant predictionएक constant prediction से शुरू करें从常数预测开始
The simplest guess: the mean of the target (regression) or the log-odds (classification). This is F₀(x).
सबसे सरल अनुमान: target का mean (regression) या log-odds (classification)। यह F₀(x) है।
最简单的猜测:目标均值(回归)或 log-odds(分类)。这就是 F₀(x)。
02
Compute pseudo-residualsPseudo-residuals निकालें计算伪残差
For each row: rᵢ = −∂L/∂F. For squared error this is simply yᵢ − ŷᵢ, the prediction error.
हर row के लिए: rᵢ = −∂L/∂F. Squared error में यह बस yᵢ − ŷᵢ है, यानी prediction error.
对每一行:rᵢ = −∂L/∂F。对平方误差,它就是 yᵢ − ŷᵢ,即预测误差。
03
Fit a new tree to themउन पर एक नया tree fit करें用新树拟合它们
Train a small tree hₘ(x) to predict the pseudo-residuals, not the original y. It learns the pattern of the current errors.
Original y नहीं, pseudo-residuals predict करने के लिए एक छोटा tree hₘ(x) train करें। यह मौजूदा errors का pattern सीखता है।
训练一棵小树 hₘ(x) 去预测伪残差,而不是原始的 y。它学的是当前误差的模式。
04
Update with a learning rateLearning rate के साथ update करें用学习率更新
Fₘ(x) = Fₘ₋₁(x) + η · hₘ(x). The learning rate η (0, 1] sets the step size. Smaller η needs more trees but usually overfits less.
Fₘ(x) = Fₘ₋₁(x) + η · hₘ(x). Learning rate η (0, 1] step का आकार तय करता है। छोटे η को ज़्यादा trees चाहिए पर यह आमतौर पर कम overfit करता है।
Fₘ(x) = Fₘ₋₁(x) + η · hₘ(x)。学习率 η ∈ (0, 1] 决定步长。η 越小需要的树越多,但通常过拟合更少。
05
Repeat M timesM बार दोहराएँ重复 M 次
Go back to step 2 with the new Fₘ(x). After M trees: F_M(x) = F₀ + η·h₁ + η·h₂ + … + η·h_M.
नए Fₘ(x) के साथ step 2 पर वापस जाएँ। M trees के बाद: F_M(x) = F₀ + η·h₁ + η·h₂ + … + η·h_M.
用新的 Fₘ(x) 回到第 2 步。M 棵树之后:F_M(x) = F₀ + η·h₁ + η·h₂ + … + η·h_M。
⚡
XGBoost's Key Improvement Over Classic Gradient BoostingClassic Gradient Boosting से XGBoost का मुख्य सुधारXGBoost 相对经典梯度提升的关键改进

Classic gradient boosting uses only the first derivative (the gradient). XGBoost uses a second-order Taylor expansion: the gradient and the Hessian (curvature). This gives each leaf a well-sized weight straight away. It also adds an explicit regularisation term Ω to the objective, which penalises complex trees from the start.

Classic gradient boosting सिर्फ़ पहला derivative (gradient) इस्तेमाल करता है। XGBoost second-order Taylor expansion इस्तेमाल करता है: gradient और Hessian (curvature)। इससे हर leaf को तुरंत सही आकार का weight मिलता है। यह objective में एक साफ़ regularisation term Ω भी जोड़ता है, जो शुरू से complex trees पर penalty लगाता है।

经典梯度提升只用一阶导数(梯度)。XGBoost 使用二阶泰勒展开:梯度和 Hessian(曲率),让每个叶子一开始就得到合适的权重。它还在目标函数中加入了显式的正则项 Ω,从一开始就惩罚复杂的树。

📊 THE BOOSTING LOOPBOOSTING LOOP提升循环
Gradient boosting loop INITIALISEशुरुआत初始化 F₀(x) = mean(y) e.g. predict 50 for allजैसे सबके लिए 50例如全部预测 50 RESIDUALSRESIDUALS残差 r = y − F(x) e.g. +20, −15, +40 …जैसे +20, −15, +40 …例如 +20, −15, +40 … FIT TREE hₘTREE hₘ FIT करें拟合树 hₘ target = r small tree, depth 3–6छोटा tree, depth 3–6小树,深度 3–6 UPDATE FF UPDATE करें更新 F Fₘ = Fₘ₋₁ + η·hₘ η = learning rateη = learning rateη = 学习率 Repeat M times — one new tree per roundM बार दोहराएँ — हर round में एक नया tree重复 M 次 — 每轮一棵新树 F_M(x) = F₀ + η·h₁ + η·h₂ + … + η·h_M

SectionSection第 04 节

The XGBoost Objective Function — Math Explained SimplyXGBoost Objective Function — आसान गणितXGBoost 目标函数 — 简单讲数学

At each boosting round, XGBoost minimises this objective:

हर boosting round में XGBoost यह objective कम करता है:

每一轮提升中,XGBoost 最小化以下目标:

Loss termLoss term损失项
L = Σᵢ l(yᵢ, ŷᵢ)
How far predictions are from the truth. MSE for regression, log-loss for classification. You choose it with objective.
Predictions सच से कितनी दूर हैं। Regression में MSE, classification में log-loss. इसे objective से चुनें।
预测离真实值有多远。回归用 MSE,分类用 log-loss,用 objective 选择。
Regularisation termRegularisation term正则项
Ω = γT + ½λ Σⱼ wⱼ² + α Σⱼ |wⱼ|
T = number of leaves, wⱼ = leaf weights. γ charges for each leaf, λ is L2 on weights, α is L1. All three keep trees simple.
T = leaves की संख्या, wⱼ = leaf weights. γ हर leaf की कीमत लेता है, λ weights पर L2, α L1. तीनों trees को सरल रखते हैं।
T = 叶子数,wⱼ = 叶子权重。γ 对每个叶子收费,λ 是权重的 L2,α 是 L1。三者都让树保持简单。
Second-order approximationSecond-order approximation二阶近似
Obj ≈ Σⱼ [Gⱼwⱼ + ½(Hⱼ + λ)wⱼ²] + γT
Gⱼ and Hⱼ are the sums of gradients gᵢ and Hessians hᵢ of the rows in leaf j. Setting the derivative to zero gives the best leaf weight w*ⱼ = −Gⱼ / (Hⱼ + λ) (for α = 0).
Gⱼ और Hⱼ, leaf j की rows के gradients gᵢ और Hessians hᵢ के जोड़ हैं। Derivative को zero रखने पर सबसे अच्छा leaf weight मिलता है: w*ⱼ = −Gⱼ / (Hⱼ + λ) (α = 0 के लिए)।
Gⱼ 和 Hⱼ 是叶子 j 中各行梯度 gᵢ 与 Hessian hᵢ 的和。令导数为零,得到最优叶子权重 w*ⱼ = −Gⱼ / (Hⱼ + λ)(α = 0 时)。
Split gainSplit gain分裂增益
Gain = ½[GL²/(HL+λ) + GR²/(HR+λ) − G²/(H+λ)] − γ
How much splitting a node improves the objective. The split is kept only if Gain > 0, so γ works as built-in pruning.
Node को split करने से objective कितना सुधरता है। Split तभी रखा जाता है जब Gain > 0 हो, इसलिए γ built-in pruning की तरह काम करता है।
分裂一个节点能让目标改善多少。只有 Gain > 0 时才保留分裂,所以 γ 起到内置剪枝的作用。
🎯
Why This Matters in Practiceव्यवहार में यह क्यों मायने रखता है为什么这在实践中很重要

Each leaf weight has a closed-form answer, w* = −G/(H+λ), so no inner optimisation is needed. λ sits in the denominator and pulls weights toward zero, which prevents extreme predictions. γ removes splits that do not pay for themselves. Try both in the calculator below.

हर leaf weight का सीधा formula है, w* = −G/(H+λ), इसलिए अंदर कोई optimisation नहीं चाहिए। λ denominator में है और weights को zero की ओर खींचता है, जिससे बहुत बड़े predictions रुकते हैं। γ उन splits को हटाता है जो अपनी कीमत नहीं चुकाते। नीचे calculator में दोनों आज़माएँ।

每个叶子权重都有闭式解 w* = −G/(H+λ),不需要内部优化。λ 在分母中,把权重拉向零,避免极端预测。γ 会去掉"不值得"的分裂。在下面的计算器里试试这两个参数。

LIVELIVE互动XGBoost Split-Gain CalculatorXGBoost Split-Gain CalculatorXGBoost 分裂增益计算器

10 houses sorted by size. Bars = residuals the next tree must fix (for MSE, g = −residual and h = 1). Move the split, change λ and γ. Thick lines = leaf weights w*. The small bars below show the gain of every possible split.

10 घर size के क्रम में। Bars = residuals जिन्हें अगले tree को ठीक करना है (MSE में g = −residual और h = 1)। Split खिसकाएँ, λ और γ बदलें। मोटी lines = leaf weights w*. नीचे की छोटी bars हर संभव split का gain दिखाती हैं।

10 套房子按面积排序。柱子 = 下一棵树要修正的残差(MSE 下 g = −残差,h = 1)。移动分裂点,调整 λ 和 γ。粗线 = 叶子权重 w*。下方小柱子显示每个可能分裂的增益。

Try λ = 10: every leaf weight shrinks toward 0. Raise γ until even the best split turns red: the tree stops growing.

λ = 10 आज़माएँ: हर leaf weight 0 की ओर सिकुड़ता है। γ को तब तक बढ़ाएँ जब तक सबसे अच्छा split भी लाल न हो जाए: tree बढ़ना बंद कर देता है।

试试 λ = 10:每个叶子权重都向 0 收缩。把 γ 调大,直到连最佳分裂也变红:树就不再生长。

📊 A WHOLE TREE — GAIN, LEAF WEIGHTS AND PRUNINGपूरा TREE — GAIN, LEAF WEIGHTS और PRUNING一整棵树 — 增益、叶子权重与剪枝
XGBoost tree with gain and pruning Age < 35 ?G = 2.0 H = 14Gain = 7.49 > 0 ✓ yesहाँ是noनहीं否 Income < 50k ?G = −7.0 H = 7Gain = 0.16 > 0 ✓ Credit < 650 ?G = 9.0 H = 7Gain = -0.16 < 0 ✗ LEAFG=−6.0 H=4w* = +1.20 LEAFG=−1.0 H=3w* = +0.25 LEAF (pruned split)G=9.0 H=7w* = -1.125 Gain below 0 → keep it as one leafGain 0 से कम → एक ही leaf रखेंGain 小于 0 → 保留为一个叶子 λ = 1, γ = 0.5. MSE loss: g = ŷ − y, h = 1 per row.

Every number follows from the formulas above. The right-hand split has Gain = −0.16 after subtracting γ, so XGBoost prunes it and keeps one leaf.

हर number ऊपर के formulas से आता है। दाईं ओर के split का Gain, γ घटाने के बाद −0.16 है, इसलिए XGBoost उसे prune करके एक leaf रखता है।

每个数字都由上面的公式算出。右侧分裂减去 γ 后的 Gain = −0.16,所以 XGBoost 把它剪掉,只保留一个叶子。


SectionSection第 05 节

What Makes XGBoost Special — Six Engineering IdeasXGBoost को क्या ख़ास बनाता है — छह Engineering IdeasXGBoost 的特别之处 — 六个工程创新

🚀
Parallel split findingParallel split finding并行寻找分裂点
tree_method='hist'
Trees are built one after another, but inside each tree the search for the best split runs in parallel across features. Features are bucketed into histograms (256 bins by default), which is the default method since XGBoost 2.0.
Trees एक के बाद एक बनते हैं, पर हर tree के अंदर सबसे अच्छे split की खोज features में parallel चलती है। Features histograms में बँटते हैं (default 256 bins), जो XGBoost 2.0 से default तरीका है।
树是一棵接一棵构建的,但每棵树内部寻找最佳分裂时会在各特征之间并行。特征会被分到直方图里(默认 256 个桶),这是 XGBoost 2.0 起的默认方式。
🧮
Second-order optimisationSecond-order optimisation二阶优化
gradient + Hessian
Uses both the gradient gᵢ and the Hessian hᵢ for each row. Leaf weights and split gains come straight from these sums.
हर row के लिए gradient gᵢ और Hessian hᵢ दोनों इस्तेमाल करता है। Leaf weights और split gains सीधे इन्हीं जोड़ों से आते हैं।
对每一行同时使用梯度 gᵢ 和 Hessian hᵢ。叶子权重和分裂增益都直接由它们的和算出。
🛡️
Built-in regularisationBuilt-in regularisation内置正则化
alpha · lambda · gamma
Three knobs: alpha (L1 on leaf weights), lambda (L2 on leaf weights) and gamma (minimum gain for a split). Together with sampling, they make overfitting easier to control than in plain GBDT.
तीन knobs: alpha (leaf weights पर L1), lambda (leaf weights पर L2) और gamma (split के लिए न्यूनतम gain)। Sampling के साथ मिलकर ये overfitting को साधारण GBDT से आसानी से नियंत्रित करने देते हैं।
三个旋钮:alpha(叶子权重的 L1)、lambda(叶子权重的 L2)和 gamma(分裂的最小增益)。配合抽样,它们让过拟合比普通 GBDT 更容易控制。
❓
Sparsity-aware splitsSparsity-aware splits稀疏感知分裂
missing valuesmissing values缺失值
Missing values are handled natively. At each split, XGBoost learns which side rows with a missing value should go to. No imputation is required.
Missing values खुद संभाली जाती हैं। हर split पर XGBoost सीखता है कि missing value वाली rows किस तरफ़ जाएँ। Imputation ज़रूरी नहीं।
原生处理缺失值。在每个分裂上,XGBoost 都会学习缺失值的行应该去哪一边,不需要填补。
💾
Cache-aware layoutCache-aware layout缓存友好布局
memory layoutmemory layout内存布局
Data is stored in compact blocks so gradient sums fit well in the CPU cache. This is one reason XGBoost is much faster than simple implementations.
Data छोटे blocks में रखा जाता है ताकि gradient के जोड़ CPU cache में अच्छी तरह आ जाएँ। XGBoost के सरल implementations से बहुत तेज़ होने का यह एक कारण है।
数据以紧凑的块存储,让梯度求和能很好地放进 CPU 缓存。这是 XGBoost 比简单实现快得多的原因之一。
🌐
External memoryExternal memory外存训练
data larger than RAMRAM से बड़ा data大于内存的数据
With external-memory mode, XGBoost can stream data from disk in batches, so you can train on datasets bigger than your RAM. GPU training is also built in (device='cuda').
External-memory mode में XGBoost disk से data batches में stream कर सकता है, इसलिए आप RAM से बड़े datasets पर train कर सकते हैं। GPU training भी built-in है (device='cuda')।
在外存模式下,XGBoost 可以分批从磁盘读取数据,所以能训练比内存还大的数据集。还内置了 GPU 训练(device='cuda')。

SectionSection第 06 节

Python Implementation — Classification & RegressionPython Implementation — Classification और RegressionPython 实现 — 分类与回归

InstallationInstallation安装

pip install xgboost scikit-learn pandas numpy

Classification — Predicting Customer ChurnClassification — Customer Churn Predict करना分类 — 预测客户流失

import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report

# Simulated churn dataset: 8,000 customers, 20 features
X, y = make_classification(
    n_samples=8000, n_features=20,
    n_informative=12, n_redundant=4,
    random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# XGBoost classifier with sensible starting values
model = xgb.XGBClassifier(
    n_estimators=300,        # number of boosting rounds
    learning_rate=0.05,      # eta: shrinkage per round
    max_depth=6,             # maximum tree depth
    subsample=0.8,           # row sampling per tree
    colsample_bytree=0.8,    # feature sampling per tree
    gamma=0,                 # minimum split gain
    reg_alpha=0,             # L1 regularisation
    reg_lambda=1,            # L2 regularisation
    eval_metric='logloss',
    random_state=42
)
# Note: do NOT pass use_label_encoder — it was removed in XGBoost 2.0.

model.fit(
    X_train, y_train,
    eval_set=[(X_test, y_test)],   # only to watch the loss; no early stopping here
    verbose=100
)

y_pred = model.predict(X_test)
print(f"\nAccuracy: {accuracy_score(y_test, y_pred):.4f}\n")
print(classification_report(y_test, y_pred))
OUTPUT
[0] validation_0-logloss:0.66842 [100] validation_0-logloss:0.17738 [200] validation_0-logloss:0.12065 [299] validation_0-logloss:0.10238 Accuracy: 0.9656 precision recall f1-score support 0 0.97 0.96 0.96 785 1 0.96 0.97 0.97 815 accuracy 0.97 1600 macro avg 0.97 0.97 0.97 1600 weighted avg 0.97 0.97 0.97 1600
⚠️
Remove use_label_encoderuse_label_encoder हटाएँ删除 use_label_encoder

Many older examples pass use_label_encoder=False. It was deprecated in XGBoost 1.6 and removed in 2.0; today it only produces a warning that the parameter is not used. Delete it from your code. Also note: passing the test set to eval_set is fine for watching the loss, but never use it for early stopping or tuning.

कई पुराने examples use_label_encoder=False देते हैं। यह XGBoost 1.6 में deprecated हुआ और 2.0 में हटा दिया गया; आज यह बस warning देता है कि parameter इस्तेमाल नहीं हुआ। इसे अपने code से हटा दें। यह भी ध्यान दें: loss देखने के लिए test set को eval_set में देना ठीक है, पर early stopping या tuning के लिए कभी नहीं।

很多旧示例会传入 use_label_encoder=False。它在 XGBoost 1.6 中被弃用,2.0 中被移除,现在只会产生"参数未使用"的警告,请从代码中删除。另外注意:把测试集放进 eval_set 来观察 loss 没问题,但绝不能用它做 early stopping 或调参。

Regression — California Housing PricesRegression — California के घरों की कीमतें回归 — 加州房价

import xgboost as xgb
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_absolute_error

housing = fetch_california_housing()
X_h, y_h = housing.data, housing.target         # y = median house value in $100,000
Xh_train, Xh_test, yh_train, yh_test = train_test_split(
    X_h, y_h, test_size=0.2, random_state=42
)

reg = xgb.XGBRegressor(
    n_estimators=500,
    learning_rate=0.03,
    max_depth=5,
    subsample=0.75,
    colsample_bytree=0.75,
    reg_lambda=1.5,
    random_state=42
)
reg.fit(Xh_train, yh_train)

y_pred = reg.predict(Xh_test)
print(f"R² Score: {r2_score(yh_test, y_pred):.4f}")
print(f"MAE:      ${mean_absolute_error(yh_test, y_pred) * 100_000:,.0f}")
OUTPUT
R² Score: 0.8328 MAE: $31,386

SectionSection第 07 节

Key Hyperparameters — Complete Referenceमुख्य Hyperparameters — पूरा Reference关键超参数 — 完整参考

XGBoost's hyperparameters fall into four groups. Defaults are for XGBoost 2.x/3.x.

XGBoost के hyperparameters चार groups में आते हैं। Defaults XGBoost 2.x/3.x के हैं।

XGBoost 的超参数分为四组。默认值适用于 XGBoost 2.x/3.x。

Group 1 — Boosting ControlGroup 1 — Boosting नियंत्रण第 1 组 — 提升控制

ParameterDefaultRangeRange范围Effectअसर作用Tuning priorityTuning priority调参优先级
n_estimators10050–3000Number of boosting rounds (trees)Boosting rounds (trees) की संख्या提升轮数(树的数量)High: set it with early stoppingज़्यादा: early stopping से तय करें高:用 early stopping 确定
learning_rate (eta)0.30.01–0.3Shrinkage per round. Lower usually generalises better but needs more treesहर round का shrinkage. कम आमतौर पर बेहतर generalise करता है पर ज़्यादा trees चाहिए每轮的缩放。越低通常泛化越好,但需要更多树Critical: start at 0.05–0.1बहुत ज़रूरी: 0.05–0.1 से शुरू करें关键:从 0.05–0.1 开始
booster'gbtree'gbtree / gblinear / dartType of base learner. gbtree is almost always best for tabular dataBase learner का प्रकार। Tabular data के लिए gbtree लगभग हमेशा best基学习器类型。表格数据几乎总是 gbtree 最好Rarely changedशायद ही बदलें很少改动

Group 2 — Tree StructureGroup 2 — Tree का ढाँचा第 2 组 — 树结构

ParameterDefaultRangeRange范围Effectअसर作用Tuning priorityTuning priority调参优先级
max_depth63–10Maximum depth. Deeper = more complex patterns, more overfitting riskअधिकतम depth. ज़्यादा = ज़्यादा complex patterns, overfitting का ज़्यादा ख़तरा最大深度。越深模式越复杂,过拟合风险越高Critical: tune firstबहुत ज़रूरी: पहले tune करें关键:最先调
min_child_weight11–10Minimum Hessian sum in a leaf. Higher = more careful splitsLeaf में न्यूनतम Hessian जोड़। ज़्यादा = ज़्यादा सावधान splits叶子中 Hessian 和的最小值。越高分裂越保守Highज़्यादा高
gamma00–5Minimum gain for a split. Higher = more pruningSplit के लिए न्यूनतम gain. ज़्यादा = ज़्यादा pruning分裂的最小增益。越高剪枝越多Highज़्यादा高
max_leaves0 (no limit)0–64Limits leaves instead of depth; mainly with grow_policy='lossguide'Depth के बजाय leaves सीमित करता है; मुख्यतः grow_policy='lossguide' के साथ限制叶子数而非深度;主要配合 grow_policy='lossguide'Optionalवैकल्पिक可选
tree_method'hist'hist / exact / approxHow splits are searched. hist is fast and the default since 2.0Splits कैसे खोजे जाते हैं। hist तेज़ है और 2.0 से default如何搜索分裂点。hist 快速,2.0 起为默认Keep histhist रखें保持 hist

Group 3 — Sampling (Stochastic Boosting)Group 3 — Sampling (Stochastic Boosting)第 3 组 — 抽样(随机提升)

ParameterDefaultRangeRange范围Effectअसर作用Tuning priorityTuning priority调参优先级
subsample1.00.5–1.0Share of rows sampled per tree. Below 1.0 adds randomnessहर tree के लिए rows का हिस्सा। 1.0 से कम randomness जोड़ता है每棵树抽样的行比例。小于 1.0 会增加随机性Highज़्यादा高
colsample_bytree1.00.3–1.0Share of features per treeहर tree के लिए features का हिस्सा每棵树的特征比例Highज़्यादा高
colsample_bylevel1.00.3–1.0Share of features per depth levelहर depth level के लिए features का हिस्सा每一层的特征比例Mediumमध्यम中
colsample_bynode1.00.3–1.0Share of features per splitहर split के लिए features का हिस्सा每次分裂的特征比例Mediumमध्यम中

Group 4 — RegularisationGroup 4 — Regularisation第 4 组 — 正则化

ParameterDefaultRangeRange范围Effectअसर作用Tuning priorityTuning priority调参优先级
reg_alpha (alpha)00–10L1 on leaf weights. Can push some weights to exactly zeroLeaf weights पर L1. कुछ weights को बिल्कुल zero कर सकता है叶子权重的 L1,可以把一些权重压到 0Higher for many featuresकई features हों तो ज़्यादा特征多时更重要
reg_lambda (lambda)10–10L2 on leaf weights. Shrinks all weights toward zeroLeaf weights पर L2. सभी weights को zero की ओर सिकोड़ता है叶子权重的 L2,把所有权重向 0 收缩Highज़्यादा高
scale_pos_weight1ratioratio比值For imbalanced data: sum(negatives) / sum(positives)Imbalanced data के लिए: sum(negatives) / sum(positives)用于不平衡数据:sum(负类) / sum(正类)Critical when classes are imbalancedClasses imbalanced हों तो बहुत ज़रूरी类别不平衡时很关键
🔑
A Tuning Order That WorksTuning का एक क्रम जो काम करता है一个有效的调参顺序

1. Fix learning_rate=0.05 and find the number of trees with early stopping. 2. Tune max_depth and min_child_weight together. 3. Tune subsample and colsample_bytree. 4. Tune gamma, reg_alpha, reg_lambda. 5. Lower learning_rate and let early stopping find the new number of trees.

1. learning_rate=0.05 तय करें और early stopping से trees की संख्या खोजें। 2. max_depth और min_child_weight साथ tune करें। 3. subsample और colsample_bytree tune करें। 4. gamma, reg_alpha, reg_lambda tune करें। 5. learning_rate घटाएँ और early stopping को trees की नई संख्या खोजने दें।

1. 固定 learning_rate=0.05,用 early stopping 找出树的数量。2. 一起调 max_depth 和 min_child_weight。3. 调 subsample 和 colsample_bytree。4. 调 gamma、reg_alpha、reg_lambda。5. 降低 learning_rate,让 early stopping 找出新的树数量。


SectionSection第 08 节

Early Stopping — Finding the Right Number of TreesEarly Stopping — Trees की सही संख्या खोजनाEarly Stopping — 找到合适的树数量

The Running Coachदौड़ का Coach跑步教练
A coach watches an athlete's lap times. For the first 30 laps the times keep improving. Around lap 41 they level off. By lap 55 they are getting worse: the athlete is tired and cramping. The coach stops the run and says: "Lap 41 was your best."

Early stopping does exactly this. It checks the validation loss after every boosting round and stops when there has been no improvement for early_stopping_rounds rounds in a row. The model keeps the trees up to the best round, not the last one.
एक coach athlete के lap times देखता है। पहले 30 laps में time सुधरता रहता है। लगभग lap 41 पर यह रुक जाता है। Lap 55 तक यह बिगड़ने लगता है: athlete थका हुआ है और ऐंठन है। Coach दौड़ रोकता है और कहता है: "Lap 41 तुम्हारा सबसे अच्छा था।"

Early stopping ठीक यही करता है। यह हर boosting round के बाद validation loss जाँचता है और जब लगातार early_stopping_rounds rounds तक सुधार नहीं होता तो रुक जाता है। Model सबसे अच्छे round तक के trees रखता है, आख़िरी वाले तक नहीं।
一位教练看着运动员的每圈用时。前 30 圈用时一直在进步,大约第 41 圈开始持平,到第 55 圈开始变差:运动员累了、抽筋了。教练叫停并说:"第 41 圈是你最好的一圈。"

Early stopping 做的正是这件事。它在每一轮提升后检查验证 loss,如果连续 early_stopping_rounds 轮都没有改善就停止。model 保留到最佳轮次为止的树,而不是最后一轮。
import xgboost as xgb
from sklearn.model_selection import train_test_split

# Split a validation set off the TRAINING data (never use the test set here)
X_tr, X_val, y_tr, y_val = train_test_split(
    X_train, y_train, test_size=0.15, random_state=42
)

model = xgb.XGBClassifier(
    n_estimators=2000,          # set high: early stopping finds the real number
    learning_rate=0.05,
    max_depth=6,
    subsample=0.8,
    colsample_bytree=0.8,
    eval_metric='logloss',
    early_stopping_rounds=50,   # stop after 50 rounds with no improvement
    random_state=42
)
model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=False)

print(f"Best round:       {model.best_iteration}")
print(f"Best val logloss: {model.best_score:.5f}")
print(f"Trees built:      {model.get_booster().num_boosted_rounds()} of 2000")
# For a final model, use best_iteration + 1 trees (best_iteration counts from 0)
OUTPUT
Best round: 568 Best val logloss: 0.13127 Trees built: 619 of 2000
LIVELIVE互动Early-Stopping CoachEarly-Stopping CoachEarly Stopping 教练

Orange = validation loss, purple = training loss. The red zone counts rounds since the last improvement. When it reaches the patience value, training stops, and the model rolls back to the green best round.

नारंगी = validation loss, बैंगनी = training loss. लाल क्षेत्र पिछले सुधार के बाद के rounds गिनता है। जब यह patience value तक पहुँचता है, training रुक जाती है, और model हरे best round पर लौट आता है।

橙色 = 验证 loss,紫色 = 训练 loss。红色区域统计自上次改善以来的轮数。当它达到耐心值时训练停止,model 回退到绿色的最佳轮次。

Train lossValidation lossBest roundBest round最佳轮次
—


SectionSection第 09 节

The Four Tuning Strategies — Overviewचार Tuning Strategies — एक नज़र四种调参策略 — 概览

Hyperparameter tuning means finding the combination of settings that gives the best model. There are four main strategies. They trade off speed, coverage and compute cost very differently.

Hyperparameter tuning का मतलब है settings का वह मेल खोजना जो सबसे अच्छा model दे। चार मुख्य strategies हैं। ये speed, coverage और compute cost के बीच बहुत अलग-अलग संतुलन बनाती हैं।

超参数调优就是找到能得到最佳 model 的参数组合。主要有四种策略,它们在速度、覆盖面和计算成本之间的取舍非常不同。

🔲
Grid Search
exhaustiveहर combination穷举
Tries every combination you list. Thorough, but the cost grows exponentially with each new parameter. Best for 2–3 parameters.
आपकी दी हुई हर combination आज़माता है। पूरा, पर हर नए parameter के साथ cost exponential बढ़ता है। 2–3 parameters के लिए सबसे अच्छा।
尝试你列出的每个组合。全面,但每多一个参数成本就指数增长。最适合 2–3 个参数。
🎲
Random Search
random samplingrandom sampling随机抽样
Samples random combinations from ranges or distributions. Fast and scales to many parameters. Has no memory of past results.
Ranges या distributions से random combinations लेता है। तेज़ और कई parameters तक scale होता है। पिछले results याद नहीं रखता।
从范围或分布中随机抽取组合。快速,能扩展到很多参数,但不记得之前的结果。
⚡
Optuna (TPE)
Bayesian, model of good vs badBayesian, अच्छे vs बुरे का model贝叶斯:建模好与坏
Learns from past trials which regions score well, and samples more there. Can prune bad trials early. Very good for real projects.
पिछले trials से सीखता है कि कौन से क्षेत्र अच्छा score देते हैं, और वहाँ ज़्यादा sample लेता है। बुरे trials को जल्दी रोक सकता है। असली projects के लिए बहुत अच्छा।
从过去的试验中学习哪些区域得分高,并在那里多抽样。可以提前剪掉差的试验。非常适合实际项目。
🧠
Bayesian (GP)Bayesian (GP)贝叶斯(GP)
surrogate model of the scorescore का surrogate model分数的代理模型
Fits a Gaussian process to all results so far and picks the next point by Expected Improvement. Very sample-efficient; best when each fit is slow.
अब तक के सभी results पर Gaussian process fit करता है और Expected Improvement से अगला point चुनता है। बहुत sample-efficient; हर fit धीमा हो तब सबसे अच्छा।
用高斯过程拟合目前所有结果,并用期望改进(EI)选下一个点。样本效率很高,最适合每次训练很慢的情况。
💡
Optuna (TPE) Is Also Bayesian OptimisationOptuna (TPE) भी Bayesian Optimisation हैOptuna(TPE)也是贝叶斯优化

Strategies 3 and 4 are both Bayesian optimisation: both use past results to choose the next trial. They differ in the model they build. TPE models "what do good settings look like vs bad ones?" A Gaussian process models the score surface itself, with uncertainty.

Strategies 3 और 4 दोनों Bayesian optimisation हैं: दोनों अगला trial चुनने के लिए पिछले results इस्तेमाल करते हैं। फ़र्क़ उनके बनाए model में है। TPE model करता है "अच्छी settings बुरी settings से कैसे अलग दिखती हैं?" Gaussian process खुद score surface को, uncertainty के साथ, model करता है।

策略 3 和 4 都属于贝叶斯优化:都利用过去的结果来选择下一次试验。区别在于它们构建的模型。TPE 建模的是"好的参数和差的参数分别长什么样";高斯过程则直接建模分数曲面本身,并带有不确定性。

🗺️ WHICH STRATEGY SHOULD YOU USE?कौन-सी STRATEGY इस्तेमाल करें?该用哪种策略?
Which tuning strategy STARTशुरू开始 ≤ 3 params, fast model?≤ 3 params, तेज़ model?≤ 3 个参数且训练快? yesहाँ是 Grid SearchGridSearchCV · fine-tuningGridSearchCV · बारीक tuningGridSearchCV · 精细调参 noनहीं否 Each fit takes minutes?हर fit में minutes?每次训练要几分钟? yesहाँ是 Bayesian (GP / TPE)25–75 evaluations25–75 evaluations25–75 次评估 noनहीं否 Want pruning & plots?Pruning और plots चाहिए?需要剪枝和可视化? yesहाँ是 Optuna (TPE)50–150 trials · pruning50–150 trials · pruning50–150 次试验 · 剪枝 noनहीं否 Random SearchRandomizedSearchCV · 50–200

A rule of thumb, not a law. The key questions: how many parameters, how long one fit takes, and whether you want pruning and diagnostic plots.

यह एक अनुमान का नियम है, क़ानून नहीं। मुख्य सवाल: कितने parameters, एक fit में कितना समय, और क्या आपको pruning और diagnostic plots चाहिए।

这是经验法则,不是定律。关键问题:有多少参数、一次训练要多久、是否需要剪枝和诊断图。


SectionSection第 10 节

Strategy 1 — Grid SearchStrategy 1 — Grid Search策略 1 — 网格搜索

The Librarian's IndexLibrarian की सूची图书管理员的索引
A librarian wants the best temperature and humidity for storing old manuscripts. She tests every combination: 15°C/40%, 15°C/50%, 15°C/60%, 20°C/40%, 20°C/50%… She tries every grid point. Thorough, but if the grid is too fine, she will spend 40 years testing. That is Grid Search: complete, but the number of combinations explodes.
एक librarian पुरानी पांडुलिपियाँ रखने के लिए सबसे अच्छा तापमान और नमी खोजना चाहती है। वह हर combination test करती है: 15°C/40%, 15°C/50%, 15°C/60%, 20°C/40%, 20°C/50%… वह हर grid point आज़माती है। पूरा, पर अगर grid बहुत बारीक हो तो वह 40 साल test करती रहेगी। यही Grid Search है: पूरा, पर combinations की संख्या फट जाती है।
一位图书管理员想找到保存古籍的最佳温度和湿度。她测试每一种组合:15°C/40%、15°C/50%、15°C/60%、20°C/40%、20°C/50%……她尝试每一个网格点。很全面,但如果网格太细,她要测 40 年。这就是网格搜索:完整,但组合数会爆炸。

Grid Search trains a model for every combination of the values you list. 3 parameters with 5 values each = 5³ = 125 models. 6 parameters = 5⁶ = 15,625 models, and with 5-fold CV that is 78,125 training runs.

Grid Search आपकी दी हुई values की हर combination के लिए एक model train करता है। 5-5 values वाले 3 parameters = 5³ = 125 models. 6 parameters = 5⁶ = 15,625 models, और 5-fold CV के साथ यह 78,125 training runs है।

网格搜索会为你列出的值的每一种组合训练一个 model。3 个参数各 5 个值 = 5³ = 125 个 model。6 个参数 = 5⁶ = 15,625 个 model,加上 5 折交叉验证就是 78,125 次训练。

⚠️
When Grid Search Is AppropriateGrid Search कब ठीक है何时适合用网格搜索

Use Grid Search only for 2–3 hyperparameters and a fast model. With XGBoost's 10+ parameters, it is rarely the right choice. Its best use is fine-tuning a small range after Random Search or Optuna has found a good region.

Grid Search सिर्फ़ 2–3 hyperparameters और तेज़ model के लिए इस्तेमाल करें। XGBoost के 10+ parameters के साथ यह शायद ही सही विकल्प है। इसका सबसे अच्छा उपयोग Random Search या Optuna के अच्छा क्षेत्र खोजने के बाद छोटी range की बारीक tuning है।

只在 2–3 个超参数且 model 训练很快时使用网格搜索。面对 XGBoost 的 10 多个参数,它很少是正确选择。它最适合在随机搜索或 Optuna 找到好区域之后,在小范围内做精细调参。

import time
import pandas as pd
import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# Keep the grid SMALL: 3 params x 3 values = 27 combos x 5 folds = 135 fits
param_grid = {
    'max_depth':     [3, 5, 7],
    'learning_rate': [0.01, 0.05, 0.1],
    'n_estimators':  [100, 300, 500],
}
base_model = xgb.XGBClassifier(subsample=0.8, colsample_bytree=0.8,
                               eval_metric='logloss', random_state=42)

grid_search = GridSearchCV(
    estimator=base_model,
    param_grid=param_grid,
    cv=5,
    scoring='roc_auc',
    n_jobs=-1,               # use all CPU cores
    verbose=1
)
t0 = time.perf_counter()
grid_search.fit(X_train, y_train)

print("Best parameters:", grid_search.best_params_)
print(f"Best CV AUC:     {grid_search.best_score_:.4f}")
print(f"Time:            {time.perf_counter() - t0:.0f} s\n")

results = pd.DataFrame(grid_search.cv_results_)
top5 = results.nlargest(5, 'mean_test_score')[[
    'param_max_depth', 'param_learning_rate', 'param_n_estimators', 'mean_test_score']]
print(top5.round(4).to_string(index=False))
OUTPUT
Fitting 5 folds for each of 27 candidates, totalling 135 fits Best parameters: {'learning_rate': 0.05, 'max_depth': 7, 'n_estimators': 500} Best CV AUC: 0.9914 Time: 72 s param_max_depth param_learning_rate param_n_estimators mean_test_score 7 0.05 500 0.9914 7 0.05 300 0.9910 5 0.10 500 0.9909 7 0.10 500 0.9909 7 0.10 300 0.9909
📐
The Curse of Dimensionality — Real NumbersCurse of Dimensionality — असली संख्याएँ维度灾难 — 真实数字

Each extra parameter with 5 values multiplies the work by 5. If one XGBoost fit takes 10 seconds and you grid-search 6 parameters with 5 values each: 5⁶ × 5 folds × 10 s = 781,250 s ≈ 217 hours (about 9 days) on one machine. Random Search with 100 iterations and 5 folds takes 100 × 5 × 10 s ≈ 83 minutes, and often finds a comparable result.

5 values वाला हर extra parameter काम को 5 गुना कर देता है। अगर एक XGBoost fit में 10 seconds लगते हैं और आप 5-5 values वाले 6 parameters grid-search करते हैं: 5⁶ × 5 folds × 10 s = 781,250 s ≈ एक machine पर 217 घंटे (लगभग 9 दिन)। 100 iterations और 5 folds वाले Random Search में 100 × 5 × 10 s ≈ 83 मिनट लगते हैं, और अक्सर इतना ही अच्छा result मिलता है।

每多一个有 5 个取值的参数,工作量就乘以 5。如果一次 XGBoost 训练要 10 秒,对 6 个参数各 5 个值做网格搜索:5⁶ × 5 折 × 10 秒 = 781,250 秒 ≈ 单机 217 小时(约 9 天)。100 次迭代、5 折的随机搜索只需 100 × 5 × 10 秒 ≈ 83 分钟,而且常常能找到差不多好的结果。

LIVELIVE互动Grid vs Random — Same BudgetGrid vs Random — बराबर Budget网格 vs 随机 — 相同预算

The green shading is the CV score. Only learning_rate (left–right) really matters; colsample (up–down) barely does. The ticks under each panel show which learning_rate values were actually tried. Yellow ring = best point found.

हरा रंग CV score है। सिर्फ़ learning_rate (बाएँ–दाएँ) असल में मायने रखता है; colsample (ऊपर–नीचे) मुश्किल से। हर panel के नीचे के निशान दिखाते हैं कि learning_rate की कौन-सी values सच में आज़माई गईं। पीला घेरा = मिला सबसे अच्छा point.

绿色深浅表示 CV 分数。只有 learning_rate(左右方向)真正重要,colsample(上下方向)几乎无关。每个面板下方的刻度显示实际尝试了哪些 learning_rate 值。黄圈 = 找到的最佳点。

GridRandom
Grid
—
Random
—


SectionSection第 11 节

Strategy 2 — Random SearchStrategy 2 — Random Search策略 2 — 随机搜索

The Prospector's ParadoxProspector की पहेली淘金者的悖论
Two gold prospectors search a desert. Prospector A drills in a perfect grid, every 100 metres. Prospector B throws darts at a map and drills wherever they land.

The gold lies in a thin seam that runs along one direction. Prospector A's grid tests only a few distinct positions along that direction, and can miss the seam. Prospector B tests a new position with every dart, so he is more likely to hit it.

Bergstra & Bengio (2012) showed this for hyperparameters: when only a few parameters really matter, random search is usually more efficient than grid search.
दो सोना खोजने वाले एक रेगिस्तान में खोज करते हैं। Prospector A हर 100 मीटर पर perfect grid में खुदाई करता है। Prospector B नक्शे पर darts फेंकता है और जहाँ वे गिरें वहाँ खुदाई करता है।

सोना एक पतली पट्टी में है जो एक दिशा में चलती है। Prospector A का grid उस दिशा में बस कुछ अलग-अलग जगहें test करता है, और पट्टी से चूक सकता है। Prospector B हर dart के साथ एक नई जगह test करता है, इसलिए उसके उसे पाने की संभावना ज़्यादा है।

Bergstra & Bengio (2012) ने hyperparameters के लिए यह दिखाया: जब सिर्फ़ कुछ parameters सच में मायने रखते हैं, तो random search आमतौर पर grid search से ज़्यादा efficient है।
两位淘金者在沙漠中寻金。淘金者 A 每隔 100 米按完美网格钻探;淘金者 B 向地图扔飞镖,飞镖落在哪里就在哪里钻。

金子在一条沿某个方向延伸的细矿脉里。A 的网格在这个方向上只测试了少数几个不同位置,可能错过矿脉;B 的每支飞镖都测试一个新位置,所以更可能碰到它。

Bergstra 和 Bengio(2012)在超参数上证明了这一点:当只有少数参数真正重要时,随机搜索通常比网格搜索更高效。
import time
import xgboost as xgb
from scipy.stats import randint, uniform, loguniform
from sklearn.model_selection import RandomizedSearchCV
from sklearn.metrics import roc_auc_score

# Wide search space: Random Search explores it efficiently
param_dist = {
    'n_estimators':     randint(100, 1000),
    'learning_rate':    loguniform(0.005, 0.3),   # log scale: more small values
    'max_depth':        randint(3, 10),
    'min_child_weight': randint(1, 10),
    'subsample':        uniform(0.5, 0.5),        # uniform(loc, scale) -> [0.5, 1.0]
    'colsample_bytree': uniform(0.4, 0.6),        # -> [0.4, 1.0]
    'gamma':            uniform(0, 2),
    'reg_alpha':        loguniform(1e-4, 10),
    'reg_lambda':       loguniform(1e-4, 10),
}
base = xgb.XGBClassifier(eval_metric='logloss', random_state=42)

random_search = RandomizedSearchCV(
    estimator=base,
    param_distributions=param_dist,
    n_iter=100,              # 100 random combinations
    cv=5,
    scoring='roc_auc',
    n_jobs=-1,
    verbose=1,
    random_state=42
)
t0 = time.perf_counter()
random_search.fit(X_train, y_train)

print("Best parameters:")
for k, v in sorted(random_search.best_params_.items()):
    print(f"  {k:<17}: {v:.4g}" if isinstance(v, float) else f"  {k:<17}: {v}")
print(f"Best CV AUC: {random_search.best_score_:.5f}")
proba = random_search.best_estimator_.predict_proba(X_test)[:, 1]
print(f"Test AUC:    {roc_auc_score(y_test, proba):.5f}")
print(f"Time:        {time.perf_counter() - t0:.0f} s")
OUTPUT
Fitting 5 folds for each of 100 candidates, totalling 500 fits Best parameters: colsample_bytree : 0.9351 gamma : 0.2932 learning_rate : 0.0409 max_depth : 8 min_child_weight : 3 n_estimators : 747 reg_alpha : 0.007436 reg_lambda : 0.007132 subsample : 0.9064 Best CV AUC: 0.99061 Test AUC: 0.99441 Time: 310 s
🔲 Grid Search (3 params, 27 combos)Grid Search (3 params, 27 combos)网格搜索(3 个参数,27 种组合)
MetricMetric指标ValueValue数值
FitsFits训练次数135 (27 × 5 folds)
Best CV AUCBest CV AUC最佳 CV AUC0.9914
Time on this page's runइस page के run में समय本页运行耗时72 s
Never tunedकभी tune नहीं हुए从未调整subsample, min_child_weight, gamma, alpha, lambda
🎲 Random Search (9 params, 100 iters)Random Search (9 params, 100 iters)随机搜索(9 个参数,100 次)
MetricMetric指标ValueValue数值
FitsFits训练次数500 (100 × 5 folds)
Best CV AUCBest CV AUC最佳 CV AUC0.99061
Time on this page's runइस page के run में समय本页运行耗时310 s
CoveredCover हुए覆盖All 9 key parametersसभी 9 मुख्य parameters全部 9 个关键参数

Both searches use the same data and the same scoring (ROC-AUC), so the numbers compare directly. A surprise: Grid Search scored slightly higher here (0.9914 vs 0.9906), in a quarter of the time. This synthetic data is easy, and the three parameters in the grid (depth, learning rate, number of trees) are exactly the ones that matter; the grid also happened to include good values. Random Search spent much of its budget on parameters that barely matter for this data. The gap is smaller than the noise between CV folds, so treat it as a tie. Timings are from a 2-core machine; yours will differ.

दोनों searches एक ही data और एक ही scoring (ROC-AUC) इस्तेमाल करती हैं, इसलिए numbers की सीधी तुलना होती है। एक हैरानी: यहाँ Grid Search ने थोड़ा ज़्यादा score किया (0.9914 बनाम 0.9906), वह भी एक-चौथाई समय में। यह synthetic data आसान है, और grid के तीन parameters (depth, learning rate, trees की संख्या) ठीक वही हैं जो मायने रखते हैं; grid में संयोग से अच्छी values भी थीं। Random Search ने अपना बहुत सा budget उन parameters पर खर्च किया जो इस data के लिए मुश्किल से मायने रखते हैं। यह अंतर CV folds के बीच के noise से छोटा है, इसलिए इसे बराबरी मानें। समय 2-core machine का है; आपका अलग होगा।

两种搜索使用相同的数据和评分(ROC-AUC),所以数字可以直接比较。意外的是:这里网格搜索的分数略高(0.9914 vs 0.9906),用时只有四分之一。这份合成数据很简单,网格里的三个参数(深度、学习率、树的数量)恰好就是最重要的那些,而且网格碰巧包含了好的取值。随机搜索把大量预算花在了对这份数据几乎无关紧要的参数上。这个差距比交叉验证各折之间的噪声还小,所以可以视为平局。耗时来自双核机器,你的结果会不同。


SectionSection第 12 节

Strategy 3 — Optuna (TPE + Pruning)Strategy 3 — Optuna (TPE + Pruning)策略 3 — Optuna(TPE + 剪枝)

The Smart Chefसमझदार Chef聪明的厨师
Three chefs try to perfect a soup. Chef A tastes every spice ratio in order. Chef B grabs spices at random and forgets what worked. Chef C (Optuna) keeps notes: "My last 10 salty soups scored badly, so I'll use less salt next time." Chef C also gives up on a bad pot early: if it tastes terrible after 2 minutes, why cook it for an hour?

Optuna's Tree-structured Parzen Estimator (TPE) learns which parameter regions give good results and samples more from them. Its pruner stops bad trials early and saves compute.
तीन chefs एक soup को perfect बनाने की कोशिश करते हैं। Chef A हर मसाले के अनुपात को क्रम से चखता है। Chef B random मसाले उठाता है और भूल जाता है कि क्या काम किया। Chef C (Optuna) notes रखता है: "मेरे पिछले 10 नमकीन soups का score बुरा था, इसलिए अगली बार कम नमक डालूँगा।" Chef C बुरे बर्तन को जल्दी छोड़ भी देता है: अगर 2 मिनट बाद ही स्वाद बहुत बुरा है, तो उसे एक घंटा क्यों पकाएँ?

Optuna का Tree-structured Parzen Estimator (TPE) सीखता है कि कौन से parameter क्षेत्र अच्छे results देते हैं और वहाँ से ज़्यादा sample लेता है। इसका pruner बुरे trials को जल्दी रोककर compute बचाता है।
三位厨师都想做出完美的汤。厨师 A 按顺序尝试每一种香料比例;厨师 B 随手抓香料,也不记得什么有效;厨师 C(Optuna)会做笔记:"最近 10 锅咸汤得分都很差,下次少放盐。"厨师 C 还会尽早放弃一锅糟糕的汤:如果 2 分钟后就已经很难吃,何必再煮一小时?

Optuna 的 Tree-structured Parzen Estimator(TPE)会学习哪些参数区域效果好,并在那里多抽样。它的剪枝器会提前终止差的试验,节省计算。

Optuna, from Preferred Networks, is a modern tuning framework. TPE splits the trials so far into a "good" group and a "bad" group, models each with a probability density, and samples where good / bad is highest.

Preferred Networks का Optuna एक modern tuning framework है। TPE अब तक के trials को "अच्छे" और "बुरे" group में बाँटता है, हर एक को probability density से model करता है, और वहाँ sample लेता है जहाँ अच्छा / बुरा सबसे ज़्यादा है।

Optuna 是 Preferred Networks 开发的现代调参框架。TPE 把已有的试验分为"好"和"差"两组,分别用概率密度建模,然后在"好/差"比值最高的地方抽样。

pip install optuna
import time
import optuna
import xgboost as xgb
from sklearn.model_selection import cross_val_score
from sklearn.metrics import roc_auc_score

optuna.logging.set_verbosity(optuna.logging.WARNING)   # quiet output

def objective(trial):
    params = {
        'n_estimators':     trial.suggest_int('n_estimators', 100, 1000),
        'learning_rate':    trial.suggest_float('learning_rate', 0.005, 0.3, log=True),
        'max_depth':        trial.suggest_int('max_depth', 3, 10),
        'min_child_weight': trial.suggest_int('min_child_weight', 1, 10),
        'subsample':        trial.suggest_float('subsample', 0.5, 1.0),
        'colsample_bytree': trial.suggest_float('colsample_bytree', 0.4, 1.0),
        'gamma':            trial.suggest_float('gamma', 0, 5),
        'reg_alpha':        trial.suggest_float('reg_alpha', 1e-4, 10, log=True),
        'reg_lambda':       trial.suggest_float('reg_lambda', 1e-4, 10, log=True),
    }
    model = xgb.XGBClassifier(**params, eval_metric='logloss', random_state=42)
    scores = cross_val_score(model, X_train, y_train, cv=5, scoring='roc_auc', n_jobs=-1)
    return scores.mean()                      # Optuna maximises this

study = optuna.create_study(
    direction='maximize',
    sampler=optuna.samplers.TPESampler(seed=42)    # Tree-structured Parzen Estimator
)
t0 = time.perf_counter()
study.optimize(objective, n_trials=100)

# Best score after 10, 30, 60, 100 trials
best_so_far = [max(t.value for t in study.trials[:n]) for n in (10, 30, 60, 100)]
for n, v in zip((10, 30, 60, 100), best_so_far):
    print(f"After {n:>3} trials: best CV AUC = {v:.5f}")

print("\nBest parameters:")
for k, v in study.best_params.items():
    print(f"  {k:<17}: {v:.4g}" if isinstance(v, float) else f"  {k:<17}: {v}")

best_model = xgb.XGBClassifier(**study.best_params, eval_metric='logloss', random_state=42)
best_model.fit(X_train, y_train)
print(f"\nTest AUC: {roc_auc_score(y_test, best_model.predict_proba(X_test)[:, 1]):.5f}")
print(f"Time:     {time.perf_counter() - t0:.0f} s")
OUTPUT
After 10 trials: best CV AUC = 0.98686 After 30 trials: best CV AUC = 0.99037 After 60 trials: best CV AUC = 0.99079 After 100 trials: best CV AUC = 0.99103 Best parameters: n_estimators : 854 learning_rate : 0.02921 max_depth : 9 min_child_weight : 2 subsample : 0.9219 colsample_bytree : 0.6845 gamma : 0.01034 reg_alpha : 0.001097 reg_lambda : 0.0001484 Test AUC: 0.99466 Time: 616 s
⚠️
A Pruner Does Nothing Without ReportsReports के बिना Pruner कुछ नहीं करता没有中间汇报,剪枝器不起作用

Some tutorials add pruner=MedianPruner() to a study whose objective just calls cross_val_score. That pruner never fires: pruning needs the objective to report intermediate scores during training (with trial.report or a callback). The next example shows pruning that actually works.

कुछ tutorials ऐसी study में pruner=MedianPruner() जोड़ते हैं जिसका objective बस cross_val_score call करता है। वह pruner कभी नहीं चलता: pruning के लिए objective को training के दौरान बीच के scores report करने पड़ते हैं (trial.report या callback से)। अगला example ऐसी pruning दिखाता है जो सच में काम करती है।

有些教程会给一个目标函数只调用 cross_val_score 的 study 加上 pruner=MedianPruner()。这个剪枝器永远不会触发:剪枝需要目标函数在训练过程中汇报中间分数(用 trial.report 或回调)。下一个例子展示了真正有效的剪枝。

Optuna with Pruning (Real Speed-up)Pruning के साथ Optuna (असली Speed-up)带剪枝的 Optuna(真正提速)

pip install optuna-integration
import optuna
import xgboost as xgb
from optuna_integration import XGBoostPruningCallback   # pip install optuna-integration
from sklearn.model_selection import train_test_split

optuna.logging.set_verbosity(optuna.logging.WARNING)
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y_train, test_size=0.15, random_state=42)

def objective_with_pruning(trial):
    model = xgb.XGBClassifier(
        n_estimators=1000,
        learning_rate=trial.suggest_float('learning_rate', 0.005, 0.3, log=True),
        max_depth=trial.suggest_int('max_depth', 3, 10),
        subsample=trial.suggest_float('subsample', 0.5, 1.0),
        colsample_bytree=trial.suggest_float('colsample_bytree', 0.4, 1.0),
        reg_alpha=trial.suggest_float('reg_alpha', 1e-4, 10, log=True),
        eval_metric='logloss',
        early_stopping_rounds=50,
        # The scikit-learn API names the first eval set "validation_0"
        callbacks=[XGBoostPruningCallback(trial, 'validation_0-logloss')],
        random_state=42
    )
    model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=False)
    return model.best_score                   # best validation logloss

study2 = optuna.create_study(
    direction='minimize',
    sampler=optuna.samplers.TPESampler(seed=42),
    pruner=optuna.pruners.MedianPruner(n_startup_trials=10, n_warmup_steps=20)
)
study2.optimize(objective_with_pruning, n_trials=80)

pruned = [t for t in study2.trials if t.state == optuna.trial.TrialState.PRUNED]
print(f"Pruned trials: {len(pruned)} of {len(study2.trials)}")
print(f"Best logloss:  {study2.best_value:.5f}")
OUTPUT
Pruned trials: 35 of 80 Best logloss: 0.12784
🐛
Two Bugs to Avoidदो Bugs से बचें要避免的两个 bug

1. XGBoostPruningCallback now lives in the separate optuna-integration package. 2. The callback must watch the exact metric name XGBoost logs. With the scikit-learn API, the first eval_set is called validation_0, so the name is 'validation_0-logloss', not 'validation-logloss'. A wrong name makes every trial fail.

1. XGBoostPruningCallback अब अलग optuna-integration package में है। 2. Callback को वही metric नाम देखना चाहिए जो XGBoost log करता है। scikit-learn API में पहले eval_set का नाम validation_0 होता है, इसलिए नाम 'validation_0-logloss' है, 'validation-logloss' नहीं। गलत नाम से हर trial fail होता है।

1. XGBoostPruningCallback 现在在单独的 optuna-integration 包里。2. 回调必须监视 XGBoost 实际记录的指标名。在 scikit-learn API 中,第一个 eval_set 叫 validation_0,所以名字是 'validation_0-logloss',而不是 'validation-logloss'。名字写错会让每个试验都失败。

LIVELIVE互动How Median Pruning Saves ComputeMedian Pruning कैसे Compute बचाता है中位数剪枝如何节省计算

20 trials, each a validation-loss curve over 100 boosting rounds. The first 5 (grey) always run fully. After round 20, every 10 rounds, a trial is cut (✂) if its loss is worse than the median of earlier trials at the same round.

20 trials, हर एक 100 boosting rounds का validation-loss curve. पहले 5 (grey) हमेशा पूरे चलते हैं। Round 20 के बाद, हर 10 rounds पर, अगर किसी trial का loss उसी round पर पहले के trials के median से बुरा है तो उसे काट दिया जाता है (✂)।

20 个试验,每个都是 100 轮提升的验证 loss 曲线。前 5 个(灰色)总是完整运行。第 20 轮之后每 10 轮检查一次:如果某个试验的 loss 比之前试验在同一轮的中位数还差,就剪掉(✂)。

—
—

:

Turn pruning off and on: the best final loss stays the same, but with pruning much less compute is spent on trials that were never going to win.

Pruning को बंद और चालू करें: सबसे अच्छा final loss वही रहता है, पर pruning के साथ उन trials पर बहुत कम compute खर्च होता है जो कभी जीतने वाले नहीं थे।

把剪枝关掉再打开:最佳最终 loss 不变,但开启剪枝后,在那些注定不会赢的试验上花的计算少得多。

🎯
Optuna's Diagnostic PlotsOptuna के Diagnostic PlotsOptuna 的诊断图

optuna.visualization.plot_param_importances(study) shows which hyperparameters matter most, plot_optimization_history(study) shows how the best score improved, and plot_contour(study) shows how pairs of parameters interact. They need pip install plotly.

optuna.visualization.plot_param_importances(study) दिखाता है कि कौन से hyperparameters सबसे ज़्यादा मायने रखते हैं, plot_optimization_history(study) दिखाता है कि best score कैसे सुधरा, और plot_contour(study) दिखाता है कि parameters के जोड़े आपस में कैसे असर डालते हैं। इनके लिए pip install plotly चाहिए।

optuna.visualization.plot_param_importances(study) 显示哪些超参数最重要,plot_optimization_history(study) 显示最佳分数如何提升,plot_contour(study) 显示参数两两之间的相互作用。需要 pip install plotly。


SectionSection第 13 节

Strategy 4 — Bayesian Optimisation with a Gaussian ProcessStrategy 4 — Gaussian Process के साथ Bayesian Optimisation策略 4 — 基于高斯过程的贝叶斯优化

The Treasure Hunter with a Mapनक्शे वाला ख़ज़ाना खोजी拿着地图的寻宝人
A treasure hunter searches a jungle. She does not walk at random. She keeps a map of where treasure is likely and how unsure she is: "I dug at three ruins with no luck. Next I'll dig either right next to my best spot, or somewhere I know nothing about."

She balances exploitation (dig near good spots) and exploration (check unknown areas). Bayesian optimisation does the same: a surrogate model (here a Gaussian process) predicts the score and its uncertainty everywhere, and an acquisition function (Expected Improvement) picks the next point to try.
एक ख़ज़ाना खोजी जंगल में खोज करती है। वह random नहीं चलती। वह एक नक्शा रखती है कि ख़ज़ाना कहाँ होने की संभावना है और वह कितनी अनिश्चित है: "मैंने तीन खंडहरों में खुदाई की, कुछ नहीं मिला। अब मैं या तो अपनी सबसे अच्छी जगह के ठीक पास खोदूँगी, या कहीं ऐसी जगह जिसके बारे में मुझे कुछ नहीं पता।"

वह exploitation (अच्छी जगहों के पास खोदना) और exploration (अनजान जगहें जाँचना) में संतुलन रखती है। Bayesian optimisation भी यही करता है: एक surrogate model (यहाँ Gaussian process) हर जगह score और उसकी uncertainty predict करता है, और एक acquisition function (Expected Improvement) अगला point चुनता है।
一位寻宝人在丛林中寻宝。她不是乱走,而是有一张地图,记录宝藏可能在哪里,以及她有多不确定:"我在三处遗迹挖过都没收获。下一次要么挖在最好的那处旁边,要么去一个我完全不了解的地方。"

她在利用(在好地方附近挖)和探索(查看未知区域)之间取得平衡。贝叶斯优化也是这样:代理模型(这里是高斯过程)预测每个位置的分数及其不确定性,采集函数(期望改进 EI)选出下一个要尝试的点。
🧠 Bayesian Optimisation — the Four-Step LoopBayesian Optimisation — चार-step Loop贝叶斯优化 — 四步循环
Step 1
Fit the surrogateSurrogate fit करें拟合代理模型: Fit a Gaussian process to all (settings → score) results so far. It gives a predicted mean and an uncertainty band everywhere.अब तक के सभी (settings → score) results पर Gaussian process fit करें। यह हर जगह predicted mean और uncertainty band देता है।用高斯过程拟合目前所有(参数 → 分数)的结果。它在每个位置给出预测均值和不确定带。
Step 2
Maximise Expected ImprovementExpected Improvement maximise करें最大化期望改进: EI asks: how much better than the current best could this point be? Points with a high predicted score or high uncertainty get high EI.EI पूछता है: यह point मौजूदा best से कितना बेहतर हो सकता है? ऊँचे predicted score या ऊँची uncertainty वाले points को ऊँचा EI मिलता है।EI 问:这个点比当前最佳可能好多少?预测分数高或不确定性大的点,EI 都高。
Step 3
EvaluateEvaluate करें评估: Train XGBoost with the chosen settings and get the real score. This is the expensive step.चुनी गई settings के साथ XGBoost train करें और असली score पाएँ। यही महँगा step है।用选出的参数训练 XGBoost,得到真实分数。这是最昂贵的一步。
Step 4
Update and repeatUpdate करें और दोहराएँ更新并重复: Add the new result and go back to Step 1, until the budget runs out.नया result जोड़ें और Step 1 पर वापस जाएँ, जब तक budget ख़त्म न हो।加入新结果,回到第 1 步,直到预算用完。
LIVELIVE互动Watch a Gaussian Process SearchGaussian Process को खोजते देखें观看高斯过程如何搜索

A real GP with an RBF kernel and Expected Improvement. Dots = evaluations (green = best so far). Orange line = predicted score; shaded band = ±2 standard deviations of uncertainty. Purple area = EI; the dashed line marks the next point it will try.

RBF kernel और Expected Improvement वाला असली GP. Dots = evaluations (हरा = अब तक का best)। नारंगी line = predicted score; छायादार band = uncertainty के ±2 standard deviations. बैंगनी क्षेत्र = EI; dashed line अगला point दिखाती है जो यह आज़माएगा।

这是一个真实的高斯过程,使用 RBF 核和期望改进。圆点 = 已评估的点(绿色 = 目前最佳)。橙线 = 预测分数,阴影带 = ±2 个标准差的不确定性。紫色区域 = EI,虚线标出它下一个要尝试的点。

Bayesian Optimisation with scikit-optimizescikit-optimize के साथ Bayesian Optimisation用 scikit-optimize 做贝叶斯优化

pip install scikit-optimize
import time
import xgboost as xgb
from skopt import BayesSearchCV                # pip install scikit-optimize
from skopt.space import Real, Integer

search_space = {
    'n_estimators':     Integer(100, 1000),
    'learning_rate':    Real(0.005, 0.3, prior='log-uniform'),
    'max_depth':        Integer(3, 10),
    'min_child_weight': Integer(1, 10),
    'subsample':        Real(0.5, 1.0),
    'colsample_bytree': Real(0.4, 1.0),
    'gamma':            Real(0, 5.0),
    'reg_alpha':        Real(1e-4, 10, prior='log-uniform'),
    'reg_lambda':       Real(1e-4, 10, prior='log-uniform'),
}
base = xgb.XGBClassifier(eval_metric='logloss', random_state=42)

bayes_search = BayesSearchCV(
    estimator=base,
    search_spaces=search_space,
    n_iter=50,               # 50 evaluations
    cv=5,
    scoring='roc_auc',
    n_jobs=-1,
    random_state=42
)

best = []
def on_step(result):                      # result.fun = best (lowest) -AUC so far
    best.append(-result.fun)
    if len(best) in (1, 10, 25, 50):
        print(f"  Iter {len(best):3d} | best CV AUC so far: {-result.fun:.5f}")

t0 = time.perf_counter()
bayes_search.fit(X_train, y_train, callback=[on_step])

print(f"\nBest CV AUC: {bayes_search.best_score_:.5f}")
print("Best parameters:")
for k, v in sorted(bayes_search.best_params_.items()):
    print(f"  {k:<17}: {v:.4g}" if isinstance(v, float) else f"  {k:<17}: {v}")
print(f"Time:        {time.perf_counter() - t0:.0f} s")
OUTPUT
Iter 1 | best CV AUC so far: 0.98398 Iter 10 | best CV AUC so far: 0.98856 Iter 25 | best CV AUC so far: 0.98884 Iter 50 | best CV AUC so far: 0.99019 Best CV AUC: 0.99019 Best parameters: colsample_bytree : 0.877 gamma : 0 learning_rate : 0.04045 max_depth : 9 min_child_weight : 6 n_estimators : 442 reg_alpha : 0.0001 reg_lambda : 0.002027 subsample : 1 Time: 228 s
🔧
Maintenance NoteMaintenance Note维护说明

scikit-optimize is no longer actively developed. The code above works with scikit-optimize 0.10 and scikit-learn 1.9, but for new projects, Optuna (TPE or GPSampler) is the safer long-term choice.

scikit-optimize अब सक्रिय रूप से develop नहीं हो रहा। ऊपर का code scikit-optimize 0.10 और scikit-learn 1.9 के साथ काम करता है, पर नए projects के लिए Optuna (TPE या GPSampler) लंबे समय के लिए सुरक्षित विकल्प है।

scikit-optimize 已不再积极开发。上面的代码可在 scikit-optimize 0.10 和 scikit-learn 1.9 下运行,但对新项目来说,Optuna(TPE 或 GPSampler)是更稳妥的长期选择。

Bayesian Optimisation with Optuna (GP Sampler)Optuna के साथ Bayesian Optimisation (GP Sampler)用 Optuna 做贝叶斯优化(GP 采样器)

import optuna
from optuna.samplers import GPSampler   # Gaussian-process sampler (Optuna >= 3.6; needs: pip install torch)

study_gp = optuna.create_study(
    direction='maximize',
    sampler=GPSampler(seed=42),
    study_name='xgb_gp_tuning'
)
study_gp.optimize(objective, n_trials=50)   # same objective as the TPE example
print(f"GP-Optuna best AUC: {study_gp.best_value:.5f}")

This reuses the objective from the TPE example; only the sampler changes. GPSampler needs PyTorch installed (pip install torch).

यह TPE example वाला objective ही इस्तेमाल करता है; सिर्फ़ sampler बदलता है। GPSampler के लिए PyTorch installed होना चाहिए (pip install torch)।

这里复用 TPE 示例中的 objective,只是换了采样器。GPSampler 需要安装 PyTorch(pip install torch)。


SectionSection第 14 节

Tuning Strategy ComparisonTuning Strategies की तुलना调参策略对比

Propertyगुण属性Grid SearchRandom SearchOptuna (TPE)Bayesian (GP)
How it searchesकैसे खोजता है搜索方式Every combinationहर combination所有组合Random samplesRandom samples随机样本Model of good vs bad regionsअच्छे vs बुरे क्षेत्रों का model好坏区域的模型Score surface + Expected ImprovementScore surface + Expected Improvement分数曲面 + 期望改进
Learns from past?पिछले से सीखता है?从过去学习?Noनहीं否Noनहीं否Yesहाँ是Yesहाँ是
Many parameters?कई parameters?参数很多时?Explodesफट जाता है爆炸Scales wellअच्छा scale扩展良好Scales wellअच्छा scale扩展良好Medium (GP cost grows as n³)मध्यम (GP cost n³ से बढ़ता है)中等(GP 成本按 n³ 增长)
Parallel?Parallel?可并行?Yesहाँ是Yesहाँ是Yes (with care)हाँ (सावधानी से)是(需注意)Partly: it is sequential by designआंशिक: design से sequential部分:设计上是串行的
Trial pruning?Trial pruning?试验剪枝?Noनहीं否Noनहीं否Yesहाँ是With Optuna, yesOptuna के साथ, हाँ用 Optuna 可以
Typical evaluations (rule of thumb)आम evaluations (अनुमान)常见评估次数(经验)All combinationsसभी combinations全部组合50–20050–15025–75
Best for XGBoost when…XGBoost के लिए सबसे अच्छा जब…对 XGBoost 最适合…Fine-tuning 2–3 params2–3 params की बारीक tuning精调 2–3 个参数First broad search, cheap fitsपहली व्यापक खोज, सस्ते fits首轮大范围搜索,训练便宜Most real projectsज़्यादातर असली projects大多数实际项目Each fit is slowहर fit धीमा हो每次训练很慢
LibraryLibrary库GridSearchCVRandomizedSearchCVoptunaoptuna GPSampler, scikit-optimize
LIVELIVE互动The Tuning RaceTuning की दौड़调参赛跑

All four strategies tune the same hidden 2-D landscape (a big peak and a smaller decoy peak), with 30 evaluations each. Grid uses a 5 × 5 grid in the usual row-by-row order. Top: where each strategy looked. Bottom: best score found so far.

चारों strategies एक ही छिपे 2-D landscape (एक बड़ी चोटी और एक छोटी धोखे वाली चोटी) को tune करती हैं, हर एक 30 evaluations के साथ। Grid सामान्य row-by-row क्रम में 5 × 5 grid इस्तेमाल करता है। ऊपर: हर strategy ने कहाँ देखा। नीचे: अब तक मिला best score.

四种策略在同一个隐藏的二维地形上调参(一个大峰和一个较小的诱饵峰),每种 30 次评估。网格搜索按常规的逐行顺序使用 5 × 5 网格。上方:每种策略查看了哪里。下方:目前找到的最佳分数。

Best AUC at the endआख़िर में best AUC最终最佳 AUC
Grid
—
Random
—
TPE
—
GP + EI
—

⚖️
Read Benchmarks With CareBenchmarks सावधानी से पढ़ें谨慎解读基准

Model-based methods shine when the score surface is smooth and each fit is expensive. On cheap problems with many noisy parameters, Random Search with a decent budget is often just as good, and it parallelises perfectly. A practical rule: fast fits (under a minute) → Random Search or Optuna with 100+ trials; slow fits (many minutes) → Optuna or GP with 25–75 trials; Grid Search only for a final, narrow 2–3 parameter sweep.

Model-based methods तब चमकते हैं जब score surface smooth हो और हर fit महँगा हो। कई noisy parameters वाले सस्ते problems पर ठीक-ठाक budget वाला Random Search अक्सर उतना ही अच्छा होता है, और पूरी तरह parallel होता है। व्यावहारिक नियम: तेज़ fits (एक मिनट से कम) → Random Search या 100+ trials वाला Optuna; धीमे fits (कई मिनट) → 25–75 trials वाला Optuna या GP; Grid Search सिर्फ़ आख़िर में 2–3 parameters की छोटी जाँच के लिए।

当分数曲面平滑且每次训练很昂贵时,基于模型的方法优势最明显。对于训练便宜、参数多且噪声大的问题,预算适中的随机搜索往往同样好,而且可以完美并行。实用规则:训练快(不到一分钟)→ 随机搜索或 100+ 次试验的 Optuna;训练慢(几分钟以上)→ 25–75 次试验的 Optuna 或 GP;网格搜索只用于最后对 2–3 个参数的小范围扫描。

On the Real Churn Dataअसली Churn Data पर在真实的流失数据上

StrategyStrategy策略FitsFits训练次数Best CV AUCBest CV AUC最佳 CV AUCTime (2-core machine)समय (2-core machine)耗时(双核机器)
Grid Search (3 params)1350.991472 s
Random Search (100)5000.99061310 s
Optuna TPE (100)5000.99103616 s
scikit-optimize GP (50)2500.99019228 s

These numbers come from the code on this page. All four strategies finish within about 0.001 AUC of each other, which is smaller than the noise between CV folds. Grid even comes first, because this synthetic data is easy and its three parameters are the ones that matter. The lesson: a sensible search space plus early stopping matters more than the choice of search method. The method starts to matter when fits are slow and many parameters interact, as in the race simulator above.

ये numbers इस page के code से आए हैं। चारों strategies एक-दूसरे से लगभग 0.001 AUC के अंदर ख़त्म होती हैं, जो CV folds के बीच के noise से भी छोटा है। Grid तो पहले स्थान पर भी है, क्योंकि यह synthetic data आसान है और उसके तीन parameters वही हैं जो मायने रखते हैं। सबक: समझदारी भरा search space और early stopping, search method के चुनाव से ज़्यादा मायने रखते हैं। Method तब मायने रखने लगता है जब fits धीमे हों और कई parameters आपस में असर डालें, जैसा ऊपर race simulator में है।

这些数字来自本页的代码。四种策略的结果彼此相差不到约 0.001 AUC,比交叉验证各折之间的噪声还小。网格搜索甚至排第一,因为这份合成数据很简单,而它的三个参数正是最重要的那些。结论:合理的搜索空间加上 early stopping,比选择哪种搜索方法更重要。当训练很慢、很多参数相互影响时(就像上面的赛跑模拟器),方法的选择才开始变得重要。


SectionSection第 15 节

Feature Importance in XGBoostXGBoost में Feature ImportanceXGBoost 特征重要性

XGBoost has three built-in importance types. Each measures something different:

XGBoost में तीन built-in importance types हैं। हर एक कुछ अलग मापता है:

XGBoost 有三种内置重要性类型,各自衡量不同的东西:

📊
Weight (frequency)Weight (frequency)Weight(频次)
importance_type='weight'
How many times a feature is used to split, across all trees. Simple, but biased toward features with many unique values. Not recommended for final conclusions.
सभी trees में किसी feature पर कितनी बार split हुआ। सरल, पर कई unique values वाले features की ओर झुका हुआ। आख़िरी निष्कर्षों के लिए सही नहीं।
某个特征在所有树中被用来分裂的次数。简单,但偏向取值多的特征,不建议用于最终结论。
📉
Gain
importance_type='gain'
Average loss reduction each time the feature is used to split. More meaningful than frequency, and the default for feature_importances_.
हर बार feature पर split होने पर औसत loss में कमी। Frequency से ज़्यादा अर्थपूर्ण, और feature_importances_ का default.
每次用该特征分裂时 loss 的平均下降量。比频次更有意义,也是 feature_importances_ 的默认值。
🎯
Cover
importance_type='cover'
Average number of rows (Hessian sum) affected by splits on the feature. Shows reach over the data rather than loss reduction.
Feature पर हुए splits से प्रभावित rows (Hessian जोड़) की औसत संख्या। Loss में कमी के बजाय data पर पहुँच दिखाता है।
在该特征上分裂时影响的平均行数(Hessian 和)。反映的是对数据的覆盖范围,而不是 loss 的下降。
import pandas as pd
import matplotlib.pyplot as plt
import xgboost as xgb
import shap                                     # pip install shap

# `model`, `X_test` come from the churn example above
feature_names = [f"f{i}" for i in range(X_test.shape[1])]
model.get_booster().feature_names = feature_names

gain = model.get_booster().get_score(importance_type='gain')
imp_df = (pd.DataFrame({'feature': list(gain), 'gain': list(gain.values())})
            .sort_values('gain', ascending=False))
print(imp_df.head(5).round(2).to_string(index=False))

xgb.plot_importance(model, importance_type='gain', max_num_features=15)
plt.title('XGBoost Feature Importance (Gain)')
plt.tight_layout()
plt.savefig('importance.png')

# SHAP values: the most reliable view of each feature's effect
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values, X_test, feature_names=feature_names, show=False)
mean_abs = abs(shap_values).mean(axis=0)
top = sorted(zip(feature_names, mean_abs), key=lambda kv: -kv[1])[:5]
print("\nTop 5 by mean |SHAP|: " + ", ".join(f"{f} ({v:.3f})" for f, v in top))
OUTPUT
feature gain f14 17.65 f18 12.54 f12 9.09 f4 8.11 f1 7.80 Top 5 by mean |SHAP|: f14 (0.943), f2 (0.768), f13 (0.742), f4 (0.691), f18 (0.660)
⚠️
Use SHAP for InterpretationInterpretation के लिए SHAP इस्तेमाल करें解释时使用 SHAP

Built-in importances can mislead, especially with correlated features. Above, gain ranks f18 second, while SHAP ranks it fifth and puts f2 second. SHAP values are consistent and show the direction of each feature's effect for each row. They are not magic either: when two features are strongly correlated, SHAP has to split the credit between them, so read those pairs together. TreeExplainer is fast on XGBoost models.

Built-in importances गुमराह कर सकती हैं, ख़ासकर correlated features के साथ। ऊपर gain, f18 को दूसरे स्थान पर रखता है, जबकि SHAP उसे पाँचवें पर रखता है और f2 को दूसरे पर। SHAP values consistent हैं और हर row के लिए हर feature के असर की दिशा दिखाती हैं। ये भी जादू नहीं हैं: जब दो features बहुत correlated हों, तो SHAP को credit उनके बीच बाँटना पड़ता है, इसलिए ऐसे जोड़ों को साथ पढ़ें। XGBoost models पर TreeExplainer तेज़ है।

内置重要性可能产生误导,特别是在特征相关时。上面 gain 把 f18 排第二,而 SHAP 把它排第五,并把 f2 排第二。SHAP 值具有一致性,能显示每个特征对每一行影响的方向。但它也不是万能的:两个特征高度相关时,SHAP 只能在它们之间分配功劳,所以要把这类特征放在一起看。TreeExplainer 在 XGBoost 上很快。


SectionSection第 16 节

Complete Production Pipeline — End-to-Endपूरी Production Pipeline — शुरू से अंत तक完整生产流程 — 端到端

This pipeline fixes a common mistake. Many tutorials find the number of trees once (at learning_rate 0.05), then let Optuna change the learning rate while keeping that tree count fixed. But the right number of trees depends on the learning rate. Here, every trial uses early stopping on the validation set, so it finds its own tree count.

यह pipeline एक आम गलती ठीक करती है। कई tutorials trees की संख्या एक बार खोजते हैं (learning_rate 0.05 पर), फिर Optuna को learning rate बदलने देते हैं जबकि trees की संख्या वही रहती है। पर trees की सही संख्या learning rate पर निर्भर करती है। यहाँ हर trial validation set पर early stopping इस्तेमाल करता है, इसलिए वह अपनी trees की संख्या खुद खोजता है।

这个流程修正了一个常见错误。很多教程只找一次树的数量(在 learning_rate 0.05 时),然后让 Optuna 改变学习率,却保持树的数量不变。但合适的树数量取决于学习率。这里每个试验都在验证集上使用 early stopping,因此会找到自己的树数量。

import optuna
import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, classification_report

# ── STEP 1: Data: train / validation / test ──────────────
X, y = make_classification(n_samples=10000, n_features=25,
                           n_informative=15, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42)
X_tr, X_val, y_tr, y_val = train_test_split(
    X_train, y_train, test_size=0.15, stratify=y_train, random_state=42)

# ── STEP 2: Optuna. Each trial uses early stopping on the validation set,
#    so the number of trees is found per trial (it depends on learning_rate).
optuna.logging.set_verbosity(optuna.logging.WARNING)

def objective(trial):
    model = xgb.XGBClassifier(
        n_estimators=3000,
        learning_rate=trial.suggest_float('learning_rate', 0.01, 0.2, log=True),
        max_depth=trial.suggest_int('max_depth', 3, 8),
        min_child_weight=trial.suggest_int('min_child_weight', 1, 7),
        subsample=trial.suggest_float('subsample', 0.6, 1.0),
        colsample_bytree=trial.suggest_float('colsample_bytree', 0.5, 1.0),
        gamma=trial.suggest_float('gamma', 0, 3),
        reg_alpha=trial.suggest_float('reg_alpha', 1e-4, 5, log=True),
        reg_lambda=trial.suggest_float('reg_lambda', 1e-4, 5, log=True),
        eval_metric='logloss', early_stopping_rounds=50, random_state=42)
    model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=False)
    trial.set_user_attr('n_trees', model.best_iteration + 1)
    return model.best_score                       # validation logloss

study = optuna.create_study(direction='minimize',
                            sampler=optuna.samplers.TPESampler(seed=42))
study.optimize(objective, n_trials=80)
best_n = study.best_trial.user_attrs['n_trees']
print(f"Best val logloss: {study.best_value:.5f} with {best_n} trees")

# ── STEP 3: Refit on train + validation with the best settings ──
final_model = xgb.XGBClassifier(**study.best_params, n_estimators=best_n,
                                eval_metric='logloss', random_state=42)
final_model.fit(X_train, y_train)

# ── STEP 4: Test set: used exactly once ──────────────────
y_proba = final_model.predict_proba(X_test)[:, 1]
print(f"\nTest AUC-ROC: {roc_auc_score(y_test, y_proba):.5f}\n")
print(classification_report(y_test, final_model.predict(X_test), digits=4))
OUTPUT
Best val logloss: 0.09884 with 1362 trees Test AUC-ROC: 0.98855 precision recall f1-score support 0 0.9592 0.9631 0.9612 1002 1 0.9628 0.9589 0.9608 998 accuracy 0.9610 2000 macro avg 0.9610 0.9610 0.9610 2000 weighted avg 0.9610 0.9610 0.9610 2000

SectionSection第 17 节

Golden Rules — XGBoost & Hyperparameter TuningGolden Rules — XGBoost और Hyperparameter Tuning黄金法则 — XGBoost 与超参数调优

🌿 XGBoost — Rules to RememberXGBoost — याद रखने के नियमXGBoost — 必记规则
1
Always use early stopping. Set n_estimators high (1000–3000) and early_stopping_rounds=50 on a validation set. When you tune the learning rate, let early stopping find the tree count inside each trial, because it changes with the learning rate.
हमेशा early stopping इस्तेमाल करें। Validation set पर n_estimators ऊँचा (1000–3000) और early_stopping_rounds=50 रखें। जब आप learning rate tune करें, तो हर trial के अंदर early stopping को trees की संख्या खोजने दें, क्योंकि यह learning rate के साथ बदलती है।
始终使用 early stopping。 在验证集上把 n_estimators 设大(1000–3000),并设 early_stopping_rounds=50。调学习率时,让 early stopping 在每个试验里找树的数量,因为它会随学习率变化。
2
A lower learning rate usually generalises better. Start at learning_rate=0.05. At the end, halve it and let early stopping roughly double the trees. This often gives a small extra gain, at about twice the training time.
कम learning rate आमतौर पर बेहतर generalise करता है। learning_rate=0.05 से शुरू करें। आख़िर में इसे आधा करें और early stopping को trees लगभग दोगुने करने दें। इससे अक्सर थोड़ा और फ़ायदा मिलता है, लगभग दोगुने training time पर।
较低的学习率通常泛化更好。 从 learning_rate=0.05 开始。最后把它减半,让 early stopping 把树大约翻倍。这常常能再带来一点提升,代价是训练时间约翻倍。
3
Tune max_depth and min_child_weight first. They are the most important tree parameters. For most tabular problems, max_depth=4–6 works well; going deeper rarely helps and raises the overfitting risk.
पहले max_depth और min_child_weight tune करें। ये सबसे ज़रूरी tree parameters हैं। ज़्यादातर tabular problems के लिए max_depth=4–6 अच्छा चलता है; ज़्यादा गहरा जाने से शायद ही फ़ायदा होता है और overfitting का ख़तरा बढ़ता है।
先调 max_depth 和 min_child_weight。 它们是最重要的树参数。对大多数表格问题,max_depth=4–6 效果很好;更深很少有帮助,还会增加过拟合风险。
4
Use row and column sampling. subsample and colsample_bytree between 0.6 and 0.9 make trees less alike and are among XGBoost's strongest tools against overfitting.
Row और column sampling इस्तेमाल करें। 0.6 और 0.9 के बीच subsample और colsample_bytree trees को कम एक जैसा बनाते हैं और overfitting के ख़िलाफ़ XGBoost के सबसे मज़बूत tools में से हैं।
使用行和列抽样。 把 subsample 和 colsample_bytree 设在 0.6–0.9,让树之间差异更大,这是 XGBoost 对抗过拟合最有力的工具之一。
5
Handle imbalance on purpose. Set scale_pos_weight = negatives / positives and use eval_metric='aucpr' (precision-recall AUC), which is more sensitive to the rare class than ROC-AUC. Then choose the decision threshold on validation data.
Imbalance को सोच-समझकर संभालें। scale_pos_weight = negatives / positives रखें और eval_metric='aucpr' (precision-recall AUC) इस्तेमाल करें, जो ROC-AUC से ज़्यादा rare class के प्रति sensitive है। फिर validation data पर decision threshold चुनें।
有意识地处理类别不平衡。 设 scale_pos_weight = 负类数 / 正类数,并使用 eval_metric='aucpr'(精确率-召回率 AUC),它比 ROC-AUC 对少数类更敏感。然后在验证集上选择决策阈值。
6
Pick the tuning strategy for your budget. Quick prototype → Random Search (50–100 iterations). Real project → Optuna TPE (80–150 trials) with pruning. Very slow fits → Bayesian GP (30–50 trials). Grid Search only for a final narrow sweep of 2–3 parameters.
अपने budget के हिसाब से tuning strategy चुनें। जल्दी prototype → Random Search (50–100 iterations)। असली project → pruning के साथ Optuna TPE (80–150 trials)। बहुत धीमे fits → Bayesian GP (30–50 trials)। Grid Search सिर्फ़ आख़िर में 2–3 parameters की छोटी जाँच के लिए।
根据预算选择调参策略。 快速原型 → 随机搜索(50–100 次)。实际项目 → 带剪枝的 Optuna TPE(80–150 次)。训练非常慢 → 贝叶斯 GP(30–50 次)。网格搜索只用于最后对 2–3 个参数的小范围扫描。
7
You do not need to impute missing values. XGBoost learns a default direction for NaN at every split. Imputing can even hide useful signal, because "missing" can itself carry information. If unsure, test both.
Missing values impute करने की ज़रूरत नहीं। XGBoost हर split पर NaN के लिए default direction सीखता है। Impute करने से उपयोगी signal छिप भी सकता है, क्योंकि "missing" होना खुद जानकारी दे सकता है। शक हो तो दोनों test करें।
不需要填补缺失值。 XGBoost 在每个分裂上都会为 NaN 学习默认方向。填补反而可能掩盖有用信号,因为"缺失"本身也可能携带信息。不确定时两种都试试。
8
Use SHAP to explain the model. Built-in importance is a quick check. SHAP gives consistent, per-row explanations with direction, and TreeExplainer is fast on XGBoost. Read correlated features together.
Model समझाने के लिए SHAP इस्तेमाल करें। Built-in importance एक जल्दी जाँच है। SHAP दिशा के साथ consistent, हर row की explanation देता है, और XGBoost पर TreeExplainer तेज़ है। Correlated features को साथ पढ़ें।
用 SHAP 解释 model。 内置重要性只是快速检查。SHAP 给出一致的、逐行的、带方向的解释,TreeExplainer 在 XGBoost 上很快。相关特征要放在一起看。

SectionSection第 18 节

XGBoost vs LightGBM vs CatBoost — Quick Decision GuideXGBoost vs LightGBM vs CatBoost — जल्दी फ़ैसलाXGBoost vs LightGBM vs CatBoost — 快速选择指南

Propertyगुण属性XGBoostLightGBMCatBoost
Default tree growthDefault tree growth默认生长方式Depth-wise (lossguide optional)Depth-wise (lossguide वैकल्पिक)按层(可选 lossguide)Leaf-wiseLeaf-wise按叶Symmetric (oblivious) treesSymmetric (oblivious) trees对称(oblivious)树
Training speedTraining speed训练速度Fast (hist)तेज़ (hist)快(hist)Often the fastestअक्सर सबसे तेज़通常最快Slower on large dense dataबड़े dense data पर धीमा大规模稠密数据上较慢
Categorical featuresCategorical features类别特征Native with enable_categorical=Trueenable_categorical=True के साथ native设 enable_categorical=True 后原生支持Native (category dtype)Native (category dtype)原生(category 类型)Excellent native supportबेहतरीन native support出色的原生支持
Missing valuesMissing values缺失值NativeNative原生NativeNative原生NativeNative原生
Very large data (>1M rows)बहुत बड़ा data (>1M rows)超大数据(>100 万行)Good (hist, GPU)अच्छा (hist, GPU)良好(hist、GPU)Excellentबेहतरीन出色Goodअच्छा良好
Sensitivity to settingsSettings के प्रति sensitivity对参数的敏感度Mediumमध्यम中High (num_leaves)ज़्यादा (num_leaves)高(num_leaves)Low (strong defaults)कम (मज़बूत defaults)低(默认值强)
🏆
The Practitioner's Decision Ruleव्यावहारिक फ़ैसले का नियम实践者的选择规则

Start with XGBoost for its reliability and huge documentation. Try LightGBM when training is too slow on very large data. Try CatBoost when you have many categorical columns or little time to tune. In competitions, people often blend all three.

Reliability और बहुत ज़्यादा documentation के लिए XGBoost से शुरू करें। बहुत बड़े data पर training बहुत धीमी हो तो LightGBM आज़माएँ। कई categorical columns हों या tuning का समय कम हो तो CatBoost आज़माएँ। Competitions में लोग अक्सर तीनों को मिला देते हैं।

因为可靠且文档丰富,先从 XGBoost 开始。在超大数据上训练太慢时试试 LightGBM。类别列很多或调参时间不多时试试 CatBoost。在比赛中,人们常把三者融合使用。

You have completed Supervised Learning. View all sections →