Task06:GBDT的分类和回归
一、Boosting算法
首先这三种算法都属于Boosting方法,且GBDT是机器学习算法,XGBoost和LightGBM是GBDT的算法实现。
Boosting方法训练基分类器时采用串行的方式,各个基分类器之间
有依赖。其基本思想是根据当前模型损失函数的负梯度信息来训练新加入的弱分类器,然后将训练好的弱分类器以累加的形式结合到现有模型中。这个过程是在不断地减小损失函数,使得模型偏差不断降低。但Boosting的过程并不会显著降低方差。这是因为Boosting的训练过程使得各弱分类器之间是强相关的,缺乏独立性,所以并不会对降低方差有作用。
二、GBDT算法
Gradient Boosting是Boosting中的一大类算法,算法1描述了Gradient
Boosting算法的基本流程,在每一轮迭代中,首先计算出当前模型在所
有样本上的负梯度,然后以该值为目标训练一个新的弱分类器进行拟合
并计算出该弱分类器的权重,最终实现对模型的更新。
enter description here
2.1 GBDT的优点和局限性
2.1.1 优点
1)预测阶段的计算速度快,树与树之间可并行化计算。
2)在分布稠密的数据集上,泛化能力和表达能力都很好。
3)采用决策树作为弱分类器使得GBDT模型具有较好的解释性和鲁棒性,能够自动发现特征间的高阶关系,并且也不需要对数据进行特殊的预处理如归一化等。
2.1.2 局限性
1)GBDT在高维稀疏的数据集上,表现不如支持向量机或者神经网络。
2)GBDT在处理文本分类特征问题上,相对其他模型的优势不如它在处理 数值特征时明显。
3)训练过程需要串行训练,只能在决策树内部采用一些局部并行的手段提高训练速度。
链接:https://www.jianshu.com/p/765efe2b951a
https://zhuanlan.zhihu.com/p/99069186
来源:简书、知乎。
GBDT分类树:
import pandas as pd
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import roc_curve,auc
from sklearn import metrics
from sklearn.model_selection import GridSearchCV
from sklearn.preprocessing import LabelEncoder
#读取数据
data = pd.read_excel(r'E:/wyz/Desktop/data/data.xlsx')
#将数据集中的字符串转化为代表类别的数字。因为sklearn的决策树只识别数字
le = LabelEncoder()
for col in data_model.columns:
data_model[col] = le.fit_transform(data_model[col].astype(str))
#划分数据集(3、7划分)
y = data_model['target']
x = data_model.drop('target', axis=1)
x_train, x_test, y_train, y_test = train_test_split(x, y,random_state=0,train_size=0.7)
#标准化数据
ss_x = StandardScaler()
ss_y = StandardScaler()
x_train = ss_x.fit_transform(x_train)
x_test = ss_x.transform(x_test)
model_GBDT = GradientBoostingClassifier(random_state=10)
model_GBDT.fit(x_train,y_train)
y_pred = gbm0.predict(x_train)
y_predprob = model_GBDT.predict_proba(x_train)[:,1]
print ("Accuracy : %.4g" % metrics.accuracy_score(y.values, y_pred))
print ("AUC Score (Train): %f" % metrics.roc_auc_score(y, y_predprob))
# https://blog.youkuaiyun.com/weixin_41851055/article/details/106260066
GBDT回归树:
import numpy as np
import math
'''
Input: x,y,splint_point_array(该特征的所有切分点)
Output:minloss(所有切分点中最小损失),最优切分点,残值数组(下一次在此基础进行拟合)
'''
def findBestSplitPoint(x_array,y_array,split_point_array):
minloss = np.inf
best_split_point = 0
best_c1 = 0
best_c2 = 0
best_R1 = 0
best_R2 = 0
#遍历切分点
for c in split_point_array:
loss = 0
# math.floor() 向下取整,划分R1/R2区域
R1 = y_array[:x_array.index(math.floor(c))+1]
R2 = y_array[x_array.index(math.floor(c))+1:]
c1 = np.mean(R1)
c2 = np.mean(R2)
for y in y_array:
if y in R1:
loss+=(y - c1)**2
else:
loss+=(y - c2)**2
if loss < minloss:
minloss = loss
best_split_point = c
best_c1 = c1
best_c2 = c2
best_R1 = R1
best_R2 = R2
#残值结果,用于下一次拟合
residual_array = np.hstack((best_R1-best_c1, best_R2-best_c2))
return minloss,best_split_point,list(residual_array)
x = [1,2,3,4,5,6,7,8,9,10]
y = [5.56,5.70,5.91,6.40,6.80,7.05,8.9,8.70,9.00,9.05]
#切分点
split_point_array = [1.5,2.5,3.5,4.5,6.5,7.5,8.5,9.5]
print(findBestSplitPoint(x,y,split_point_array))
#https://blog.youkuaiyun.com/forestForQuietLive/article/details/89335508
侧边栏问题待补
(findBestSplitPoint(x,y,split_point_array))
#https://blog.youkuaiyun.com/forestForQuietLive/article/details/89335508
##### 侧边栏问题待补