前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字节一面,差点跪在 GBDT !!

字节一面,差点跪在 GBDT !!

作者头像
Python编程爱好者
发布2024-07-12 13:37:39
730
发布2024-07-12 13:37:39
举报
文章被收录于专栏:Python编程爱好者

Hi,我是Johngo~

这些天有一个同学在字节一面的时候,在 GBDT 交流的时候,感觉差点点挂掉。好在后面的面试中表现还算可以。

现在在等待offer中,据说是问题不大。

趁这个机会,我也和大家分享一下关于 GBDT 一些理论内容。

熟悉的同学全当复习,不熟悉的同学可以学习一番。

一点介绍

梯度提升决策树(Gradient Boosting Decision Trees, GBDT)是一种常用的机器学习集成方法。

通过逐步构建一系列决策树(通常是弱学习器),每个新树都试图纠正之前所有树的误差。GBDT主要用于回归和分类任务,能够处理复杂的非线性关系和多种数据类型。

历史背景:

GBDT的发展可以追溯到1999年,当时杰罗姆·弗里德曼(Jerome H. Friedman)发表了一篇关于梯度提升算法的开创性论文。梯度提升是由他提出的一种通用方法,旨在提高预测模型的性能。最初的梯度提升框架被称为“Gradient Boosting Machines”(GBM),其中决策树是最常用的基学习器。

GBDT自提出以来,已经被广泛应用于各种机器学习任务中,并且在许多实际问题中表现出色。近年来,GBDT也得到了许多优化和扩展,例如XGBoost、LightGBM和CatBoost等变种。

理论基础

GBDT的核心思想是通过逐步构建多个决策树(弱学习器),每棵新树都试图纠正之前所有树的误差。GBDT的训练过程是一个迭代优化过程,目标是最小化目标函数(通常是损失函数)。

  1. 初始化模型:

初始时,模型是一个常数函数,通常选择目标变量的均值作为初始预测值:

其中, 是损失函数, 是第 个样本的实际值, 是常数值。

  1. 迭代构建模型:

对于 :

a. 计算残差: 计算当前模型的残差(即误差):

其中, 是第 轮的模型, 是第 个样本在第 轮的残差。

b. 拟合新树: 拟合一个新的决策树 来预测残差:

c. 更新模型: 更新模型,通过对之前模型和新拟合的树的加权和来更新模型:

其中, 是学习率(step size),控制模型更新的步伐。

  1. 最终模型:

经过 轮迭代后,得到最终的预测模型:

算法流程:

  1. 输入:
  • 训练数据集
  • 损失函数
  • 最大迭代次数
  • 学习率
  1. 初始化:
  • 初始化模型 为常数:
  1. 迭代过程: 对于 到 :

a. 计算残差 :

b. 拟合新的决策树 来预测残差 :

c. 更新模型 :

  1. 输出:
  • 最终的预测模型 :

GBDT通过迭代地构建一系列决策树,并逐步减少误差,最终得到一个强大的预测模型。

每一步中,通过计算残差并拟合新的树来捕捉数据中的剩余信息,从而不断优化模型的性能。

案例

整个案例包括数据预处理、模型训练、预测、可视化以及一些优化技巧。

我们将使用加利福尼亚住房数据集(California Housing Dataset)来进行回归任务,即预测房屋的中位数价格。

导入库

代码语言:javascript
复制
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error

加载和预处理数据

代码语言:javascript
复制
# 加载数据集
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 标准化特征
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

训练GBDT模型

代码语言:javascript
复制
# 初始化并训练GBDT模型
gbdt = GradientBoostingRegressor(n_estimators=500, learning_rate=0.1, max_depth=4, random_state=42)
gbdt.fit(X_train, y_train)

预测和评估

代码语言:javascript
复制
# 预测
y_train_pred = gbdt.predict(X_train)
y_test_pred = gbdt.predict(X_test)

