超全面讲透一个算法模型,XGBoost!!

文摘   2024-11-08 16:27   北京  

大家好~

XGBoost作为一个非常牛逼的算法模型,大家一定要非常清楚其原理。

XGBoost 特别擅长解决结构化数据问题,比如表格数据。它的全称是「eXtreme Gradient Boosting」,意思是「极限梯度提升」。听起来有点复杂,其实用通俗的语言解释,它就是一种让模型一步步变得更聪明的算法。

下面我们一步步来看看它的思路~

1. 什么是「梯度提升」?

想象我们要训练一个模型来预测房价。我们一开始用一个很简单的模型,它可能只会做一些粗略的预测,误差会很大。然后我们让第二个模型来专门学习第一个模型的错误,想办法减少这个误差。接着,第三个模型再学习前两个模型的误差……每一步都「纠正」前面的错误,让模型不断「提升」。这种逐步提高模型的方式就叫「梯度提升」。

2. XGBoost 是一种「强化」版的梯度提升

XGBoost 是梯度提升的一个升级版,在很多细节上做了优化,让它训练更快、效果更好。比如,它会使用一种叫做「并行计算」的技术,让计算机同时进行多个计算,大大加速了训练速度。还有一些优化的数学技巧,可以让它在不损失准确性的前提下更快地找到答案。

举个easy案例:预测房价

假设我们在某个城市的房产数据上训练 XGBoost 模型来预测房价。数据包括房子的面积、房间数、建造年份等特征。具体步骤如下:

  1. 初始化模型:XGBoost 一开始会用一个非常简单的预测方式,比如预测每个房子价格的平均值。这种预测通常误差很大。

  2. 计算误差:接着,模型会检查哪里预测得不准,比如有些房子的价格预测得偏高,有些偏低。

  3. 学习误差:然后,XGBoost 会生成一个「决策树」,专门用来预测这些误差。决策树就像一张分支图,它会根据数据特征一步步地把房子分类,比如先按照面积大小分,再按照房间数量分,直到找到价格的规律。这个新的决策树就会「修正」第一个模型的误差。

  4. 重复多次:再接着,XGBoost 会不断创建更多的树,每棵树都是为了修正之前树的误差。每次生成新的树,模型的预测都会更准确一点。最终,把所有树的预测加起来就会得到一个很不错的结果。

XGBoost 的一些特点

  1. 速度快:它计算效率很高,尤其适合大数据。
  2. 准确性高:XGBoost 在比赛和实际应用中常常表现优异,因为它在训练过程中逐步减少误差。
  3. 可以防止过拟合:XGBoost 有一些机制可以防止模型过度拟合,比如设置最大深度、学习率等参数。

总的来说,XGBoost 就像一个由很多「小树」组成的团队,这些小树各自负责一部分任务,彼此互相纠正错误,最终得出一个更加准确的预测。对于大部分表格数据问题,比如预测价格、用户行为等,XGBoost 都是一个表现很好的选择。

下面,我们通过详细的原理解释和案例,让大家更加深入的理解XGBoost。

公式推导

1. 树模型和损失函数

XGBoost 的目标是利用决策树集合来预测一个目标变量。假设我们有一个数据集 ,其中  是特征, 是目标值。模型的预测值可以表示为各棵树的加权和:

其中, 表示第  棵树的结构。每棵树  会将数据分到不同的叶子节点,每个叶子节点有一个得分值。

我们的目标是找到一组树,使得预测值与真实值的误差最小。因此,我们定义一个损失函数来度量误差,通常可以用均方误差或其他误差函数。对于均方误差的情形,损失函数可以写作:

2. 二阶泰勒展开

XGBoost 通过迭代地优化损失函数来训练每棵树。在每一轮中,我们新增一个树 ,希望能最小化损失。使用泰勒展开,损失函数可以近似写作:

其中  是一阶导数, 是二阶导数。通过最小化这个近似的损失函数,我们能更高效地找到最优解。

3. 叶子节点的得分

对于每个叶子节点,我们可以计算一个最优权重,以此来降低误差。假设叶子节点集合为 ,则第  个叶子节点的最优权重为:

其中, 是正则化参数,用于控制模型的复杂度,防止过拟合。

完整案例

  1. 生成虚拟数据:包含房屋面积、房间数量、建造年份等特征。
  2. 使用 XGBoost 模型训练:预测房价。
  3. 数据可视化:绘制数据分布、模型训练过程的损失变化、特征重要性、预测效果等图表。

