以下内容属于经验总结的建模模块,建模模块目前包括 lasso 和 XGBoost,文章内容属于 XGBoost。
建模
XGBoost
功能介绍
xgboost 是大规模并行 boosted tree 的工具。
XGBoost 支持以 CART 作为基分类器、线性分类器,相当于带 L1 和 L2 正则化项的逻辑斯蒂回归(分类问题)或者线性回归问题。
XGBoost 在优化时对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数,并支持自定义代价函数,只要函数可一阶和二阶求导。
XGBoost 在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的 Score 的 L2 模的平方和。从 bias-variance tradeoff 角度来讲,正则项降低了模型的 vairance,使学习出来的模型更加简单,防止过拟合。
XGBoost 在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间,实际应用中,一般将学习速率 eta 设置得小一点,然后迭代次数设置得大一点。
XGBoost 支持列抽样(column subsampling),能够降低过拟合,还能减少计算。
对于缺失值的处理,对于特征的值有缺失的样本,XGBoost 可以自动学习出它的分裂方向。
-
xgboost工具支持并行。XGBoost 的并行不是 tree 粒度的并行,XGBoost 也是一次迭代完才能进行下一次迭代的(第 t 次迭代的代价函数里包含了前面t-1次迭代的预测值)。XGBoost 的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),XGBoost 在训练之前,预先对数据进行了排序,然后保存为 block 结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个 block 结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
利用 xgboost 进一步优化模型,提升 kaggle 机器学习模型的得分。
语法
import xgboost as xgb
dtrain = xgb.DMatrix(X_train, label = y)#DMatrix 是 xgb 存储信息的单位,本步骤把数据放进这里面去
dtest = xgb.DMatrix(X_test)
params = {"max_depth":2, "eta":0.1}#max_depth:最大深度。eta 和 gradiant boosting 中的 learning rate 参数类似。通过减少每一步的权重,可以提高模型的稳定性。 典型值为 0.01-0.2。
model = xgb.cv(params, dtrain, num_boost_round=500, early_stopping_rounds=100)# CV 用法及参数见下文
model.loc[30:,["test-rmse-mean", "train-rmse-mean"]].plot()
Early_stopping_rounds: 提前终止程序
如果有评价数据,可以提前终止程序,这样可以找到最优的迭代次数。如果要提前终止程序必须至少有一个评价数据在参数evals
中。 超过一个则使用最后一个。
train(..., evals=evals, early_stopping_rounds=10)
此模型下,机器会一直学习到 validation score 不再增长。每经过 early_stopping_rounds 轮,误差应该都有所下降,否则不应该继续学习。
如果出现了提前终止,模型会出现两个额外情况:bst.best_score
和 bst.best_iteration
. 注意此处 train() 会返回最后一次循环的模型,而非最好的循环的模型。
此方法适用于各类最低 (RMSE, log loss, etc.) 或最高 (MAP, NDCG, AUC) 误差计算。
观察误差情况
语法如下:
model.loc[30:,["test-rmse-mean", "train-rmse-mean"]].plot()
横轴 boost round,最大 500;纵轴是平均误差。
利用 XGBoost 建模
语法如下:
model_xgb = xgb.XGBRegressor(n_estimators=360, max_depth=2, learning_rate=0.1) #用了xgb.cv 调参。n_estimators:训练的轮数;max_depth:最大深度。
model_xgb.fit(X_train, y)
利用 lasso 验证 XGBoost
语法如下:
xgb_preds = np.expm1(model_xgb.predict(X_test))
lasso_preds = np.expm1(model_lasso.predict(X_test))
predictions = pd.DataFrame({"xgb":xgb_preds, "lasso":lasso_preds})
predictions.plot(x = "xgb", y = "lasso", kind = "scatter")
横轴:xgb 预测值,纵轴:lasso 预测值。散点图可以看出强线性相关,两个预测结果大部分基本一致。
很多情况下把不相关的结果进行加权平均是有用的,通常能够优化结果,虽然在这个案例里帮助不大。
最终结果
preds = 0.7*lasso_preds + 0.3*xgb_preds#把 lasso 和 xgb 加权后得到最终预测值,为啥是 0.7 和 0.3?经验吧
solution = pd.DataFrame({"id":test.Id, "SalePrice":preds})
solution.to_csv("ridge_sol.csv", index = False)
XGBoost 的参数
1. eta [默认 0.3]
和 GBM 中的 learning rate 参数类似。 通过减少每一步的权重,可以提高模型的稳定性。 典型值为 0.01-0.2。
2. min_child_weight [默认 1]
决定最小叶子节点样本权重和。和 GBM 的 min_child_leaf 参数类似,但不完全一样。XGBoost 的这个参数是最小样本权重的和,而 GBM 参数是最小样本总数。这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。但是如果这个值过高,会导致欠拟合。这个参数需要使用 CV 来调整。
3. max_depth [默认 6]
和 GBM 中的参数相同,这个值为树的最大深度。这个值也是用来避免过拟合的。max_depth 越大,模型会学到更具体更局部的样本。需要使用 CV 函数来进行调优。 典型值:3-10
4. max_leaf_nodes
树上最大的节点或叶子的数量。 可以替代 max_depth 的作用。因为如果生成的是二叉树,一个深度为 n 的树最多生成 n2 个叶子。 如果定义了这个参数,GBM 会忽略 max_depth 参数。
5. gamma [默认 0]
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma 指定了节点分裂所需的最小损失函数下降值。 这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
6、max_delta_step[默认 0]
这参数限制每棵树权重改变的最大步长。如果这个参数的值为 0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。 通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。 这个参数一般用不到,但是你可以挖掘出来它更多的用处。
7. subsample [默认 1]
和 GBM 中的 subsample 参数一模一样。这个参数控制对于每棵树,随机采样的比例。 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。 典型值:0.5-1
8. colsample_bytree [默认 1]
和 GBM 里面的 max_features 参数类似。用来控制每棵随机采样的列数的占比 (每一列是一个特征)。 典型值:0.5-1
9. colsample_bylevel [默认 1]
用来控制树的每一级的每一次分裂,对列数的采样的占比。 我个人一般不太用这个参数,因为 subsample 参数和 colsample_bytree 参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。
10. lambda [默认 1]
权重的 L2 正则化项。(和 Ridge regression 类似)。 这个参数是用来控制 XGBoost 的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。
11. alpha [默认 1]
权重的 L1 正则化项。(和 Lasso regression 类似)。 可以应用在很高维度的情况下,使得算法的速度更快。
12. scale_pos_weight [默认 1]
在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。
学习目标参数
这个参数用来控制理想的优化目标和每一步结果的度量方法。
1. objective [默认 reg:linear]
这个参数定义需要被最小化的损失函数。最常用的值有:
binary:logistic 二分类的逻辑回归,返回预测的概率 (不是类别)。 multi:softmax 使用 softmax 的多分类器,返回预测的类别 (不是概率)。
在这种情况下,你还需要多设一个参数:num_class(类别数目)。 multi:softprob 和 multi:softmax 参数一样,但是返回的是每个数据属于各个类别的概率。
2. eval_metric [默认值取决于 objective 参数的取值]
对于有效数据的度量方法。对于回归问题,默认值是 rmse,对于分类问题,默认值是 error。 典型值有:
rmse 均方根误差、mae 平均绝对误差、logloss 负对数似然函数值、error 二分类错误率 (阈值为 0.5)、merror 多分类错误率、mlogloss 多分类 logloss 损失函数、auc 曲线下面积
3. seed [默认 0]
随机数的种子设置它可以复现随机数据的结果,也可以用于调整参数。