赞
踩
Gradient Boosting 基本原理
GBDT是boosting的一种方法,主要思想:
每一次建立单个分类器时,是在之前建立的模型的损失函数的梯度下降方向。
损失函数越大,说明模型越容易出错,如果我们的模型能让损失函数持续的下降,则说明我们的模型在持续不断的改进,而最好的方式就是让损失函数在其梯度的方向上下降。
GBDT的核心在于每一棵树学的是之前所有树结论和的残差
Shrinkage(缩减)是 GBDT 的一个重要演进分支
GBDT可以用于回归问题(线性和非线性),也可用于分类问题
GBDT和随机森林的异同点
相同点:
不同点:
GBDT的优缺点
优点:
缺点:
XGBoost与GDBT的区别
区别一:
区别二:
区别三:
为了理解Histogram-based Gradient Boosting的原理, 我们回顾一下回归决策树的构建过程。在回归树生长的过程中, 我们需要遍历每一个特征, 如果是连续型特征:
上述过程的计算量明显会随着样本数量以及特征维度的增加而成倍增长。假设我们有100万样本,100个数值类特征我们最多需要尝试 100万 X 100 =1亿次计算才能得到一个节点如何划分, 显然这种树的分裂方式在数据量很大的时候会导致训练速度缓慢
如何能加速训练的过程?一种改进方案是将特征值进行分箱处理,依然假设有100万样本,100个数值类特征。此时将每个特征列分箱为 100 箱。 现在,要找到最佳分割点,我们只需要进行100 X 100次计算就可以找到最佳分割点,对比之前的方案, 计算量最多减少了 10000倍
看下面的例子
import matplotlib.pyplot as plt import matplotlib.patches as patches # 形状:指的是 matplotlib.patches 包里面的一些对象,比如我们常见的箭头,正方形,椭圆等等,也称之为“块”。 n_samples = 50 n_bins = 5 X = np.random.uniform(low=-6.0, high=6.0, size=(n_samples, )) X = np.sort(X) y = 1 / (1 + np.exp(-X)) # 绘制数据 fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(13, 4)) ax[0].scatter(X, y, s=10) ax[0].set_title('1d regression problem with {0} points'.format(n_samples)) ax[0].set_xlabel('X') ax[0].set_ylabel('y') # 绘制标准的分割方式 ax[1].scatter(X, y, s=10) for i in range(n_samples - 1): split = (X[i] + X[i-1]) / 2 ax[1].plot([split, split], [0.0, 1.0], c='r', linewidth=1) # c 颜色 linewidth 线宽 ax[1].set_title('Standard: {0} splits to consider'.format(n_samples - 1)) ax[1].set_xlabel('X') ax[1].set_ylabel('y') # 找到最佳分割点 best = (-np.inf, np.inf) for i in range(n_samples - 1): split = (X[i] + X[i-1]) / 2 loss = np.mean((y[X <= split] - np.mean(y[X <= split]))**2) + np.mean((y[X > split] - np.mean(y[X > split]))**2) if loss <= best[1]: best = (split, loss) print(best) ax[1].plot([best[0], best[0]], [0., 1.], linewidth=3, linestyle='--', c='k') ax[2].scatter(X, y, s=10) splits = [X[0],X[10],X[20],X[30],X[40],X[49]] for split in splits: ax[2].plot([split, split], [0.0, 1.0], c='r', linewidth=1) bin_colors = ['#8000ff', '#1996f3', '#4df3ce', '#b2f396', '#ff964f', '#ff0000'] for i in range(n_bins): ax[2].add_patch(patches.Rectangle((splits[i], 0.0), splits[i+1] - splits[i], 1.0, color=bin_colors[i], alpha=0.2)) ax[2].set_title('Histogram with {0} bins: {0} splits to consider'.format(n_bins)) ax[2].set_xlabel('X') ax[2].set_ylabel('counts') # 找到分箱之后的最佳分割点 best = (-np.inf, np.inf) splits = [X[0],X[10],X[20],X[30],X[40],X[49]] for split in splits: loss = np.mean((y[X <= split] - np.mean(y[X <= split]))**2) + np.mean((y[X > split] - np.mean(y[X > split]))**2) if loss <= best[1]: best = (split, loss) print(best) ax[2].plot([best[0], best[0]], [0., 1.], linewidth=3, linestyle='--', c='k')
(0.1834031699694303, 0.044419292201901245) (0.38106574907332114, 0.045130335725236406)
上面的图中, 我们对比了标准回归树分裂方式,和基于直方图的回归树的分裂方式。 在标准的回归树分裂方式中,我们尝试了49种不同的分裂方式,得到了最佳分裂点, 而基于直方图的回归树,我们只尝试了4次就找到了最佳分裂方式。如果数据规模进一步扩大, 采用直方图的回归树,训练的速度会更快!
Histogram-based Gradient Boosting 的Sklearn实现
from sklearn.experimental import enable_hist_gradient_boosting #属于实验版本
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X,y = load_breast_cancer(return_X_y = True)
X_train ,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=45)
histGBC = HistGradientBoostingClassifier(max_depth=2,max_iter=20,learning_rate=0.75)
histGBC.fit(X_train,y_train)
histGBC.score(X_test,y_test)
0.9824561403508771
SKlearn中 HistGradientBoosting 的思想实际上受到了lightGBM启发,相当于是lightGBM的sklearn版本
lightGBM(Light Gradient Boosted Machines)是2017年1月,微软在GItHub上开源的一个新的梯度提升框架。LightGBM 的核心原理是基于直方图的梯度提升方法,它具有以下优势:
LightGBM除了在建树的过程中, 除了采用分箱的方式来处理特征值,还采用了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。