ML——xgboost包使用笔记

xgboost包中包含了XGBoost分类器,回归器等, 本文详细介绍XGBClassifier


安装和导入

  • 安装

    1
    pip install xgboost
  • 导入

    1
    import xgboost as xgb
  • 使用

    1
    clf = xgb.XGBClassifier()

模型参数

普通参数

以下参数按照我理解的重要性排序

  • booster:
    • ‘gbtree’: 使用树模型作为基分类器
    • ‘gbliner’: 使用线性模型作为基分类器
    • 默认使用模型树模型即可,因为使用线性分类器时XGBoost相当于退化成含有L1和L2正则化的逻辑回归(分类问题中)或者线性回归(回归问题中)
  • n_estimators: 基分类器数量
    • 每个分类器都需要一轮训练,基分类器越多,训练所需要的时间越多
    • 经测试发现,开始时越大越能提升模型性能,但是增加到一定程度后模型变化不大,甚至出现过拟合
  • max_depth[default=3]: 每棵树的最大深度
    • 树越深,越容易过拟合
  • objective[default="binary:logistic"]: 目标(损失函数)函数,训练的目标是最小化损失函数
    • ‘binary:logistic’: 二分类回归, XGBClassifier默认是这个,因为XGBClassifier是分类器
    • ‘reg:linear’: 线性回归, XGBRegressor默认使用这个
    • ‘multi:softmax’: 多分类中的softmax
    • ‘multi:softprob’: 与softmax相同,但是每个类别返回的是当前类别的概率值而不是普通的softmax值
  • n_jobs: 线程数量
    • 以前使用的是nthread, 现在已经不使用了,直接使用n_jobs即可
    • 经测试发现并不是越多越快, 猜测原因可能是因为各个线程之间交互需要代价
  • reg_alpha: L1正则化系数
  • reg_lambda: L2正则化系数
  • subsample: 样本的下采样率
  • colsample: 构建每棵树时的样本特征下采样率
  • scale_pos_weight: 用于平衡正负样本不均衡问题, 有助于样本不平衡时训练的收敛
    • 具体调参实验还需测试[待更新]
    • 这个值可以作为计算损失时正样本的权重
  • learning_rate: shrinkage参数
    • 更新叶子结点权重时,乘以该系数,避免步长过大,减小学习率,增加学习次数
    • 在公式中叫做eta, 也就是 \(\eta\)
  • min_child_weight[default=1]: [待更新]
  • max_leaf_nodes: 最大叶子结点数目
    • 也是用于控制过拟合, 和max_depth的作用差不多
  • importance_type: 指明特征重要性评估方式, 只有在booster为’gbtree’时有效
    • ‘gain’: [默认], is the average gain of splits which use the feature
    • ‘cover’: is the average coverage of splits which use the feature
    • ‘weight’: is the number of times a feature appears in a tree
    • ‘total_gain’: 整体增益
    • ‘total_cover’: 整体覆盖率