# 计算误差
mse_train = mean_squared_error(y_train, y_train_pred)
mse_test = mean_squared_error(y_test, y_test_pred)
mae_train = mean_absolute_error(y_train, y_train_pred)
mae_test = mean_absolute_error(y_test, y_test_pred)

print(f"Training MSE: {mse_train:.4f}, Training MAE: {mae_train:.4f}")
print(f"Test MSE: {mse_test:.4f}, Test MAE: {mae_test:.4f}")

预测值与实际值的对比

代码语言:javascript
复制
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_test_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('Actual vs Predicted Values')
plt.show()

特征重要性

代码语言:javascript
复制
feature_importance = gbdt.feature_importances_
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + 0.5

plt.figure(figsize=(12, 6))
plt.barh(pos, feature_importance[sorted_idx], align='center')
plt.yticks(pos, np.array(housing.feature_names)[sorted_idx])
plt.xlabel('Feature Importance')
plt.title('Feature Importance of GBDT')
plt.show()

算法优化

  1. 参数调优:使用网格搜索(Grid Search)或随机搜索(Random Search)来寻找最佳参数组合。
  2. 早停法:使用验证集来监控模型的性能,防止过拟合。
  3. 特征选择:移除无关或冗余的特征,减少模型的复杂度。
参数调优示例
代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV

param_grid = {
    'n_estimators': [100, 200, 300],
    'learning_rate': [0.01, 0.05, 0.1],
    'max_depth': [3, 4, 5],
    'subsample': [0.8, 1.0]
}

grid_search = GridSearchCV(estimator=GradientBoostingRegressor(random_state=42), param_grid=param_grid, cv=3, n_jobs=-1, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train)

print("Best parameters found: ", grid_search.best_params_)

早停法示例

代码语言:javascript
复制
from sklearn.model_selection import train_test_split

# 将训练数据再分割为训练集和验证集
X_train_sub, X_val, y_train_sub, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)

# 初始化并训练GBDT模型
gbdt_early_stopping = GradientBoostingRegressor(n_estimators=1000, learning_rate=0.1, max_depth=4, random_state=42)
gbdt_early_stopping.fit(X_train_sub, y_train_sub)

# 记录验证集上的误差
val_errors = [mean_squared_error(y_val, y_pred) for y_pred in gbdt_early_stopping.staged_predict(X_val)]

# 找到最佳的迭代次数
best_n_estimators = np.argmin(val_errors) + 1

# 使用最佳的迭代次数重新训练模型
gbdt_best = GradientBoostingRegressor(n_estimators=best_n_estimators, learning_rate=0.1, max_depth=4, random_state=42)
gbdt_best.fit(X_train, y_train)

# 评估
y_test_pred_best = gbdt_best.predict(X_test)
mse_test_best = mean_squared_error(y_test, y_test_pred_best)
print(f"Test MSE after early stopping: {mse_test_best:.4f}")

这个完整的示例展示了如何使用GBDT进行回归任务,包括数据预处理、模型训练、预测、评估和可视化。此外,还有一些优化技巧,如参数调优和早停法,以提高模型的性能和泛化能力。

算法评估

1. 准确性指标

回归任务
  • 均方误差(Mean Squared Error, MSE): MSE 是预测值与实际值之间差的平方的平均值。它是一个常见的回归性能指标,用来衡量模型的预测误差。

其中, 是实际值, 是预测值, 是样本数量。

  • 均绝对误差(Mean Absolute Error, MAE): MAE 是预测值与实际值之间差的绝对值的平均值。它是另一个常见的回归性能指标,用来衡量模型的预测误差。
  • **决定系数(R-squared, ):** 是一个统计量,表示模型的解释力。它介于0和1之间,越接近1表示模型越好。

其中, 是实际值的平均值。

分类任务

准确率(Accuracy):

  • 准确率是正确预测的样本数量与总样本数量之比。

精确率(Precision)和召回率(Recall):

  • 精确率是正确预测的正类样本数量与预测为正类的样本数量之比。
  • 召回率是正确预测的正类样本数量与实际正类样本数量之比。

