The Story That Explains Boostingवह कहानी जो Boosting समझाती है一个解释 Boosting 的故事
That is Boosting. Random Forest trains many independent models. Boosting trains models one after another. Each new model focuses on the examples the current team still gets wrong.
यही Boosting है। Random Forest कई independent models train करता है। Boosting models को एक के बाद एक train करता है। हर नया model उन examples पर ध्यान देता है जो मौजूदा टीम अभी भी गलत करती है।
这就是 Boosting。Random Forest 训练许多相互独立的 model,而 Boosting 一个接一个地训练 model。每个新 model 都专注于当前团队仍然做错的样本。
Boosting is a family of ensemble learning methods. The idea: combine many weak learners (models only a little better than guessing) into one strong learner. Each weak learner fixes what the earlier ones could not. The three most important members are:
Boosting, ensemble learning methods का एक परिवार है। विचार: कई weak learners (जो अंदाज़े से बस थोड़े बेहतर हों) को जोड़कर एक strong learner बनाना। हर weak learner वह ठीक करता है जो पहले वाले नहीं कर पाए। इसके तीन सबसे ज़रूरी सदस्य हैं:
Boosting 是一类 ensemble learning 方法。思路:把许多 weak learner(只比瞎猜好一点的 model)组合成一个 strong learner。每个 weak learner 修正前面的 learner 没能解决的问题。三个最重要的成员是:
Bagging (Random Forest) builds trees in parallel. Each tree is independent. The goal is lower variance. Boosting builds trees one after another, each fixing the last. The goal is lower bias. This makes boosting more powerful, but it can overfit if you do not regularise it and stop it in time.
Bagging (Random Forest) trees को parallel में बनाता है। हर tree independent है। लक्ष्य: कम variance. Boosting trees को एक के बाद एक बनाता है, हर tree पिछले को सुधारता है। लक्ष्य: कम bias. इससे boosting ज़्यादा ताक़तवर है, पर अगर आप उसे regularise न करें और समय पर न रोकें तो वह overfit कर सकता है।
Bagging(Random Forest)并行建树,每棵树相互独立,目标是降低 variance。Boosting 逐个建树,每棵树修正上一棵,目标是降低 bias。这让 boosting 更强大,但如果不加正则化、不及时停止,就会过拟合。
AdaBoost — Where It All StartedAdaBoost — जहाँ से सब शुरू हुआAdaBoost — 一切的起点
AdaBoost (Adaptive Boosting) was introduced by Freund & Schapire in the mid-1990s. Their work won the 2003 Gödel Prize. It is the simplest boosting method, and once you understand it, everything after it is easier.
AdaBoost (Adaptive Boosting) को Freund & Schapire ने 1990 के दशक के मध्य में पेश किया। उनके काम को 2003 का Gödel Prize मिला। यह सबसे सरल boosting method है, और इसे समझने के बाद आगे की हर चीज़ आसान हो जाती है।
AdaBoost(Adaptive Boosting)由 Freund 和 Schapire 在 1990 年代中期提出,他们的工作获得了 2003 年哥德尔奖。它是最简单的 boosting 方法,理解了它,后面的内容都会更容易。
The AdaBoost Algorithm — Step by StepAdaBoost Algorithm — Step by StepAdaBoost 算法 — 逐步讲解
8 samples. Every number here comes from the formulas above. After each update, the wrong points always hold half of the total weight. That forces the next stump to take them seriously.
8 samples. यहाँ का हर number ऊपर के formulas से आया है। हर update के बाद गलत points के पास हमेशा कुल weight का आधा होता है। इससे अगला stump उन्हें गंभीरता से लेने पर मजबूर होता है।
8 个样本。这里每个数字都来自上面的公式。每次更新后,错误点总是占总权重的一半,这迫使下一个 stump 认真对待它们。
Squares belong inside the circle; dots are outside. Each round adds one stump (purple dashed line). Point size = weight. Red ring = still wrong. Watch the live ε, α and weight multipliers.
Squares घेरे के अंदर हैं; dots बाहर। हर round एक stump जोड़ता है (बैंगनी dashed line)। Point का आकार = weight. लाल घेरा = अभी भी गलत। Live ε, α और weight multipliers देखें।
方块在圆内,圆点在圆外。每一轮加入一个 stump(紫色虚线)。点的大小 = 权重,红圈 = 仍然错误。观察实时的 ε、α 和权重乘数。
| RoundRound轮次 | |
| ε | |
| α |
Move ε. The curve is α = ½ · ln((1−ε)/ε). The red zone (ε > 0.5) is worse than a coin flip.
ε को खिसकाएँ। Curve है α = ½ · ln((1−ε)/ε). लाल क्षेत्र (ε > 0.5) सिक्का उछालने से भी बुरा है।
拖动 ε。曲线是 α = ½ · ln((1−ε)/ε)。红色区域(ε > 0.5)比抛硬币还差。
| α | |
| wrong weightगलत का weight错误点权重 × eα | |
| right weightसही का weight正确点权重 × e−α |
Gradient Boosting — The GeneralisationGradient Boosting — सामान्य रूपGradient Boosting — 推广形式
Gradient Boosting (Friedman, 1999; published 2001) took the idea of AdaBoost and turned it into gradient descent in function space. Instead of re-weighting samples, each new tree directly predicts the residual errors (more precisely, the negative gradients of the loss) of the current model.
Gradient Boosting (Friedman, 1999; प्रकाशित 2001) ने AdaBoost के विचार को function space में gradient descent बना दिया। Samples का weight बदलने के बजाय हर नया tree सीधे मौजूदा model की residual errors (सटीक रूप से, loss के negative gradients) predict करता है।
Gradient Boosting(Friedman,1999 年提出,2001 年发表)把 AdaBoost 的思想变成了函数空间中的梯度下降。它不再重新加权样本,而是让每棵新树直接预测当前 model 的残差(更准确地说,是 loss 的负梯度)。
Your model predicts ₹72 lakh for a house worth ₹100 lakh. The residual is 28. Train the next tree to predict 28 (the error), not 100. If the tree gets it right and the learning rate η = 0.1, the new prediction is 72 + 0.1 × 28 = 74.8. A bit closer. Repeat, and each tree removes part of what is left.
आपका model ₹100 lakh के घर के लिए ₹72 lakh predict करता है। Residual 28 है। अगले tree को 28 (error) predict करना सिखाएँ, 100 नहीं। अगर tree सही है और learning rate η = 0.1 है, तो नया prediction है 72 + 0.1 × 28 = 74.8. थोड़ा पास। दोहराते रहें, हर tree बचे हुए error का एक हिस्सा हटाता है।
你的 model 对一套价值 ₹100 lakh 的房子预测为 ₹72 lakh,残差是 28。训练下一棵树去预测 28(误差),而不是 100。如果树预测准确且学习率 η = 0.1,新预测就是 72 + 0.1 × 28 = 74.8,更接近了一点。不断重复,每棵树都消除一部分剩余误差。
Gradient Boosting — The AlgorithmGradient Boosting — AlgorithmGradient Boosting — 算法
Each round adds one tree whose only job is to predict the current mistakes. The learning rate η shrinks each tree, so no single tree can push the model too far.
हर round एक tree जोड़ता है जिसका एकमात्र काम मौजूदा गलतियाँ predict करना है। Learning rate η हर tree को छोटा करता है, ताकि कोई एक tree model को बहुत दूर न धकेले।
每一轮加入一棵树,它唯一的任务就是预测当前的错误。学习率 η 缩小每棵树的作用,避免任何一棵树把 model 推得太远。
Filled dots = training data. Hollow dots = validation data. Red lines = residuals (what is still wrong). Each round, one small tree fits those red lines, and the green curve moves. Below: training error keeps falling; validation error turns back up.
भरे dots = training data. खोखले dots = validation data. लाल lines = residuals (जो अभी भी गलत है)। हर round में एक छोटा tree उन लाल lines को fit करता है और हरा curve खिसकता है। नीचे: training error घटता रहता है; validation error फिर बढ़ने लगता है।
实心点 = 训练数据,空心点 = 验证数据,红线 = 残差(仍然错的部分)。每一轮,一棵小树拟合这些红线,绿色曲线随之移动。下方:训练误差持续下降,验证误差却会掉头上升。
Gradient Boosting From Scratch — 15 LinesGradient Boosting Scratch से — 15 Lines从零实现 Gradient Boosting — 15 行
The four formulas above fit in a short loop. The scikit-learn version with the same settings gives exactly the same training error, so this really is the whole algorithm (for MSE loss).
ऊपर के चार formulas एक छोटे loop में आ जाते हैं। उन्हीं settings वाला scikit-learn version बिल्कुल वही training error देता है, इसलिए (MSE loss के लिए) यही पूरा algorithm है।
上面四个公式可以写成一个很短的循环。相同设置下的 scikit-learn 版本给出完全相同的训练误差,所以(对 MSE loss 来说)这就是整个算法。
import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
# Toy data: a noisy sine wave
rng = np.random.default_rng(42)
X = np.sort(rng.uniform(0, 10, 200)).reshape(-1, 1)
y = 3 * np.sin(X).ravel() + rng.normal(0, 0.5, 200)
eta, n_rounds = 0.1, 100
F = np.full_like(y, y.mean()) # Step 1: F0 = mean of y
trees = []
for m in range(1, n_rounds + 1):
residuals = y - F # Step 2: residuals (negative gradient of MSE)
tree = DecisionTreeRegressor(max_depth=2).fit(X, residuals) # Step 3
F += eta * tree.predict(X) # Step 4: F_m = F_(m-1) + eta * h_m
trees.append(tree)
if m in (1, 5, 20, 50, 100):
print(f"Round {m:3d}: train MSE = {np.mean((y - F) ** 2):.4f}")
# Same settings in scikit-learn give the same answer
sk = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1,
max_depth=2, random_state=0).fit(X, y)
print(f"\nOur model : train MSE = {np.mean((y - F) ** 2):.4f}")
print(f"scikit-learn : train MSE = {np.mean((y - sk.predict(X)) ** 2):.4f}")
Three models with the same depth, different learning rates, trained side by side. The lines show validation error. The dots mark each model's lowest point.
एक ही depth पर अलग learning rates वाले तीन models साथ-साथ train होते हैं। Lines validation error दिखाती हैं। Dots हर model का सबसे निचला बिंदु दिखाते हैं।
三个深度相同、学习率不同的 model 同时训练。曲线是验证误差,圆点标出每个 model 的最低点。
XGBoost — Extreme Gradient BoostingXGBoost — Extreme Gradient BoostingXGBoost — 极端梯度提升
What Makes XGBoost DifferentXGBoost को क्या अलग बनाता हैXGBoost 有何不同
subsample and colsample_bytree/bylevel/bynode add randomness like Random Forest. Trees become less alike, which helps against overfitting.subsample और colsample_bytree/bylevel/bynode Random Forest जैसी randomness जोड़ते हैं। Trees कम एक जैसे होते हैं, जिससे overfitting घटता है।subsample 和 colsample_bytree/bylevel/bynode 像 Random Forest 一样加入随机性,让树之间差异更大,有助于防止过拟合。device='cuda' it trains on a GPU, which is often many times faster on large data.device='cuda' से GPU पर train होता है, जो बड़े data पर अक्सर कई गुना तेज़ है।device='cuda' 可在 GPU 上训练,在大数据上通常快很多倍。The XGBoost Objective FunctionXGBoost Objective FunctionXGBoost 目标函数
Plain gradient boosting follows the slope and then picks a step size. XGBoost also uses the curvature (second derivative), so each leaf gets a well-sized step straight away, like Newton's method. For log-loss this often means good results with fewer trees. For MSE the Hessian is constant (h = 1), so the two methods behave the same way.
साधारण gradient boosting ढलान का पीछा करता है और फिर step size चुनता है। XGBoost curvature (second derivative) भी इस्तेमाल करता है, इसलिए हर leaf को तुरंत सही आकार का step मिलता है, Newton's method की तरह। Log-loss में इसका मतलब अक्सर कम trees में अच्छे results है। MSE में Hessian constant (h = 1) है, इसलिए दोनों methods एक जैसे चलते हैं।
普通梯度提升沿着斜率走,然后再选步长。XGBoost 还使用曲率(二阶导数),所以每个叶子一开始就得到合适的步长,就像牛顿法。对 log-loss,这通常意味着用更少的树就能得到好结果。对 MSE,Hessian 是常数(h = 1),两种方法表现一样。
Every number follows from the formulas above. The right-hand split has Gain = −0.16, which is below zero after subtracting γ, so XGBoost prunes it and keeps one leaf.
हर number ऊपर के formulas से आता है। दाईं ओर के split का Gain = −0.16 है, जो γ घटाने के बाद zero से कम है, इसलिए XGBoost उसे prune करके एक ही leaf रखता है।
每个数字都由上面的公式算出。右侧分裂的 Gain = −0.16,减去 γ 后小于 0,所以 XGBoost 把它剪掉,只保留一个叶子。
10 houses sorted by size. Bars = residuals the next tree must fix. Move the split. Change λ and γ. The thick lines are the leaf weights w*. The small bars at the bottom show the gain of every possible split.
10 घर size के क्रम में। Bars = residuals जिन्हें अगले tree को ठीक करना है। Split खिसकाएँ। λ और γ बदलें। मोटी lines leaf weights w* हैं। नीचे की छोटी bars हर संभव split का gain दिखाती हैं।
10 套房子按面积排序。柱子 = 下一棵树要修正的残差。移动分裂点,改变 λ 和 γ。粗线是叶子权重 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 收缩。把 γ 调大,直到连最佳分裂也变红:树就不再生长。
The split is "Age < 30". Three passengers have no Age. XGBoost tries sending them left, then right, computes the gain for each (λ = 1), and keeps the better one. That choice is stored in the tree.
Split है "Age < 30"। तीन passengers की Age नहीं है। XGBoost उन्हें पहले left, फिर right भेजकर देखता है, हर एक का gain (λ = 1) निकालता है, और बेहतर वाला रखता है। यह फ़ैसला tree में save हो जाता है।
分裂条件是 "Age < 30"。有三位乘客没有 Age。XGBoost 先试着把他们放到左边,再放到右边,分别计算增益(λ = 1),保留更好的那个。这个选择会被存进树里。
Small number = residual of that passenger.छोटी संख्या = उस passenger का residual.小数字 = 该乘客的残差。
Python Implementation — AdaBoostPython Implementation — AdaBoostPython 实现 — AdaBoost
Let's start with AdaBoost on a classic yes/no problem: will a bank customer default on a loan? (The data is synthetic.)
AdaBoost से एक classic हाँ/नहीं वाले सवाल पर शुरू करें: क्या bank customer loan default करेगा? (Data synthetic है।)
先用 AdaBoost 解决一个经典的是/否问题:银行客户会不会贷款违约?(数据是合成的。)
import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import classification_report, roc_auc_score
from sklearn.datasets import make_classification
# ── Synthetic "loan default" dataset ──────────────────────
X, y = make_classification(
n_samples=5000, n_features=15, n_informative=10,
n_redundant=3, class_sep=0.8, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# ── AdaBoost with decision stumps (depth = 1) ─────────────
# Note: do NOT pass algorithm='SAMME'. That parameter was removed
# from recent scikit-learn; SAMME is now the only algorithm.
ada = AdaBoostClassifier(
estimator=DecisionTreeClassifier(max_depth=1),
n_estimators=200, # number of stumps / boosting rounds
learning_rate=0.5, # shrinks each stump's vote
random_state=42
)
# ── Cross-validation ──────────────────────────────────────
cv_auc = cross_val_score(ada, X_train, y_train, cv=5, scoring='roc_auc')
print(f"CV ROC-AUC : {cv_auc.mean():.4f} ± {cv_auc.std():.4f}")
# ── Fit and evaluate ──────────────────────────────────────
ada.fit(X_train, y_train)
y_pred = ada.predict(X_test)
y_proba = ada.predict_proba(X_test)[:, 1]
print(f"Test ROC-AUC: {roc_auc_score(y_test, y_proba):.4f}\n")
print(classification_report(y_test, y_pred))
# ── Look at the stump weights (alpha) ─────────────────────
print("Top 5 stump weights:")
for i in np.argsort(ada.estimator_weights_)[::-1][:5]:
print(f" Stump {i:3d}: weight = {ada.estimator_weights_[i]:.4f}")
1. Older code passes algorithm='SAMME'. That parameter was deprecated in scikit-learn 1.6 and is now removed, so old code crashes. Just delete it.
2. estimator_weights_ are not the textbook α. For two classes, scikit-learn stores learning_rate × ln((1−ε)/ε), which is 2 × learning_rate × α. The model is the same; only the scale differs.
1. पुराना code algorithm='SAMME' देता है। यह parameter scikit-learn 1.6 में deprecated हुआ और अब हटा दिया गया है, इसलिए पुराना code crash होता है। बस इसे हटा दें।
2. estimator_weights_ textbook वाला α नहीं हैं। दो classes के लिए scikit-learn learning_rate × ln((1−ε)/ε) रखता है, जो 2 × learning_rate × α है। Model वही है; सिर्फ़ scale अलग है।
1. 旧代码会传入 algorithm='SAMME'。这个参数在 scikit-learn 1.6 中已弃用,现在已移除,旧代码会报错,直接删掉即可。
2. estimator_weights_ 不是教科书里的 α。对二分类,scikit-learn 存储的是 learning_rate × ln((1−ε)/ε),即 2 × learning_rate × α。model 是一样的,只是尺度不同。
Python Implementation — XGBoost End-to-EndPython Implementation — XGBoost शुरू से अंत तकPython 实现 — XGBoost 端到端
Now the real workhorse: a full XGBoost pipeline on the classic Titanic survival data (Kaggle train.csv, 891 passengers), with feature engineering, early stopping and annotated hyperparameters.
अब असली workhorse: classic Titanic survival data (Kaggle train.csv, 891 passengers) पर पूरी XGBoost pipeline, feature engineering, early stopping और समझाए गए hyperparameters के साथ।
现在来看真正的主力:在经典的 Titanic 生存数据(Kaggle train.csv,891 名乘客)上搭建完整的 XGBoost 流程,包括特征工程、early stopping 和带注释的超参数。
import xgboost as xgb
import pandas as pd
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score
from sklearn.preprocessing import LabelEncoder
# ── Load data (Kaggle Titanic train.csv) ──────────────────
df = pd.read_csv('titanic.csv')
# ── Feature engineering ───────────────────────────────────
df['Title'] = df['Name'].str.extract(r' ([A-Za-z]+)\.', expand=False)
df['Title'] = df['Title'].replace({
'Mlle': 'Miss', 'Ms': 'Miss', 'Mme': 'Mrs',
'Lady': 'Rare', 'Countess': 'Rare', 'Capt': 'Rare', 'Col': 'Rare',
'Don': 'Rare', 'Dr': 'Rare', 'Major': 'Rare', 'Rev': 'Rare',
'Sir': 'Rare', 'Jonkheer': 'Rare', 'Dona': 'Rare'
})
df['FamilySize'] = df['SibSp'] + df['Parch'] + 1
df['IsAlone'] = (df['FamilySize'] == 1).astype(int)
# pandas 3: assign back. df['Age'].fillna(..., inplace=True) does NOTHING.
# (XGBoost can also handle NaN itself; we fill here only for Embarked/Fare.)
df['Embarked'] = df['Embarked'].fillna(df['Embarked'].mode()[0])
df['Fare'] = df['Fare'].fillna(df['Fare'].median())
# Encode text columns as integers
for col in ['Sex', 'Embarked', 'Title']:
df[col] = LabelEncoder().fit_transform(df[col].astype(str))
features = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch',
'Fare', 'Embarked', 'Title', 'FamilySize', 'IsAlone']
X, y = df[features], df['Survived'] # Age keeps its NaNs on purpose
# ── XGBoost model — annotated hyperparameters ─────────────
model = xgb.XGBClassifier(
# Boosting structure
n_estimators = 1000, # upper limit; early stopping picks the real number
learning_rate = 0.05, # eta: shrinks each tree's contribution
max_depth = 4, # tree depth: 3-6 is typical
# Regularisation
reg_alpha = 0.1, # L1 on leaf weights
reg_lambda = 1.0, # L2 on leaf weights
gamma = 0.05, # minimum gain needed to split
min_child_weight = 3, # minimum Hessian sum in a leaf
# Randomisation (like Random Forest)
subsample = 0.8, # rows per tree
colsample_bytree = 0.7, # columns per tree
# Performance
tree_method = 'hist', # fast histogram splits (the default in XGBoost 2+)
device = 'cpu', # 'cuda' for GPU
n_jobs = -1,
random_state = 42,
eval_metric = 'logloss', # smooth metric: better for early stopping than AUC
early_stopping_rounds = 50 # stop after 50 rounds with no improvement
)
# ── Hold out a validation set for early stopping ──────────
X_tr, X_val, y_tr, y_val = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=50)
print(f"\nBest iteration : {model.best_iteration}")
print(f"Best val loss : {model.best_score:.4f}")
# ── Cross-validated AUC with the chosen number of trees ───
cv_model = xgb.XGBClassifier(
n_estimators=model.best_iteration + 1, # best_iteration is 0-based
learning_rate=0.05, max_depth=4, subsample=0.8,
colsample_bytree=0.7, tree_method='hist', n_jobs=-1, random_state=42
)
cv = StratifiedKFold(5, shuffle=True, random_state=42)
cv_auc = cross_val_score(cv_model, X, y, cv=cv, scoring='roc_auc')
print(f"CV ROC-AUC : {cv_auc.mean():.4f} ± {cv_auc.std():.4f}")
# ── Feature importance (the default type is 'gain') ───────
imp = pd.Series(model.feature_importances_, index=features)
print("\nFeature importance (gain):")
print(imp.sort_values(ascending=False).round(4).to_string())
Many tutorials write df['Age'].fillna(x, inplace=True). In pandas 3 (Copy-on-Write), this changes a temporary copy, and df stays the same. Always assign back: df['Age'] = df['Age'].fillna(x). Here we leave Age empty on purpose, because XGBoost handles NaN by itself.
कई tutorials df['Age'].fillna(x, inplace=True) लिखते हैं। pandas 3 (Copy-on-Write) में यह एक temporary copy बदलता है, और df वैसा ही रहता है। हमेशा वापस assign करें: df['Age'] = df['Age'].fillna(x). यहाँ हम Age को जानबूझकर खाली छोड़ते हैं, क्योंकि XGBoost NaN को खुद संभालता है।
很多教程写 df['Age'].fillna(x, inplace=True)。在 pandas 3(Copy-on-Write)中,这只会修改一个临时副本,df 本身不变。一定要赋值回去:df['Age'] = df['Age'].fillna(x)。这里我们故意让 Age 保持缺失,因为 XGBoost 能自己处理 NaN。
Set n_estimators high and add early_stopping_rounds with a validation set. Training stops when the validation score stops improving. Here it stopped at round 49 out of a possible 1000. Two tips from this run: (1) stop on logloss, not AUC. On small validation sets AUC is jumpy. With AUC this same model stopped at round 3 and its CV AUC fell from 0.881 to 0.872. (2) best_iteration counts from 0, so retrain with best_iteration + 1 trees.
n_estimators ऊँचा रखें और validation set के साथ early_stopping_rounds जोड़ें। जब validation score सुधरना बंद करता है तो training रुक जाती है। यहाँ यह 1000 में से round 49 पर रुकी। इस run से दो tips: (1) AUC नहीं, logloss पर रोकें। छोटे validation sets पर AUC उछलता है। AUC के साथ यही model round 3 पर रुका और उसका CV AUC 0.881 से गिरकर 0.872 हो गया। (2) best_iteration 0 से गिनता है, इसलिए best_iteration + 1 trees के साथ दोबारा train करें।
把 n_estimators 设大,并配合验证集使用 early_stopping_rounds。验证分数不再提升时训练就会停止。这里它在 1000 轮中的第 49 轮停下。从这次运行得到两个建议:(1) 用 logloss 而不是 AUC 来停止。小验证集上 AUC 波动大,用 AUC 时同一个 model 在第 3 轮就停了,CV AUC 从 0.881 降到 0.872。(2) best_iteration 从 0 开始计数,所以重新训练时用 best_iteration + 1 棵树。
XGBoost for RegressionRegression के लिए XGBoostXGBoost 回归
XGBoost works just as well for regression. You mainly change the objective. Here we predict house prices in California.
XGBoost regression के लिए भी उतना ही अच्छा है। मुख्य रूप से आप objective बदलते हैं। यहाँ हम California में घरों की कीमत predict करते हैं।
XGBoost 做回归同样出色,主要只需改 objective。这里我们预测加州的房价。
import numpy as np
import xgboost as xgb
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.metrics import root_mean_squared_error, mean_absolute_error, r2_score
# ── Load California housing ───────────────────────────────
data = fetch_california_housing(as_frame=True)
X, y = data.data, data.target # y = median house value in $100,000
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
X_tr, X_val, y_tr, y_val = train_test_split(
X_train, y_train, test_size=0.15, random_state=42
)
# ── XGBoost regressor ─────────────────────────────────────
reg = xgb.XGBRegressor(
objective = 'reg:squarederror', # MSE loss
n_estimators = 3000,
learning_rate = 0.04,
max_depth = 5,
min_child_weight = 5,
subsample = 0.8,
colsample_bytree = 0.8,
reg_alpha = 0.05,
reg_lambda = 1.5,
gamma = 0.1,
tree_method = 'hist',
eval_metric = 'rmse',
early_stopping_rounds = 50,
n_jobs = -1,
random_state = 42
)
reg.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], verbose=200)
# ── Evaluate on the untouched test set ────────────────────
y_pred = reg.predict(X_test)
print(f"\nTest RMSE : {root_mean_squared_error(y_test, y_pred):.4f}")
print(f"Test MAE : {mean_absolute_error(y_test, y_pred):.4f}")
print(f"Test R² : {r2_score(y_test, y_pred):.4f}")
print(f"Best iter : {reg.best_iteration}")
Some versions of this example compute RMSE as sqrt(MAE² + var(error)). That is not RMSE: MAE² is not the same as the squared mean error, so the number is wrong. Use root_mean_squared_error (scikit-learn 1.4+) or np.sqrt(mean_squared_error(...)). Also note that early stopping never touched the test set; it used the separate validation split.
इस example के कुछ versions RMSE को sqrt(MAE² + var(error)) से निकालते हैं। यह RMSE नहीं है: MAE², squared mean error के बराबर नहीं होता, इसलिए number गलत आता है। root_mean_squared_error (scikit-learn 1.4+) या np.sqrt(mean_squared_error(...)) इस्तेमाल करें। यह भी देखें कि early stopping ने test set को कभी नहीं छुआ; उसने अलग validation split इस्तेमाल किया।
这个例子的某些版本用 sqrt(MAE² + var(error)) 计算 RMSE。这不是 RMSE:MAE² 不等于平均误差的平方,所以结果是错的。请使用 root_mean_squared_error(scikit-learn 1.4+)或 np.sqrt(mean_squared_error(...))。另外注意,early stopping 从未接触测试集,它用的是单独的验证集。
Hyperparameter Guide — The Complete ReferenceHyperparameter Guide — पूरा Reference超参数指南 — 完整参考
XGBoost has dozens of hyperparameters. These are the ones that matter in practice. Defaults are for XGBoost 2.x/3.x.
XGBoost में दर्जनों hyperparameters हैं। ये वे हैं जो असल में मायने रखते हैं। Defaults XGBoost 2.x/3.x के हैं।
XGBoost 有几十个超参数,下面是实践中真正重要的。默认值适用于 XGBoost 2.x/3.x。
| Parameter | Default | Effectअसर作用 | How to tuneकैसे tune करें如何调整 |
|---|---|---|---|
n_estimators | 100 | Number of boosting rounds (trees)Boosting rounds (trees) की संख्या提升轮数(树的数量) | Set high, use early stoppingऊँचा रखें, early stopping लगाएँ设大,用 early stopping |
learning_rate (η) | 0.3 | Shrinks each tree. Lower = more trees, usually better generalisationहर tree को छोटा करता है। कम = ज़्यादा trees, आमतौर पर बेहतर generalisation缩小每棵树的作用。越低 = 树越多,通常泛化更好 | 0.01–0.1 for the final modelFinal model के लिए 0.01–0.1最终 model 用 0.01–0.1 |
max_depth | 6 | Depth of each tree. Deeper = more complex, more overfit riskहर tree की depth. ज़्यादा = ज़्यादा complex, overfit का ख़तरा每棵树的深度。越深越复杂,过拟合风险越高 | 3–6 is the usual rangeआमतौर पर 3–6通常 3–6 |
min_child_weight | 1 | Minimum Hessian sum in a leaf. Higher = more careful splitsLeaf में न्यूनतम Hessian जोड़। ज़्यादा = ज़्यादा सावधान splits叶子中 Hessian 和的最小值。越高分裂越保守 | 1–10; raise if overfitting1–10; overfit हो तो बढ़ाएँ1–10;过拟合时调大 |
gamma (γ) | 0 | Minimum gain needed to split. Prunes weak splitsSplit के लिए न्यूनतम gain. कमज़ोर splits prune करता है分裂所需的最小增益,剪掉弱分裂 | 0–5; raise if overfitting0–5; overfit हो तो बढ़ाएँ0–5;过拟合时调大 |
subsample | 1.0 | Share of rows used per treeहर tree के लिए rows का हिस्सा每棵树使用的行比例 | 0.6–0.9 reduces overfitting0.6–0.9 overfitting घटाता है0.6–0.9 可减少过拟合 |
colsample_bytree | 1.0 | Share of columns used per treeहर tree के लिए columns का हिस्सा每棵树使用的列比例 | 0.5–0.9; try 0.7 first0.5–0.9; पहले 0.7 आज़माएँ0.5–0.9;先试 0.7 |
reg_alpha (α) | 0 | L1 penalty on leaf weightsLeaf weights पर L1 penalty叶子权重的 L1 惩罚 | 0, 0.01, 0.1, 1 |
reg_lambda (λ) | 1 | L2 penalty on leaf weights. Shrinks them toward 0Leaf weights पर L2 penalty. उन्हें 0 की ओर सिकोड़ता है叶子权重的 L2 惩罚,把它们向 0 收缩 | 1, 2, 5; raise if overfitting1, 2, 5; overfit हो तो बढ़ाएँ1, 2, 5;过拟合时调大 |
scale_pos_weight | 1 | For imbalanced classesImbalanced classes के लिए用于类别不平衡 | sum(neg) / sum(pos) |
tree_method | 'hist' | How splits are searched. 'hist' is the default since XGBoost 2.0Splits कैसे खोजे जाते हैं। XGBoost 2.0 से 'hist' default है如何搜索分裂点。从 XGBoost 2.0 起默认是 'hist' | Keep 'hist'; 'exact' only for small data'hist' रखें; 'exact' सिर्फ़ छोटे data के लिए保持 'hist';只有小数据才用 'exact' |
① Fix learning_rate=0.1 and find the number of trees with early stopping. ② Tune max_depth and min_child_weight together. ③ Tune gamma. ④ Tune subsample and colsample_bytree. ⑤ Tune reg_alpha and reg_lambda. ⑥ Lower learning_rate and retrain with more trees. This avoids searching a 10-dimensional space blindly. Or let Optuna do it (next section).
① learning_rate=0.1 तय करें और early stopping से trees की संख्या खोजें। ② max_depth और min_child_weight साथ tune करें। ③ gamma tune करें। ④ subsample और colsample_bytree tune करें। ⑤ reg_alpha और reg_lambda tune करें। ⑥ learning_rate घटाएँ और ज़्यादा trees के साथ दोबारा train करें। इससे 10-dimensional space में अंधेरे में खोज से बचते हैं। या यह काम Optuna को करने दें (अगला section)।
① 固定 learning_rate=0.1,用 early stopping 找出树的数量。② 一起调 max_depth 和 min_child_weight。③ 调 gamma。④ 调 subsample 和 colsample_bytree。⑤ 调 reg_alpha 和 reg_lambda。⑥ 降低 learning_rate,用更多树重新训练。这样可以避免在 10 维空间里盲目搜索。或者让 Optuna 来做(下一节)。
Hyperparameter Tuning with OptunaOptuna से Hyperparameter Tuning用 Optuna 调超参数
Manual tuning works, but Optuna's smart (Bayesian-style) search is faster and often finds better combinations. Here it searches 9 hyperparameters on the Titanic data from Section 06.
Manual tuning काम करती है, पर Optuna की smart (Bayesian-style) search तेज़ है और अक्सर बेहतर combinations खोजती है। यहाँ यह Section 06 के Titanic data पर 9 hyperparameters खोजती है।
手动调参可行,但 Optuna 的智能(贝叶斯式)搜索更快,常常能找到更好的组合。这里它在第 06 节的 Titanic 数据上搜索 9 个超参数。
import optuna
import xgboost as xgb
from sklearn.model_selection import StratifiedKFold, cross_val_score
optuna.logging.set_verbosity(optuna.logging.WARNING) # quiet output
# X, y: the Titanic features from the previous section
def objective(trial):
params = {
'n_estimators' : trial.suggest_int('n_estimators', 100, 800),
'learning_rate' : trial.suggest_float('learning_rate', 0.01, 0.3, log=True),
'max_depth' : trial.suggest_int('max_depth', 2, 8),
'min_child_weight': trial.suggest_int('min_child_weight', 1, 10),
'gamma' : trial.suggest_float('gamma', 0, 5),
'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-8, 10, log=True),
'reg_lambda' : trial.suggest_float('reg_lambda', 1e-8, 10, log=True),
}
model = xgb.XGBClassifier(**params, tree_method='hist', n_jobs=-1, random_state=42)
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
return cross_val_score(model, X, y, cv=cv, scoring='roc_auc').mean()
study = optuna.create_study(direction='maximize',
sampler=optuna.samplers.TPESampler(seed=42))
study.optimize(objective, n_trials=100, timeout=300) # 5 minutes max
print(f"Trials run : {len(study.trials)}")
print(f"Best AUC : {study.best_value:.4f}")
print("Best params:")
for k, v in study.best_params.items():
print(f" {k:<17}: {v:.4g}" if isinstance(v, float) else f" {k:<17}: {v}")
# ── Retrain the final model with the best params ──────────
best = xgb.XGBClassifier(**study.best_params, tree_method='hist',
n_jobs=-1, random_state=42)
best.fit(X, y)
After 100 trials, the best CV AUC is 0.889, up from 0.881 with our hand-picked settings. Notice the pattern Optuna found: a very low learning rate (0.015) with many trees (479). That matches the advice in the table above.
100 trials के बाद best CV AUC 0.889 है, हमारी हाथ से चुनी settings के 0.881 से ज़्यादा। Optuna को मिला pattern देखें: बहुत कम learning rate (0.015) और कई trees (479)। यह ऊपर की table की सलाह से मेल खाता है।
100 次试验后,最佳 CV AUC 为 0.889,高于我们手动选择参数时的 0.881。注意 Optuna 找到的规律:很低的学习率(0.015)加上很多树(479 棵),这和上表的建议一致。
Feature Importance in XGBoost — Three TypesXGBoost में Feature Importance — तीन प्रकारXGBoost 特征重要性 — 三种类型
XGBoost can measure feature importance in three ways. They tell different stories, and on real data they can disagree a lot.
XGBoost feature importance को तीन तरीकों से माप सकता है। वे अलग कहानियाँ बताते हैं, और असली data पर उनमें बहुत अंतर हो सकता है।
XGBoost 可以用三种方式衡量特征重要性。它们讲述的故事不同,在真实数据上可能差别很大。
feature_importances_.feature_importances_ का default यही है।feature_importances_ 的默认值。import matplotlib.pyplot as plt
from xgboost import plot_importance
import shap
# `model` and `X_val` come from the Titanic example above
booster = model.get_booster()
# ── The three built-in importance types ───────────────────
for imp_type in ['weight', 'gain', 'cover']:
scores = booster.get_score(importance_type=imp_type)
top3 = sorted(scores.items(), key=lambda kv: -kv[1])[:3]
print(f"{imp_type:<7}: " + ", ".join(f"{f} ({v:.1f})" for f, v in top3))
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for ax, imp_type in zip(axes, ['weight', 'gain', 'cover']):
plot_importance(model, importance_type=imp_type, ax=ax,
title=f'Importance ({imp_type})')
plt.tight_layout()
plt.savefig('xgb_importance.png', dpi=150)
# ── SHAP values: the most reliable importance ─────────────
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_val)
mean_abs = abs(shap_values).mean(axis=0)
top3 = sorted(zip(X_val.columns, mean_abs), key=lambda kv: -kv[1])[:3]
print("SHAP : " + ", ".join(f"{f} ({v:.3f})" for f, v in top3))
shap.summary_plot(shap_values, X_val, plot_type='bar', show=False)
Real numbers from the Titanic model above (shares add up to 100%). Switch between the importance types and watch the ranking change.
ऊपर वाले Titanic model के असली numbers (हिस्सों का जोड़ 100%)। Importance types के बीच बदलें और ranking बदलते देखें।
来自上面 Titanic model 的真实数字(各项之和为 100%)。在不同的重要性类型之间切换,看排名如何变化。
Built-in scores are quick checks, but as you just saw, "weight" ranked Fare and Age first while every other method ranked Sex first. SHAP values (SHapley Additive exPlanations) come from game theory, are consistent, and show the direction of each feature's effect, not just its size. Use SHAP for any model that goes into production or a client presentation.
Built-in scores जल्दी जाँच के लिए हैं, पर जैसा आपने अभी देखा, "weight" ने Fare और Age को पहले रखा जबकि बाकी हर method ने Sex को पहले रखा। SHAP values (SHapley Additive exPlanations) game theory से आती हैं, consistent हैं, और हर feature के असर की दिशा भी दिखाती हैं, सिर्फ़ आकार नहीं। Production या client presentation में जाने वाले हर model के लिए SHAP इस्तेमाल करें।
内置分数适合快速检查,但正如你刚才看到的,"weight" 把 Fare 和 Age 排在最前,而其他所有方法都把 Sex 排第一。SHAP 值(SHapley Additive exPlanations)来自博弈论,具有一致性,并能显示每个特征影响的方向,而不只是大小。任何要上线或给客户展示的 model 都应使用 SHAP。
The Full Boosting LandscapeBoosting का पूरा नक्शाBoosting 全景图
XGBoost is the best-known member of the gradient boosting family. LightGBM grows trees leaf-wise and is often faster on very large data. CatBoost handles categorical features natively and is strong with little tuning.
XGBoost, gradient boosting परिवार का सबसे जाना-माना सदस्य है। LightGBM trees को leaf-wise उगाता है और बहुत बड़े data पर अक्सर तेज़ है। CatBoost categorical features को खुद संभालता है और कम tuning में अच्छा करता है।
XGBoost 是梯度提升家族中最知名的成员。LightGBM 按叶子生长,在超大数据上通常更快。CatBoost 原生处理类别特征,几乎不调参也表现很好。
Boosting vs Random Forest — When to Use WhichBoosting vs Random Forest — कब कौन-साBoosting vs Random Forest — 何时用哪个
| Dimensionपहलू方面 | Random Forest | XGBoost / Gradient Boosting |
|---|---|---|
| How trees are builtTrees कैसे बनते हैं如何建树 | Parallel, independentParallel, independent并行、独立 | One after another, each fixes the lastएक के बाद एक, हर tree पिछले को सुधारता है逐个构建,每棵修正上一棵 |
| What it reducesक्या घटाता है降低什么 | VarianceVarianceVariance | Bias (and variance through regularisation)Bias (और regularisation से variance)Bias(通过正则化也降低 variance) |
| Overfitting riskOverfitting का ख़तरा过拟合风险 | Lowकम低 | Higher: needs early stoppingज़्यादा: early stopping चाहिए较高:需要 early stopping |
| Training speedTraining speed训练速度 | Fast, easy to paralleliseतेज़, आसानी से parallel快,易并行 | Rounds are sequential (each tree is built in parallel)Rounds sequential हैं (हर tree parallel में बनता है)轮次是串行的(每棵树内部并行) |
| Sensitivity to settingsSettings के प्रति sensitivity对参数的敏感度 | Low: defaults work wellकम: defaults अच्छे हैं低:默认值就很好 | High: needs tuningज़्यादा: tuning चाहिए高:需要调参 |
| Peak accuracy (tabular)Peak accuracy (tabular)峰值精度(表格) | Very goodबहुत अच्छी很好 | Often the highestअक्सर सबसे ज़्यादा通常最高 |
| Missing valuesMissing values缺失值 | scikit-learn 1.4+ supports NaN; older versions need imputationscikit-learn 1.4+ NaN support करता है; पुराने versions में imputation चाहिएscikit-learn 1.4+ 支持 NaN;旧版本需要填补 | Handled nativelyखुद संभालता है原生处理 |
| InterpretabilityInterpretability可解释性 | Moderate (importance, SHAP)मध्यम (importance, SHAP)中等(重要性、SHAP) | Moderate (SHAP)मध्यम (SHAP)中等(SHAP) |
| Best choice when…सबसे अच्छा जब…最适合… | You want a fast, robust baselineआपको तेज़, robust baseline चाहिए需要快速、稳健的 baseline | You want maximum accuracy and can tuneआपको ज़्यादा से ज़्यादा accuracy चाहिए और tuning कर सकते हैं追求最高精度且愿意调参 |
Common Mistakes & How to Avoid Themआम गलतियाँ और उनसे कैसे बचें常见错误及避免方法
learning_rate=0.3, n_estimators=100 without early stopping: the model ends up under- or over-trained.learning_rate=0.3, n_estimators=100 इस्तेमाल करना: model या तो कम या ज़्यादा train होता है।learning_rate=0.3、n_estimators=100:model 不是欠训练就是过训练。n_estimators by hand. Very wasteful: early stopping does it for free.n_estimators को हाथ से grid-search करना। बहुत बर्बादी: early stopping यह मुफ़्त में करता है।n_estimators。非常浪费:early stopping 可以免费做到。learning_rate=0.05–0.1, a high n_estimators, and early_stopping_rounds=30–50 on a validation set.learning_rate=0.05–0.1, ऊँचा n_estimators, और early_stopping_rounds=30–50 इस्तेमाल करें।learning_rate=0.05–0.1、较大的 n_estimators 和 early_stopping_rounds=30–50。enable_categorical=True with pandas category columns.category columns के साथ enable_categorical=True इस्तेमाल करें।category 列使用 enable_categorical=True。n_estimators high and let early stopping pick the round.n_estimators ऊँचा रखें और early stopping को round चुनने दें।n_estimators 设大,让 early stopping 选择轮次。scale_pos_weight = neg / pos and judge with ROC-AUC, PR-AUC or F1.scale_pos_weight = neg / pos रखें और ROC-AUC, PR-AUC या F1 से परखें।scale_pos_weight = neg / pos,用 ROC-AUC、PR-AUC 或 F1 来评估。Golden RulesGolden Rules黄金法则
n_estimators high and early_stopping_rounds=30–50 on a validation set. Stop on a smooth metric like logloss. Do not grid-search the number of trees.n_estimators ऊँचा और early_stopping_rounds=30–50 रखें। logloss जैसे smooth metric पर रोकें। Trees की संख्या को grid-search न करें।n_estimators 设大,并设 early_stopping_rounds=30–50。用 logloss 这类平滑指标来停止。不要网格搜索树的数量。learning_rate=0.05 with more trees usually matches or beats 0.3 with fewer, and it is far more forgiving about when you stop (see the learning-rate race). Optuna also picked η ≈ 0.015 on Titanic.learning_rate=0.05 और ज़्यादा trees आमतौर पर 0.3 और कम trees के बराबर या बेहतर होते हैं, और रुकने के समय को लेकर बहुत ज़्यादा माफ़ करने वाले हैं (learning-rate race देखें)। Titanic पर Optuna ने भी η ≈ 0.015 चुना।learning_rate=0.05 配更多树,通常不输于甚至胜过 0.3 配更少树,而且对何时停止宽容得多(见学习率赛跑)。在 Titanic 上 Optuna 也选择了 η ≈ 0.015。subsample=0.8 and colsample_bytree=0.7 make trees less alike and usually reduce overfitting at little cost.subsample=0.8 और colsample_bytree=0.7 trees को कम एक जैसा बनाते हैं और आमतौर पर कम कीमत पर overfitting घटाते हैं।subsample=0.8 和 colsample_bytree=0.7 让树之间差异更大,通常以很小的代价减少过拟合。tree_method='hist'. It is the default since XGBoost 2.0, much faster than 'exact' on large data, and its accuracy is almost always the same.tree_method='hist' रखें। यह XGBoost 2.0 से default है, बड़े data पर 'exact' से बहुत तेज़ है, और इसकी accuracy लगभग हमेशा वही रहती है।tree_method='hist'。 从 XGBoost 2.0 开始它就是默认值,在大数据上比 'exact' 快得多,精度几乎总是一样。shap.TreeExplainer for anything you show to stakeholders or put into production.shap.TreeExplainer इस्तेमाल करें।shap.TreeExplainer。