常用函数

  • feature_importances_:

    • 返回特征的重要性列表
    • 特征重要性可以由不同方式评估
    • 特征重要性评估指标(importance_type)在创建时指定, 使用plot_importance函数的话,可以在使用函数时指定
  • plot_importance: 按照递减顺序给出每个特征的重要性排序图

    • 使用方式

      1
      2
      3
      4
      from xgboost import plot_importance
      from matplotlib import pyplot
      plot_importance(model)
      pyplot.show()
    • 详细定义

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      def plot_importance(booster, ax=None, height=0.2,
      xlim=None, ylim=None, title='Feature importance',
      xlabel='F score', ylabel='Features',
      importance_type='weight', max_num_features=None,
      grid=True, show_values=True, **kwargs):
      """Plot importance based on fitted trees.
      Parameters
      ----------
      booster : Booster, XGBModel or dict
      Booster or XGBModel instance, or dict taken by Booster.get_fscore()
      ax : matplotlib Axes, default None
      Target axes instance. If None, new figure and axes will be created.
      grid : bool, Turn the axes grids on or off. Default is True (On).
      importance_type : str, default "weight"
      How the importance is calculated: either "weight", "gain", or "cover"
      * "weight" is the number of times a feature appears in a tree
      * "gain" is the average gain of splits which use the feature
      * "cover" is the average coverage of splits which use the feature
      where coverage is defined as the number of samples affected by the split
      max_num_features : int, default None
      Maximum number of top features displayed on plot. If None, all features will be displayed.
      height : float, default 0.2
      Bar height, passed to ax.barh()
      xlim : tuple, default None
      Tuple passed to axes.xlim()
      ylim : tuple, default None
      Tuple passed to axes.ylim()
      title : str, default "Feature importance"
      Axes title. To disable, pass None.
      xlabel : str, default "F score"
      X axis title label. To disable, pass None.
      ylabel : str, default "Features"
      Y axis title label. To disable, pass None.
      show_values : bool, default True
      Show values on plot. To disable, pass False.
      kwargs :
      Other keywords passed to ax.barh()
      Returns
      -------
      ax : matplotlib Axes
      """

单调性保证

  • XGBoost自带单调性保证功能:
    • 参数使用示例是monotone_constraints="(1,0,-1,0,0)",表示输出结果随着
      • 第一个参数单调递增
      • 第三个参数单调递减
      • 其他参数不做约束
    • 这个参数的实现逻辑是:
      • monotone_constraints 参数通过在梯度提升树的分裂过程中加入额外的限制来实现单调性。具体来说,在选择最佳分裂点时,XGBoost 不仅考虑分裂的增益(如基尼不纯度减少或均方误差减少),还会检查分裂是否满足指定的单调性约束。如果一个潜在的分裂点违反了单调性约束,那么即使它能带来较大的增益,也不会被选作最佳分裂点。
    • 在现实场景中会出现修改单调特征值以后,模型预测结果为0的问题
      • 表现:实际使用时体现为输出值全是相同的(单调确没有意义)
      • 原因:此时主要原因是数据本身不具有单调性,特别是当label不随着单调特征单调时,容易出现学到的许多区间上模型值相同
      • 测试(对于单调递增场景,单调递减的正常):
        • 测试一:如果样本中存在太多不单调的数据,甚至希望单增,但数据单调递减,则会导致模型预估值随目标特征值变化,基本相同 * 测试二:如果样本中的目标特征和label是满足单调的,但是存在一些随机值,则在某些区间上容易出现单调值,特别是没有见过的区间上,预估值会是完全一致的
        • 注意:测试时,需要限定其他特征都不变,只有当前特征变化才可以,否则无法保证单调性
  • Demo示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import xgboost as xgb
    import numpy as np
    from sklearn.datasets import make_regression
    from sklearn.model_selection import train_test_split
    # 创建一个简单的回归数据集
    X, y = make_regression(n_samples=1000, n_features=5, noise=0.1)
    # 假设我们有5个特征,并且我们知道第一个特征应该与目标变量呈现正相关,
    # 第二个特征应该与目标变量呈现负相关,其余特征没有特定的单调性要求
    monotone_constraints = (1, -1, 0, 0, 0)
    # 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    # 将数据转换为 DMatrix 格式,这是 XGBoost 所需的数据格式
    dtrain = xgb.DMatrix(X_train, label=y_train)
    dtest = xgb.DMatrix(X_test, label=y_test)
    # 定义 XGBoost 参数
    params = {
    'objective': 'reg:squarederror', # 对于回归任务
    'monotone_constraints': str(monotone_constraints) # 应用单调性约束
    }
    # 训练模型
    model = xgb.train(params, dtrain, num_boost_round=100)
    # 预测
    predictions = model.predict(dtest)
    # 打印部分预测结果
    print(predictions[:10])