F1分数:

  • F1分数是精确率和召回率的调和平均数,用于衡量分类模型的性能。

2. 训练效率和预测效率

  • 训练时间: 训练时间是模型训练所需的时间,通常会受模型复杂度和数据集大小的影响。
  • 预测时间: 预测时间是模型进行一次预测所需的时间,通常在实时预测任务中需要考虑。

3. 模型复杂度和泛化能力

  • 过拟合与欠拟合:
    • 过拟合(Overfitting)是指模型在训练集上表现很好,但在测试集上表现很差。可以通过交叉验证和正则化等方法来检测和防止过拟合。
    • 欠拟合(Underfitting)是指模型在训练集和测试集上都表现不好,通常是由于模型过于简单导致的。
  • 交叉验证(Cross-Validation): 交叉验证是一种评估模型泛化能力的方法,通过将数据集分成多个折叠(fold),然后多次训练和测试模型,以获取模型性能的稳定估计。

4. 特征重要性

  • 特征重要性(Feature Importance): 特征重要性度量每个特征对模型预测的影响。GBDT可以自然地提供每个特征的重要性评分,有助于理解模型并进行特征选择。

5. ROC曲线和AUC

  • ROC曲线(Receiver Operating Characteristic Curve): ROC曲线是反映分类模型性能的图形,横轴为假阳性率(False Positive Rate),纵轴为真阳性率(True Positive Rate)。
  • AUC(Area Under the Curve): AUC是ROC曲线下面积的大小,表示分类模型的整体性能。AUC值越接近1,模型性能越好。

综合实例

使用GBDT进行回归任务并评估其性能:

代码语言:javascript
复制
import numpy as np
import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import matplotlib.pyplot as plt
import seaborn as sns

# 加载数据集
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target

# 分割数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 标准化特征
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 初始化并训练GBDT模型
gbdt = GradientBoostingRegressor(n_estimators=500, learning_rate=0.1, max_depth=4, random_state=42)
gbdt.fit(X_train, y_train)

# 预测
y_train_pred = gbdt.predict(X_train)
y_test_pred = gbdt.predict(X_test)

# 计算误差
mse_train = mean_squared_error(y_train, y_train_pred)
mse_test = mean_squared_error(y_test, y_test_pred)
mae_train = mean_absolute_error(y_train, y_train_pred)
mae_test = mean_absolute_error(y_test, y_test_pred)
r2_train = r2_score(y_train, y_train_pred)
r2_test = r2_score(y_test, y_test_pred)

print(f"Training MSE: {mse_train:.4f}, Training MAE: {mae_train:.4f}, Training R^2: {r2_train:.4f}")
print(f"Test MSE: {mse_test:.4f}, Test MAE: {mae_test:.4f}, Test R^2: {r2_test:.4f}")

# 可视化预测值与实际值的对比
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_test_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('Actual vs Predicted Values')
plt.show()

# 可视化特征重要性
feature_importance = gbdt.feature_importances_
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + 0.5

plt.figure(figsize=(12, 6))
plt.barh(pos, feature_importance[sorted_idx], align='center')
plt.yticks(pos, np.array(housing.feature_names)[sorted_idx])
plt.xlabel('Feature Importance')
plt.title('Feature Importance of GBDT')
plt.show()

代码中,展示了如何训练GBDT模型并使用MSE、MAE和R²等关键指标来评估其性能。同时,还展示了如何可视化预测值与实际值的对比以及特征重要性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Johngo学长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一点介绍
  • 理论基础
  • 案例
    • 算法优化
      • 参数调优示例
    • 早停法示例
    • 算法评估
      • 1. 准确性指标
        • 回归任务
        • 分类任务
      • 2. 训练效率和预测效率
        • 3. 模型复杂度和泛化能力
          • 4. 特征重要性
            • 5. ROC曲线和AUC
              • 综合实例
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档