XGboost的目标函数
防止模型过复杂分的过细,加了正则化项。
在GBDT中我们考虑的是模型最终累加的预测值和实际值之间的误差。虽然乘上了衰减因子但是只考虑了误差的构建还是可能陷入过拟合的,这里的V是一个减缓的策略。
XGBoost中加入了一个子模型复杂度的累计作为惩罚系数,这样既考虑了误差又考虑了复杂度,来减缓过拟合(在bagging中各个模型互不相干,所以降低了过拟合的情况,Boosting是解决欠拟合的问题,所以容易造成过拟合,在Boosting中我们就用XGBoost来解决的)。
Wq(x):W是一个向量,q(x)代表落入哪一个叶子节点,根据节点从W向量取值
rT:模型复杂的表现就是分的过细,也就是叶子节点过多。所以T表示的就是当前这个叶子节点的叶子数目。后面部分相当于是个L2正则,所有叶子节点的预测值的平方。这样惩罚项就有两部分一部分是控制叶子节点数目不要太多,另一个是预测值不要太大
公式推导
这个式子直接求梯度值是不好求的。后面部分(正则化项)消不掉
这里的一阶导,二阶导后面在做理解,这里只理解思路。具体的过程后面补上。这里的f(x)就是整个损失函数loss,泰勒中的x就是ft(x),对整个l损失函数做泰勒二阶展开式去拟合它,就是图上的内容。
去掉公式中的常数项,就得到了最终的目标函数。但是在这个函数中n表示表示样本,而T表示叶子节点。所以我们做一个归换,把样本换为叶子。
然后对这个目标函数做一个求解。
这样我们就求得了预测值Wj。然后将Wj带入导损失函数中就到了最终的损失函数。在这个损失函数中,H,G都是上一次损失的导数,T是本轮的叶子节点个数。所以本轮构建树的时候前面的都一样,后面会选择一个叶子节点少的
XGBoost 和 GBDT比较
- XGBoost在GBDt的基础上加入了损失函数,防止了过拟合。因为过拟合问题也是Boosting的主要问题
- XGBoost在构建过程中也考虑了二阶导数,GBDT只考虑一阶导数
- XGBoost中决策树的构建是基于损失函数,GBDT是基于MAE、MSE、基尼系数
XGBoost树节点分裂方法
在这里介绍些其他特性
- 支持列采样,降低过拟合,同时降低计算量
- 缺失值自动处理
- 并行计算。治理的并行指的是划分特征选择的时候是并行的
- 子学习器可以时cart 逻辑回归 线性回归
代码
"""
开始使用XGBoost的相关API
"""
# 一、直接使用XGBoost的API
# a. 数据转换
dtrain = xgb.DMatrix(data=x_train, label=y_train)
dtest = xgb.DMatrix(data=x_test)
# b. 模型参数构建
params = {'max_depth': 10, 'eta': 1, 'objective': 'reg:linear'}
num_boost_round = 2
# c. 模型训练
model = xgb.train(params=params, dtrain=dtrain, num_boost_round=num_boost_round)
# d. 模型保存
model.save_model('xgb.model')
print(model)
# a. 加载模型产生预测值
model2 = xgb.Booster()
model2.load_model('xgb.model')
print(model2)
print("测试集R2:{}".format(r2_score(y_test, model2.predict(dtest))))
print("训练集R2:{}".format(r2_score(y_train, model2.predict(dtrain))))
algo = XGBRegressor(learning_rate=0.2,reg_lambda=0.5)
"""
max_depth=3, 子模型的树的深度
learning_rate=1, 相当于GDBT当中的v
n_estimators=100, 构建几个子模型
objective="reg:linear", 模型的损失函数
"""
# 模型训练
algo.fit(x_train, y_train)
# 模型效果评估
train_predict = algo.predict(x_train)
test_predict = algo.predict(x_test)
print("训练集集上的效果(mse):{}".format(mean_squared_error(y_train,train_predict)))
print("测试集上的效果(mse):{}".format(mean_squared_error(y_test,test_predict)))
print("训练集集上的效果(R^2):{}".format(r2_score(y_train,train_predict)))
print("测试集上的效果(R^2):{}".format(r2_score(y_test,test_predict)))