XGBoost Python 完整教程
目录
- 什么是 XGBoost?
- 简介
- 为什么选择 XGBoost?(核心优势)
- 安装与环境准备
- 安装 XGBoost
- 验证安装
- XGBoost 基础:从数据到模型
- 第一个模型:回归任务
- 关键参数解析
- 模型评估
- XGBoost 核心概念
- GBDT vs. XGBoost:它们有什么不同?
- 正则化:防止过拟合的关键
- 损失函数:目标是什么?
- 基学习器:CART 回归树
- 分类任务实战
- 二分类
- 多分类
- 高级特性
- 提前停止:找到最佳迭代次数
- 特征重要性:理解模型
- 处理缺失值:XGBoost 的独特优势
- 交叉验证:
XGBClassifier内置 CV
- Scikit-learn 接口
XGBRegressor/XGBClassifierGridSearchCV/RandomizedSearchCV超参数调优
- 进阶主题
- 处理不平衡数据集
- 使用 DMatrix 优化性能
- 保存和加载模型
- 总结与最佳实践
什么是 XGBoost?
简介
XGBoost (eXtreme Gradient Boosting) 是一个基于梯度提升决策树的开源、分布式梯度提升库,它最初由陈天奇(Tianqi Chen)为解决机器学习竞赛中的大规模数据问题而设计,现已成为数据科学领域最强大、最流行的机器学习算法之一。

为什么选择 XGBoost?(核心优势)
- 高性能与速度:通过算法优化(如近似直方图算法)和并行计算,训练速度极快。
- 高准确率:集成了 L1/L2 正则化,能有效防止过拟合,通常能获得比其他算法更高的准确率。
- 灵活性:支持自定义损失函数和评估指标,适用于分类、回归、排序等多种任务。
- 健壮性:内置处理缺失值的机制,对数据不那么敏感。
- 可扩展性:能够处理大规模数据,支持分布式计算。
安装与环境准备
安装 XGBoost
最简单的方式是通过 pip 或 conda 安装。
# 使用 pip pip install xgboost # 使用 conda conda install -c conda-forge xgboost
注意:XGBoost 依赖于 NumPy 和 SciPy,如果你的环境较旧,可能需要先升级它们:
pip install --upgrade numpy scipy。
验证安装
安装完成后,在 Python 中导入并检查版本。
import xgboost as xgb print(xgb.__version__) # 输出版本号, 1.7.6
XGBoost 基础:从数据到模型
我们从一个经典的回归问题开始:预测房价。

第一步:准备数据
我们将使用 Scikit-learn 自带的波士顿房价数据集(注:新版本中已移除,此处用 fetch_openml 获取替代数据集)。
import xgboost as xgb from sklearn.model_selection import train_test_split from sklearn.datasets import fetch_openml from sklearn.metrics import mean_squared_error # 加载数据 (使用 California Housing 数据集,替代已弃用的 Boston 数据集) housing = fetch_openml(name="house_prices", as_frame=True) X, y = housing.data, housing.target # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
第二步:创建 DMatrix
XGBoost 有自己的数据结构 DMatrix,它专为 XGBoost 优化,比 NumPy 数组或 Pandas DataFrame 效率更高。
# 将数据转换为 DMatrix 格式 dtrain = xgb.DMatrix(X_train, label=y_train) dtest = xgb.DMatrix(X_test, label=y_test)
第三步:定义参数
我们需要指定模型的各种参数。
params = {
'objective': 'reg:squarederror', # 损失函数:回归用平方误差
'eval_metric': 'rmse', # 评估指标:均方根误差
'max_depth': 6, # 树的最大深度
'eta': 0.1, # 学习率 / shrinkage
'seed': 42 # 随机种子,保证结果可复现
}
第四步:训练模型
使用 xgb.train 函数进行训练。