代码实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from xgboost import XGBRegressor, plot_importance
import xgboost as xgb

# 生成虚拟数据集
np.random.seed(42)
n_samples = 5000
area = np.random.normal(1500500, n_samples)  # 房屋面积
rooms = np.random.randint(27, n_samples)  # 房间数量
age = np.random.randint(130, n_samples)  # 建造年份
location_score = np.random.uniform(110, n_samples)  # 位置评分

# 假设真实的房价与这些特征的线性关系,再加入噪声
price = 5000 + 0.3 * area + 10000 * rooms - 150 * age + 5000 * location_score + np.random.normal(010000, n_samples)

# 创建 DataFrame
data = pd.DataFrame({
    'Area': area,
    'Rooms': rooms,
    'Age': age,
    'Location_Score': location_score,
    'Price': price
})

# 数据分为训练集和测试集
X = data[['Area''Rooms''Age''Location_Score']]
y = data['Price']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 定义和训练 XGBoost 回归模型,添加 eval_set 参数
eval_set = [(X_train, y_train), (X_test, y_test)]
model = XGBRegressor(objective='reg:squarederror', max_depth=4, learning_rate=0.1, n_estimators=100, random_state=42)
model.fit(X_train, y_train, eval_set=eval_set, eval_metric="rmse", verbose=False)

# 预测结果
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))

# Data Distribution
plt.figure(figsize=(106))
sns.scatterplot(x='Area', y='Price', hue='Rooms', size='Location_Score', sizes=(20200), data=data, palette="viridis")
plt.title("Relationship between Area and Price (by Room Count and Location Score)")
plt.xlabel("Area (Square Feet)")
plt.ylabel("Price")
plt.legend(title="Room Count & Location Score", loc="upper left", bbox_to_anchor=(11))
plt.show()

# Loss Change during Training
results = model.evals_result()
epochs = len(results['validation_0']['rmse'])
x_axis = range(0, epochs)

plt.figure(figsize=(106))
plt.plot(x_axis, results['validation_0']['rmse'], label='Train')
plt.plot(x_axis, results['validation_1']['rmse'], label='Test')
plt.title("RMSE during XGBoost Training")
plt.xlabel("Epoch")
plt.ylabel("RMSE")
plt.legend()
plt.show()

# Feature Importance
plt.figure(figsize=(106))
plot_importance(model, importance_type='weight', title='Feature Importance (Based on Frequency of Use)')
plt.show()

# Actual vs Predicted Values
plt.figure(figsize=(106))
plt.scatter(y_test, y_pred, c='red', marker='o', edgecolor='k', alpha=0.6)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.title("Actual vs Predicted Prices")
plt.xlabel("Actual Price")
plt.ylabel("Predicted Price")
plt.show()

# Output RMSE
print(f"Test RMSE: {rmse:.2f}")

图表1:房屋面积和价格的关系:这是特征的基本分布图。横轴表示面积,纵轴表示价格,颜色代表房间数量,大小代表位置评分。我们可以从中看到一些特征间的相关性,比如面积越大、房间越多,价格也越高。

图表2:训练过程中的损失变化(RMSE):这个图展示了模型在训练过程中 RMSE 的变化趋势。通过观察曲线的下降速度,我们可以评估模型收敛的情况。如果曲线平稳,说明模型训练得较好;如果曲线过早停止下降,可能需要调整参数。

图表3:特征重要性:这是 XGBoost 自动计算的特征重要性。每个特征的重要性由其在模型中出现的频率决定。重要性高的特征对预测结果影响更大。我们可以看到哪些特征对房价预测的贡献最大,比如「面积」和「房间数量」。

图表4:真实值 vs 预测值:该图展示了测试集的真实房价和模型预测的房价的关系。理想情况下,所有点应落在对角线附近。点越靠近对角线,说明模型的预测越准确。散布较远的点说明模型误差较大。

整个过程,咱们展示了 XGBoost 如何预测房价,并且用多个图表展示了数据和模型训练的细节。这些图表有助于大家很好的理解数据特征、训练过程和模型的表现。

最后

通过这个案例,给大家展现了这种从零实现 GBDT 的过程能帮助你更好地理解梯度提升决策树的核心原理。
最近准备了16大块的内容,124个算法问题的总结,完整的机器学习小册,免费领取~
另外,今天给大家准备了关于「深度学习」的论文合集,往期核心论文汇总,分享给大家。
点击名片,回复「深度学习论文」即可~
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~

机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
 最新文章