机器学习经验总结之XGBoost

作者: 魏立艳 | 来源:发表于2017-06-08 15:41 被阅读865次

    以下内容属于经验总结的建模模块,建模模块目前包括 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_scorebst.best_iteration. 注意此处 train() 会返回最后一次循环的模型,而非最好的循环的模型。

    此方法适用于各类最低 (RMSE, log loss, etc.) 或最高 (MAP, NDCG, AUC) 误差计算。

    观察误差情况

    语法如下:

    model.loc[30:,["test-rmse-mean", "train-rmse-mean"]].plot()
    
    1480446-44c3184cee47d8ee.png

    横轴 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")
    
    __results___39_1.png

    横轴: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]

    随机数的种子设置它可以复现随机数据的结果,也可以用于调整参数。

    相关文章

      网友评论

      • marvinxu:感觉都是凑起来的,cv验证如何调参, max_depth等参数如何调整并没有很好的说明。 还有eta的典型值,文档里默认值是0.3, 而你给的是0.01-0.2, 请问是自己的经验吗?
        魏立艳:本来也还没有写完,我的这篇是其中一部分;不完全是自己的经验,是做的 case study。

      本文标题:机器学习经验总结之XGBoost

      本文链接:https://www.haomeiwen.com/subject/gshtqxtx.html