一. 梯度增强 Gradient Boosting (GB)
目的:利用前K-1个分类器得到第K个分类器,并将这K个弱分类器叠加,组成强分类器。
Boosting算法的学习过程采用的思想是Additive Manner(加法效应),即:迭代生成多个(K个)弱学习器,然后将弱模型的结果相加,其中后面的模型是基于前面的模型的效果生成的,模型间的关系以及最后的预测结果如下:
可以看到,Boosting算法是通过一系列的迭代来优化分类结果,每迭代一次引入一个新的弱分类器,来克服现在已经存在的弱分类器组合的shortcomings,即:每一次迭代都致力于减少偏差。
Gradient Boosting算法在迭代的时候将负梯度作为上一轮基学习器犯错的衡量指标,在下一轮学习中通过拟合负梯度来纠正上一轮犯的错误。
注:argmin :表示使目标函数取最小值时的变量值 。
f_K(x):第k个分类器的分类值
\gamma:伪残差 y_i-f(i)
L(.):损失函数,绝对值损失函数或均方误差损失函数
二、GBDT
GBDT(Gradient Boosting Decision Tree)是以决策树(CART)为基学习器的GB算法。
GBDT是Boosting里面的boosting tree(提升树),并使用gradient boost。其关键是利用损失函数的负梯度方向在当前模型的值作为残差的近似值,进而拟合一颗CART回归树(classification and regression tree)
随机森林和GBDT区别
1)随机森林采用的bagging思想,而GBDT采用的boosting思想。
2)组成随机森林的树可以是分类树,也可以是回归树;而GBDT只能由回归树组成。
3)组成随机森林的树可以并行生成;而GBDT只能是串行生成。
4)对于最终的输出结果而言,随机森林采用多数投票等;而GBDT则是将所有结果累加起来,或者加权累加起来。
5)随机森林对异常值不敏感;GBDT对异常值非常敏感。
6)随机森林对训练集一视同仁;GBDT是基于权值的弱分类器的集成。
7)随机森林是通过减少模型方差提高性能;GBDT是通过减少模型偏差提高性能。
三、XGboost
XGBoost与GBDT算法的区别:
-
传统的GBDT在优化的时候只用到了一阶导数信息,而XGBoost则对代价函数进行了二阶泰勒展开,得到一阶和二阶导数,并且XGBoost在代价函数中加入了正则项,用于控制模型的复杂度。
-
另外XGBoost还支持线性分类器,通过在代价函数中加入正则项,降低了模型的方差,使学习出来的模型更加简单,避免过拟合。
目标:求第t个分类器和它的权值。
1、在第t次迭代的损失函数可以写成:
其中,y_i^{t-1}_hat是前t-1个分类器对于第i个样本的预测值的加权和。如下图所示:
注:K代表分类器的个数,n代表样本的个数,f代表基分类器,\omga是正则项。
5、如何构建树的结构:
看哪个特征使得L最大。
XGboost 决策树举例
决策树的核心在于树的结构和叶子权值。
XGBoost的优点
- 使用许多策略去防止过拟合,如:正则化项、Shrinkage and Column Subsampling等。
- 目标函数优化利用了损失函数关于待求函数的二阶导数
- 支持并行化,这是XGBoost的闪光点,虽然树与树之间是串行关系,但是同层级节点可并行。具体的对于某个节点,节点内选择最佳分裂点,候选分裂点计算增益用多线程并行。训练速度快。
- 添加了对稀疏数据的处理。
- 交叉验证,early stop,当预测结果已经很好的时候可以提前停止建树,加快训练速度。
- 支持设置样本权重,该权重体现在一阶导数g和二阶导数h,通过调整权重可以去更加关注一些样本。
四、Adaboost
前面都是分类器(预测)加权
- 提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被正确分类样本的权值。
- 得到若干弱分类器后,加大分类误差率小的弱分类器的权值。最后T个分类器求加权和,并预测。
算法
注:
D_1(i)第一个分类器的第i个样本的权值;
\ebuslu:分类误差率,直接分类错误的样本权值相加;
T:T个分类器;
Z_t:归一化因子,值为所有样本的分子的和。保证概率为1;
sign(x):x>0返回1;x<0返回-1;
只要初始分类误差率<0.5,最后分类误差率会收敛到0.
鸢尾花-xgboost
import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegressionCV
from sklearn.ensemble import RandomForestClassifier
name = ['sepal length', 'sepal width', 'petal length', 'petal width', 'class']
data = pd.read_csv('..\\8.Regression\\iris.data', header=None, names=name)
x = data[name[:4]]
y = LabelEncoder().fit_transform(data[name[4]])
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.7)
print('x_train.shape', x_train.shape)
"""生成xgb需要的测试数据,训练数据格式Dmatrix"""
data_train = xgb.DMatrix(x_train, label=y_train)
data_test = xgb.DMatrix(x_test, label=y_test)
"""设置参数-字典格式"""
""" max_depth:树的最大深度,缺省值为6,取值范围:[1,∞]
eta:为了防止过拟合,更新过程用到的收缩步长,eta通过缩减特征的权重使提升计算过程更加保守。缺省值为0.3,取值范围为[0,1]
silent:0表示打印出运行时信息,1表示以缄默方式运行,缺省值为0
objective:定义学习任务以及相应的学习目标,'binary:logistic'表示二分类的逻辑回归问题,输出为概率"""
para = {'max_depth': 2, 'eta': 0.3, 'silent': 1, 'objective': 'multi:softmax', 'num_class': 3}
bst = xgb.train(para, data_train, num_boost_round=6)
y_hat = bst.predict(data_test)
print('xgboost测试集正确率', sum(y_hat == data_test.get_label()) / y_hat.size)
models={'Logistic':LogisticRegressionCV(cv=5,multi_class='ovr'),'RandomForestClassifier':RandomForestClassifier(n_estimators=100,criterion='gini',max_depth=3)}
for key,value in models.items():
value.fit(x_train,y_train)
print(key,'测试集正确率',value.score(x_test,y_test))
毒蘑菇-xgboost(二分类)
数据集:
在XGBoost中数据的加载是使用其特有的数据格式进行训练的,我们可以使用XGBoost中的xgb.DMatrix(x_train, label=y_train)函数进行数据的加载,xgb.DMatrix()也支持libsvm格式的数据,这是一种稀疏数据的存储方式,xgb.DMatrix()可以直接读取这种数据格式:
共125个特征,第一列为样本标签,表示是否为毒蘑菇
数据集特征解释:
libsvm数据格式是一种稀疏矩阵的表示方法,其中第1列为结果集,后面的每列含义为:该样本的特征序号:该样本对应的特征序号的值,对于特征数量多,且稀疏的时候非常的合适。
# /usr/bin/python
# -*- encoding:utf-8 -*-
import xgboost as xgb
import numpy as np
# 1、xgBoost的基本使用
# 2、自定义损失函数的梯度和二阶导
# 3、binary:logistic/logitraw
"""蘑菇的例子"""
# 定义f: theta * x
def log_reg(y_hat, y):
p = 1.0 / (1.0 + np.exp(-y_hat))
g = p - y.get_label()
h = p * (1.0-p)
return g, h
def error_rate(y_hat, y):
return 'error', float(sum(y.get_label() != (y_hat > 0.5))) / len(y_hat)
if __name__ == "__main__":
# 读取数据
data_train = xgb.DMatrix('agaricus_train.txt')
data_test = xgb.DMatrix('agaricus_test.txt')
print(data_train)
print(type(data_train))
'''
para = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic'}
bst=xgb.train(para,data_train,num_boost_round=6)
# bst = xgb.train(param, data_train, num_boost_round=n_round, evals=watchlist, obj=log_reg, feval=error_rate)
print('bst',bst)
y_hat=bst.predict(data_test) #输出为概率值
y_hat=y_hat>0.5
result=(y_hat==data_test.get_label())
print('测试集总个数',y_hat.size)
print('测试集预测错误的个数',y_hat.size-sum(result))