# 训练轮次 (n_estimators)
num_rounds = 100
# 设置一个验证集,以便监控模型在验证集上的表现
watchlist = [(dtrain, 'train'), (dtest, 'eval')]
# 开始训练
bst = xgb.train(
params,
dtrain,
num_rounds,
watchlist,
early_stopping_rounds=10, # 早停,如果10轮后性能没有提升,就停止训练
verbose_eval=10 # 每10轮打印一次日志
)
输出解释: 你会看到类似下面的输出,显示了训练集和验证集上的 RMSE 值。
[0] train-rmse:1.66151 eval-rmse:1.66087
...
[10] train-rmse:1.41235 eval-rmse:1.41321
...
[50] train-rmse:1.12345 eval-rmse:1.13567
...
Stopped. Best iteration: [45] train-rmse:1.13123 eval-rmse:1.14210
early_stopping_rounds=10 使得模型在第45轮后停止,因为从第36轮到第45轮,验证集的 RMSE 没有再提升。
第五步:预测与评估
使用训练好的模型 bst 进行预测。
# 对测试集进行预测
y_pred = bst.predict(dtest)
# 计算均方误差
mse = mean_squared_error(y_test, y_pred)
rmse = mse ** 0.5
print(f"RMSE on test set: {rmse:.4f}")
XGBoost 核心概念
GBDT vs. XGBoost
| 特性 | GBDT (传统梯度提升) | XGBoost |
|---|---|---|
| 基学习器 | 任何可微分的模型(通常是CART树) | 一定是CART回归树 |
| 损失函数 | 仅支持一阶导数(梯度) | 支持一阶和二阶导数(梯度+Hessian),使泰勒展开更精确 |
| 正则化 | 通常没有或只有简单的L2正则化 | 内置L1和L2正则化,惩罚模型复杂度 |
| 缺失值处理 | 需要手动处理 | 自动学习最优的默认方向处理缺失值 |
| 并行化 | 主要特征并行 | 行、列、节点并行,效率更高 |
| 剪枝策略 | 后剪枝 | 在树的生长过程中进行预剪枝 |
正则化
XGBoost 的目标函数由两部分组成: Obj = Loss + Regularization
- Loss: 模型对数据的拟合程度,如回归中的平方误差。
- Regularization: 对模型复杂度的惩罚,防止过拟合。
gamma(min_split_loss): 节点分裂所需的最小损失减少量,值越大,算法越保守。lambda(reg_lambda): L2 正则化项的权重,惩罚叶子节点的权重平方和。alpha(reg_alpha): L1 正则化项的权重,惩罚叶子节点的权重绝对值和。
损失函数
objective 参数定义了模型的目标。
- 回归:
reg:squarederror: 标准平方误差回归。reg:squaredlogerror: 对数平方误差回归,适用于目标值跨度大的情况。
- 分类:
binary:logistic: 二分类,输出概率(0-1之间)。multi:softmax: 多分类,输出类别编号。multi:softprob: 多分类,输出每个类别的概率。
基学习器
默认使用 gbtree(CART 回归树),你也可以使用 gblinear(线性模型),但 gbtree 是最常用且效果最好的。
分类任务实战
二分类
使用 Scikit-learn 的乳腺癌数据集。
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import accuracy_score, roc_auc_score
# 加载数据
cancer = load_breast_cancer()
X, y = cancer.data, cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 转换为 DMatrix
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# 定义分类参数
params_clf = {
'objective': 'binary:logistic', # 二分类逻辑回归
'eval_metric': 'logloss', # 评估指标:对数损失
'max_depth': 4,
'eta': 0.1,
'seed': 42
}
# 训练模型
bst_clf = xgb.train(params_clf, dtrain, num_rounds=100, verbose_eval=20)
# 预测 (输出概率)
y_pred_proba = bst_clf.predict(dtest)
# 将概率转换为类别 (0或1)
y_pred_class = [1 if p > 0.5 else 0 for p in y_pred_proba]
# 评估
print(f"Accuracy: {accuracy_score(y_test, y_pred_class):.4f}")
print(f"AUC: {roc_auc_score(y_test, y_pred_proba):.4f}")
多分类
使用 Scikit-learn 的鸢尾花数据集。
from sklearn.datasets import load_iris
# 加载数据
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 转换为 DMatrix
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# 定义多分类参数
params_multi = {
'objective': 'multi:softprob', # 多分类,输出概率
'num_class': 3, # 类别数量
'eval_metric': 'mlogloss', # 多分类对数损失
'max_depth': 3,
'eta': 0.1,
'seed': 42
}
# 训练模型
bst_multi = xgb.train(params_multi, dtrain, num_rounds=100, verbose_eval=20)
# 预测 (输出每个类别的概率)
y_pred_proba = bst_multi.predict(dtest)
# 找到概率最大的类别作为预测结果
y_pred_class = [p.argmax() for p in y_pred_proba]
# 评估
print(f"Accuracy: {accuracy_score(y_test, y_pred_class):.4f}")
高级特性
提前停止
early_stopping_rounds 是防止过拟合和节省计算时间的关键,它需要一个验证集 (watchlist),如果在指定的轮数内,验证集上的评估指标没有改善,训练就会停止。
特征重要性
训练好的模型可以告诉我们哪些特征最重要。
# 获取特征重要性分数
importance = bst.get_score(importance_type='gain') # 'gain', 'weight', 'cover', 'total_gain'
# 'gain': 一个特征在所有分裂中带来的平均增益
# 'weight': 一个特征被用作分裂点的总次数
# 可视化
import matplotlib.pyplot as plt
import pandas as pd
# 将重要性转换为 DataFrame 并排序
importance_df = pd.DataFrame(list(importance.items()), columns=['feature', 'importance'])
importance_df = importance_df.sort_values(by='importance', ascending=False)
# 绘制条形图
plt.figure(figsize=(10, 6))
plt.barh(importance_df['feature'], importance_df['importance'])
plt.xlabel('Importance (Gain)')
plt.ylabel('Feature')'Feature Importance')
plt.gca().invert_yaxis() # 让最重要的特征在顶部
plt.show()
处理缺失值
XGBoost 会自动学习处理缺失值的最佳路径,你不需要在数据预处理中填充它们。
# 创建一个带有缺失值的数据集
import numpy as np
X_with_nan = X.copy()
X_with_nan[0, 0] = np.nan
X_with_nan[1, 1] = np.nan
# DMatrix 可以自动处理 NaN
dtrain_nan = xgb.DMatrix(X_with_nan, label=y_train)
# 训练模型 (参数不变)
bst_nan = xgb.train(params, dtrain_nan, num_rounds=10)
print("Model trained with missing values successfully.")
交叉验证
XGBoost 内置了高效的交叉验证功能,无需手动划分数据。
# 使用 xgb.cv 进行交叉验证
cv_results = xgb.cv(
params,
dtrain,
num_rounds=100,
nfold=5, # 5折交叉验证
stratified=True, # 对于分类任务,建议使用分层抽样
early_stopping_rounds=10,
seed=42,
verbose_eval=20
)
# cv_results 是一个 DataFrame,包含了每一折的评估结果
print(cv_results.tail()) # 打印最后几轮的结果
# 找到最佳迭代次数和对应的得分
best_score = cv_results['test-rmse-mean'].min()
best_iteration = cv_results['test-rmse-mean'].idxmin() + 1 # idxmin 返回的是索引,从0开始
print(f"\nBest CV RMSE: {best_score:.4f} at iteration {best_iteration}")
Scikit-learn 接口
为了方便与 Scikit-learn 生态系统(如 Pipeline, GridSearchCV)集成,XGBoost 提供了 Scikit-learn 兼容的 API。
XGBRegressor / XGBClassifier
from xgboost import XGBRegressor, XGBClassifier
# 回归任务 (使用与上面相同的房价数据)
xgb_reg = XGBRegressor(
objective='reg:squarederror',
max_depth=6,
eta=0.1,
n_estimators=100, # 等同于 num_rounds
early_stopping_rounds=10,
eval_metric='rmse',
random_state=42
)
# Scikit-learn API 直接接受 NumPy 数组或 Pandas DataFrame
xgb_reg.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=10)
y_pred_reg = xgb_reg.predict(X_test)
print(f"Scikit-learn API RMSE: {mean_squared_error(y_test, y_pred_reg)**0.5:.4f}")
# 分类任务
xgb_clf = XGBClassifier(
objective='binary:logistic',
use_label_encoder=False, # 推荐设置为 False,避免警告
eval_metric='logloss',
n_estimators=100,
random_state=42
)
xgb_clf.fit(X_train, y_train)
y_pred_clf = xgb_clf.predict(X_test)
print(f"Scikit-learn API Accuracy: {accuracy_score(y_test, y_pred_clf):.4f}")
超参数调优 (GridSearchCV)
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {
'max_depth': [3, 5, 7],
'eta': [0.01, 0.1, 0.2],
'subsample': [0.8, 1.0] # 子样本比例,用于行采样
}
# 创建 GridSearchCV 对象
grid_search = GridSearchCV(
estimator=XGBRegressor(objective='reg:squarederror', n_estimators=100),
param_grid=param_grid,
cv=3,
scoring='neg_mean_squared_error',
verbose=2
)
# 执行网格搜索
grid_search.fit(X_train, y_train)
# 输出最佳参数和最佳得分
print("\nBest parameters found: ", grid_search.best_params_)
print("Best RMSE: ", (-grid_search.best_score_)**0.5)
进阶主题
处理不平衡数据集
对于分类问题,当正负样本比例严重失衡时,可以设置 scale_pos_weight 参数。
# 计算正负样本比例
pos_count = y_train.sum()
neg_count = len(y_train) - pos_count
scale_pos_weight_val = neg_count / pos_count
print(f"scale_pos_weight: {scale_pos_weight_val}")
# 在模型中使用
imbalance_params = {
'objective': 'binary:logistic',
'scale_pos_weight': scale_pos_weight_val,
# ... 其他参数
}
使用 DMatrix 优化性能
对于非常大的数据集,DMatrix 的性能优势会非常明显,它支持从文件(如 CSV, TSV)直接加载数据,节省内存。
# 保存数据到文件
# dtrain.save_binary('dtrain.buffer')
# dtest.save_binary('dtest.buffer')
# 从文件加载
# dtrain = xgb.DMatrix('dtrain.buffer')
保存和加载模型
# 保存模型
bst.save_model('xgboost_model.json')
# 加载模型
loaded_bst = xgb.Booster()
loaded_bst.load_model('xgboost_model.json')
# 使用加载的模型进行预测
y_pred_loaded = loaded_bst.predict(dtest)
print(f"Loaded model RMSE: {mean_squared_error(y_test, y_pred_loaded)**0.5:.4f}")
总结与最佳实践
- 从简单开始:先用默认参数训练一个基线模型。
- 使用
early_stopping:这是防止过拟合和节省计算时间的必备技巧。 - 交叉验证:
xgb.cv是进行模型评估和选择超参数的强大工具。 - 理解特征重要性:这有助于你进行特征工程和理解模型行为。
- 优先使用 Scikit-learn API:当你需要与 Scikit-learn 的工具链(如
Pipeline,GridSearchCV)无缝集成时。 - 关注核心参数:
max_depth,eta(learning_rate),n_estimators(num_rounds),subsample,colsample_bytree是最重要的调参对象。 - 处理不平衡数据:记得使用
scale_pos_weight。
这份教程涵盖了 XGBoost 的绝大多数核心功能,通过实践这些示例,你将能够自信地将 XGBoost 应用于各种机器学习问题,祝你学习愉快!
