LightGBM调参

GBDT模型的另一个进化版本:LightGBM。LigthGBM是boosting集合模型中的新进成员,由微软提供,它和XGBoost一样是对GBDT的高效实现,原理上它和GBDT及XGBoost类似,都采用损失函数的负梯度作为当前决策树的残差近似值,去拟合新的决策树。

LightGBM在很多方面会比XGBoost表现的更为优秀。它有以下优势:

  • 更快的训练效率
  • 低内存使用
  • 更高的准确率
  • 支持并行化学习
  • 可处理大规模数据
  • 支持直接使用category特征

从下图实验数据可以看出, LightGBM比XGBoost快将近10倍,内存占用率大约为XGBoost的1/6,并且准确率也有提升。

好用归好用,关于这个东西的调参一直让我很伤脑筋,首先是它的参数好多,源码里好像不全,好像一些参数的意义相同但是有好几个名字,等等等等,很怪。

源码中的一些参数

Parameters
        ----------
        boosting_type : string, optional (default='gbdt')
            'gbdt', traditional Gradient Boosting Decision Tree.
            'dart', Dropouts meet Multiple Additive Regression Trees.
            'goss', Gradient-based One-Side Sampling.
            'rf', Random Forest.
        num_leaves : int, optional (default=31)
            Maximum tree leaves for base learners.
        max_depth : int, optional (default=-1)
            Maximum tree depth for base learners, <=0 means no limit.
        learning_rate : float, optional (default=0.1)
            Boosting learning rate.
            You can use ``callbacks`` parameter of ``fit`` method to shrink/adapt learning rate
            in training using ``reset_parameter`` callback.
            Note, that this will ignore the ``learning_rate`` argument in training.
        n_estimators : int, optional (default=100)
            Number of boosted trees to fit.
        subsample_for_bin : int, optional (default=200000)
            Number of samples for constructing bins.
        objective : string, callable or None, optional (default=None)
            Specify the learning task and the corresponding learning objective or
            a custom objective function to be used (see note below).
            Default: 'regression' for LGBMRegressor, 'binary' or 'multiclass' for LGBMClassifier, 'lambdarank' for LGBMRanker.
        class_weight : dict, 'balanced' or None, optional (default=None)
            Weights associated with classes in the form ``{class_label: weight}``.
            Use this parameter only for multi-class classification task;
            for binary classification task you may use ``is_unbalance`` or ``scale_pos_weight`` parameters.
            Note, that the usage of all these parameters will result in poor estimates of the individual class probabilities.
            You may want to consider performing probability calibration
            (https://scikit-learn.org/stable/modules/calibration.html) of your model.
            The 'balanced' mode uses the values of y to automatically adjust weights
            inversely proportional to class frequencies in the input data as ``n_samples / (n_classes * np.bincount(y))``.
            If None, all classes are supposed to have weight one.
            Note, that these weights will be multiplied with ``sample_weight`` (passed through the ``fit`` method)
            if ``sample_weight`` is specified.
        min_split_gain : float, optional (default=0.)
            Minimum loss reduction required to make a further partition on a leaf node of the tree.
        min_child_weight : float, optional (default=1e-3)
            Minimum sum of instance weight (hessian) needed in a child (leaf).
        min_child_samples : int, optional (default=20)
            Minimum number of data needed in a child (leaf).
        subsample : float, optional (default=1.)
            Subsample ratio of the training instance.
        subsample_freq : int, optional (default=0)
            Frequence of subsample, <=0 means no enable.
        colsample_bytree : float, optional (default=1.)
            Subsample ratio of columns when constructing each tree.
        reg_alpha : float, optional (default=0.)
            L1 regularization term on weights.
        reg_lambda : float, optional (default=0.)
            L2 regularization term on weights.
        random_state : int or None, optional (default=None)
            Random number seed.
            If None, default seeds in C++ code will be used.
        n_jobs : int, optional (default=-1)
            Number of parallel threads.
        silent : bool, optional (default=True)
            Whether to print messages while running boosting.
        importance_type : string, optional (default='split')
            The type of feature importance to be filled into ``feature_importances_``.
            If 'split', result contains numbers of times the feature is used in a model.
            If 'gain', result contains total gains of splits which use the feature.
        **kwargs
            Other parameters for the model.
            Check http://lightgbm.readthedocs.io/en/latest/Parameters.html for more parameters.

            .. warning::

                \*\*kwargs is not supported in sklearn, it may cause unexpected issues.

        Attributes
        ----------
        n_features_ : int
            The number of features of fitted model.
        classes_ : array of shape = [n_classes]
            The class label array (only for classification problem).
        n_classes_ : int
            The number of classes (only for classification problem).
        best_score_ : dict or None
            The best score of fitted model.
        best_iteration_ : int or None
            The best iteration of fitted model if ``early_stopping_rounds`` has been specified.
        objective_ : string or callable
            The concrete objective used while fitting this model.
        booster_ : Booster
            The underlying Booster of this model.
        evals_result_ : dict or None
            The evaluation results if ``early_stopping_rounds`` has been specified.
        feature_importances_ : array of shape = [n_features]
            The feature importances (the higher, the more important the feature).

        Note
        ----
        A custom objective function can be provided for the ``objective`` parameter.
        In this case, it should have the signature
        ``objective(y_true, y_pred) -> grad, hess`` or
        ``objective(y_true, y_pred, group) -> grad, hess``:

            y_true : array-like of shape = [n_samples]
                The target values.
            y_pred : array-like of shape = [n_samples] or shape = [n_samples * n_classes] (for multi-class task)
                The predicted values.
            group : array-like
                Group/query data, used for ranking task.
            grad : array-like of shape = [n_samples] or shape = [n_samples * n_classes] (for multi-class task)
                The value of the first order derivative (gradient) for each sample point.
            hess : array-like of shape = [n_samples] or shape = [n_samples * n_classes] (for multi-class task)
                The value of the second order derivative (Hessian) for each sample point.

        For multi-class task, the y_pred is group by class_id first, then group by row_id.
        If you want to get i-th row y_pred in j-th class, the access way is y_pred[j * num_data + i]
        and you should group grad and hess in this way as well.
        """

里面的参数都是比较常见的,但是上网搜了很多调参的参数里面都没有,我意识到事情没有这么简单,我又搜集了好多网站,终于找到了一个我认为参数比较全的。(机器学习算法之LightGBM – 标点符

LightGBM调参指导
针对 leaf-wise 树的参数优化:

num_leaves:控制了叶节点的数目。它是控制树模型复杂度的主要参数。
如果是level-wise,则该参数为2^{depth},其中depth为树的深度。但是当叶子数量相同时,leaf-wise的树要远远深过level-wise树,非常容易导致过拟合。因此应该让num_leaves小于2^{depth}。在leaf-wise树中,并不存在depth的概念。因为不存在一个从leaves到depth的合理映射。
min_data_in_leaf:每个叶节点的最少样本数量。它是处理leaf-wise树的过拟合的重要参数。将它设为较大的值,可以避免生成一个过深的树。但是也可能导致欠拟合。
max_depth: 控制了树的最大深度。该参数可以显式的限制树的深度。
针对更快的训练速度:

通过设置 bagging_fraction 和 bagging_freq 参数来使用 bagging 方法
通过设置 feature_fraction 参数来使用特征的子抽样
使用较小的 max_bin
使用 save_binary 在未来的学习过程对数据加载进行加速
获取更好的准确率:

使用较大的 max_bin (学习速度可能变慢)
使用较小的 learning_rate 和较大的 num_iterations
使用较大的 num_leaves (可能导致过拟合)
使用更大的训练数据
尝试 dart
缓解过拟合:

使用较小的 max_bin
使用较小的 num_leaves
使用 min_data_in_leaf 和 min_sum_hessian_in_leaf
通过设置 bagging_fraction 和 bagging_freq 来使用 bagging
通过设置 feature_fraction 来使用特征子抽样
使用更大的训练数据
使用 lambda_l1, lambda_l2 和 min_gain_to_split 来使用正则
尝试 max_depth 来避免生成过深的树
核心参数:

config 或者config_file:一个字符串,给出了配置文件的路径。默认为空字符串。
task: 一个字符串,给出了要执行的任务。可以为:
‘train’ 或者 ‘training’:表示是训练任务。默认为’train’。
‘predict’ 或者 ‘prediction’或者’test’:表示是预测任务。
‘convert_model’: 表示是模型转换任务。将模型文件转换成if-else 格式。
application或者objective或者app:一个字符串,表示问题类型。可以为:
‘regression’或’regression_l2’或’mean_squared_error’或’mse’或’l2_root’或’root_mean_squred_error’或’rmse’:表示回归任务,但是使用L2损失函数。默认为’regression’
‘regression_l1’或者mae或者mean_absolute_error:表示回归任务,但是使用L1损失函数。
‘huber’: 表示回归任务,但是使用huber 损失函数。
‘fair’: 表示回归任务,但是使用fair 损失函数。
‘poisson’: 表示Poisson 回归任务。
‘quantile’: 表示quantile回归任务。
‘quantile_l2’:表示quantile回归任务,但是使用了L2 损失函数。
‘mape’ 或者’mean_absolute_precentage_error’: 表示回归任务,但是使用MAPE 损失函数
‘gamma’: 表示gamma 回归任务。
‘tweedie’: 表示tweedie 回归任务。
‘binary’: 表示二分类任务,使用对数损失函数作为目标函数。
‘multiclass’: 表示多分类任务,使用softmax 函数作为目标函数。必须设置num_class 参数
‘multiclassova’ 或者’multiclass_ova’ 或者’ova’ 或者’ovr’: 表示多分类任务,使用one-vs-all 的二分类目标函数。必须设置num_class 参数
‘xentropy’ 或者’cross_entropy’: 目标函数为交叉熵(同时具有可选择的线性权重)。要求标签是[0,1] 之间的数值。
‘xentlambda’ 或者’cross_entropy_lambda’: 替代了参数化的cross_entropy 。要求标签是[0,1]之间的数值。
‘lambdarank’:表示排序任务。在lambdarank 任务中,标签应该为整数类型,数值越大表示相关性越高。label_gain 参数可以用于设置整数标签的增益(权重)
boosting 或者’boost’ 或者 ‘boosting_type’: 一个字符串,给出了基学习器模型算法。可以为:
‘gbdt’: 表示传统的梯度提升决策树。默认值为’gbdt’
‘rf’: 表示随机森林。
‘dart’: 表示带dropout 的gbdt
goss:表示Gradient-based One-Side Sampling 的gbdt
data或者train或者train_data:一个字符串,给出了训练数据所在的文件的文件名。默认为空字符串。lightgbm将使用它来训练模型。
valid或者test或者valid_data或者test_data:一个字符串,表示验证集所在的文件的文件名。默认为空字符串。lightgbm将输出该数据集的度量。如果有多个验证集,则用逗号分隔。
num_iterations或者num_iteration或者num_tree或者num_trees或者num_round或者num_rounds或者num_boost_round 一个整数,给出了boosting的迭代次数。默认为 100。
对于python/R包,该参数是被忽略的。对于python,使用train()/cv()的输入参数num_boost_round来代替。
在内部,lightgbm对于multiclass 问题设置了num_class*num_iterations 棵树。
learning_rate或者shrinkage_rate: 个浮点数,给出了学习率。默认为1。在dart 中,它还会影响dropped trees 的归一化权重。
num_leaves或者num_leaf:一个整数,给出了一棵树上的叶子数。默认为 31
tree_learner或者tree:一个字符串,给出了tree learner,主要用于并行学习。 默认为’serial’。 可以为:
‘serial’: 单台机器的tree learner
‘feature’: 特征并行的tree learner
‘data’: 数据并行的tree learner
‘voting’: 投票并行的tree learner
num_threads 或者num_thread 或者nthread:一个整数, 给出了lightgbm 的线程数。默认为OpenMP_default。
为了更快的速度,应该将它设置为真正的CPU 内核数,而不是线程的数量(大多数CPU 使用超线程来使每个CPU内核生成2个线程)。
当数据集较小的时候,不要将它设置的过大
对于并行学习,不应该使用全部的CPU核心,因为这会使得网络性能不佳
device: 一个字符串,指定计算设备。默认为’cpu’。 可以为’gpu’,’cpu’。
建议使用较小的max_bin 来获得更快的计算速度
为了加快学习速度,GPU 默认使用32位浮点数来求和。你可以设置gpu_use_dp=True 来启动64位浮点数,但是它会使得训练速度降低。
学习控制参数:

max_depth: 一个整数,限制了树模型的最大深度,默认值为-1。如果小于0,则表示没有限制。
min_data_in_leaf 或者 min_data_per_leaf 或者 min_data或者min_child_samples: 一个整数,表示一个叶子节点上包含的最少样本数量。默认值为 20
min_sum_hessian_in_leaf 或者 min_sum_hessian_per_leaf或者 min_sum_hessian 或者 min_hessian或者min_child_weight: 一个浮点数,表示一个叶子节点上的最小hessian 之和。(也就是叶节点样本权重之和的最小值) 默认为1e-3 。
feature_fraction或者sub_feature或者colsample_bytree:一个浮点数,取值范围为[0.0,1.0], 默认值为0。如果小于1.0,则lightgbm 会在每次迭代中随机选择部分特征。如0.8 表示:在每棵树训练之前选择80% 的特征来训练。
feature_fraction_seed: 一个整数,表示feature_fraction 的随机数种子,默认为2。
bagging_fraction 或者sub_row 或者 subsample:一个浮点数,取值范围为[0.0,1.0], 默认值为0。如果小于1.0,则lightgbm 会在每次迭代中随机选择部分样本来训练(非重复采样)。如0.8 表示:在每棵树训练之前选择80% 的样本(非重复采样)来训练。
bagging_freq 或者subsample_freq:一个整数,表示每bagging_freq 次执行bagging。如果该参数为0,表示禁用bagging。
bagging_seed 或者 bagging_fraction_seed:一个整数,表示bagging 的随机数种子,默认为 3 。
early_stopping_round 或者 early_stopping_rounds或者early_stopping:一个整数,默认为0。如果一个验证集的度量在early_stopping_round 循环中没有提升,则停止训练。如果为0则表示不开启早停。
lambda_l1 或者reg_alpha: 一个浮点数,表示L1正则化系数。默认为0
lambda_l2 或者reg_lambda: 一个浮点数,表示L2正则化系数。默认为0
min_split_gain 或者min_gain_to_split: 一个浮点数,表示执行切分的最小增益,默认为0
drop_rate: 一个浮点数,取值范围为[0.0,1.0],表示dropout 的比例,默认为1。 该参数仅在dart 中使用
skip_drop: 一个浮点数,取值范围为[0.0,1.0],表示跳过dropout 的概率,默认为5。 该参数仅在dart 中使用
max_drop: 一个整数,表示一次迭代中删除树的最大数量,默认为50。 如果小于等于0,则表示没有限制。 该参数仅在dart 中使用
uniform_drop:一个布尔值,表示是否想要均匀的删除树,默认值为False。 该参数仅在dart 中使用
xgboost_dart_mode: 一个布尔值,表示是否使用xgboost dart 模式,默认值为False。该参数仅在dart 中使用
drop_seed: 一个整数,表示dropout 的随机数种子,默认值为 4。 该参数仅在dart 中使用
top_rate: 一个浮点数,取值范围为[0.0,1.0],表示在goss 中,大梯度数据的保留比例,默认值为2。该参数仅在goss 中使用
other_rate: 一个浮点数,取值范围为[0.0,1.0],表示在goss 中,小梯度数据的保留比例,默认值为1。该参数仅在goss 中使用
min_data_per_group:一个整数,表示每个分类组的最小数据量,默认值为100。用于排序任务
max_cat_threshold: 一个整数,表示category 特征的取值集合的最大大小。默认为 32 。
cat_smooth: 一个浮点数,用于category 特征的概率平滑。默认值为 10。它可以降低噪声在category 特征中的影响,尤其是对于数据很少的类。
cat_l2: 一个浮点数,用于category 切分中的L2 正则化系数。默认为 10 。
top_k 或者 topk: 一个整数,用于投票并行中。默认为20 。将它设置为更大的值可以获得更精确的结果,但是会降低训练速度。
IO 参数:

max_bin: 一个整数,表示最大的桶的数量。默认值为 255。lightgbm 会根据它来自动压缩内存。如max_bin=255 时,则lightgbm 将使用uint8 来表示特征的每一个值。
min_data_in_bin: 一个整数,表示每个桶的最小样本数。默认为3。该方法可以避免出现一个桶只有一个样本的情况。
data_random_seed: 一个整数,表示并行学习数据分隔中的随机数种子。默认为1它不包括特征并行。
output_model或者model_output或者model_out: 一个字符串,表示训练中输出的模型被保存的文件的文件名。默认txt 。
input_model或者model_input或者model_in: 一个字符串,表示输入模型的文件的文件名。默认空字符串。对于prediction任务,该模型将用于预测数据,对于train任务,训练将从该模型继续
output_result或者 predict_result或者prediction_result:一个字符串,给出了prediction 结果存放的文件名。默认为txt。
pre_partition 或者 is_pre_partition: 一个布尔值,指示数据是否已经被划分。默认值为False。 如果为true,则不同的机器使用不同的partition 来训练。它用于并行学习(不包括特征并行)
is_sparse或者 is_enable_sparse或者enable_sparse: 一个布尔值,表示是否开启稀疏优化,默认为True。如果为True则启用稀疏优化。
two_round 或者two_round_loading或者 use_two_round_loading: 一个布尔值,指示是否启动两次加载。默认值为False,表示只需要进行一次加载。默认情况下,lightgbm 会将数据文件映射到内存,然后从内存加载特征,这将提供更快的数据加载速度。但是当数据文件很大时,内存可能会被耗尽。如果数据文件太大,则将它设置为True
save_binary或者is_save_binary或者 is_save_binary_file: 一个布尔值,表示是否将数据集(包括验证集)保存到二进制文件中。默认值为False。如果为True,则可以加快数据的加载速度。
verbosity 或者verbose:一个整数,表示是否输出中间信息。默认值为1。如果小于0,则仅仅输出critical 信息;如果等于0,则还会输出error,warning 信息; 如果大于0,则还会输出info 信息。
header或者has_header:一个布尔值,表示输入数据是否有头部。默认为False。
label 或者label_column:一个字符串,表示标签列。默认为空字符串。你也可以指定一个整数,如label=0 表示第0列是标签列。你也可以为列名添加前缀,如label=prefix:label_name
weight 或者weight_column: 一个字符串,表示样本权重列。默认为空字符串。你也可以指定一个整数,如weight=0 表示第0列是权重列。注意:它是剔除了标签列之后的索引。假如标签列为0,权重列为1,则这里weight=0。你也可以为列名添加前缀,如weight=prefix:weight_name
query 或者query_column或者gourp 或者group_column: 一个字符串,query/group ID 列。默认为空字符串。你也可以指定一个整数,如query=0 表示第0列是query列。注意:它是剔除了标签列之后的索引。假如标签列为0,query列为1,则这里query=0。你也可以为列名添加前缀,如query=prefix:query_name
ignore_column 或者 ignore_feature或者blacklist: 一个字符串,表示训练中忽略的一些列,默认为空字符串。可以用数字做索引,如ignore_column=0,1,2 表示第0,1,2 列将被忽略。注意:它是剔除了标签列之后的索引。
你也可以为列名添加前缀,如ignore_column=prefix:ign_name1,ign_name2
categorical_feature 或者categorical_column或者cat_feature或者 cat_column:一个字符串,指定category 特征的列。默认为空字符串。可以用数字做索引,如categorical_feature=0,1,2 表示第0,1,2 列将作为category 特征。注意:它是剔除了标签列之后的索引。你也可以为列名添加前缀,如categorical_feature=prefix:cat_name1,cat_name2 在categorycal 特征中,负的取值被视作缺失值。
predict_raw_score 或者raw_score或者 is_predict_raw_score:一个布尔值,表示是否预测原始得分。默认为False。如果为True则仅预测原始得分。该参数只用于prediction 任务。
predict_leaf_index 或者 leaf_index或者 is_predict_leaf_index: 一个布尔值,表示是否预测每个样本在每棵树上的叶节点编号。默认为False。在预测时,每个样本都会被分配到每棵树的某个叶子节点上。该参数就是要输出这些叶子节点的编号。该参数只用于prediction 任务。
predict_contrib 或者 contrib或者 is_predict_contrib: 一个布尔值,表示是否输出每个特征对于每个样本的预测的贡献。默认为False。输出的结果形状为[nsamples,nfeatures+1], 之所以+1 是考虑到bais 的贡献。所有的贡献加起来就是该样本的预测结果。该参数只用于prediction 任务。
bin_construct_sample_cnt 或者 subsample_for_bin:一个整数,表示用来构建直方图的样本的数量。默认为200000。如果数据非常稀疏,则可以设置为一个更大的值,如果设置更大的值,则会提供更好的训练效果,但是会增加数据加载时间。
num_iteration_predict: 一个整数,表示在预测中使用多少棵子树。默认为-1。小于等于0表示使用模型的所有子树。该参数只用于prediction 任务。
pred_early_stop:一个布尔值,表示是否使用早停来加速预测。默认为False。如果为True,则可能影响精度。
pred_early_stop_freq: 一个整数,表示检查早停的频率。默认为10
pred_early_stop_margin: 一个浮点数,表示早停的边际阈值。默认为0
use_missing: 一个布尔值,表示是否使用缺失值功能。默认为True如果为False 则禁用缺失值功能。
zero_as_missing: 一个布尔值,表示是否将所有的零(包括在libsvm/sparse矩阵 中未显示的值)都视为缺失值。 默认为False。如果为False,则将nan 视作缺失值。如果为True,则np.nan 和 零都将视作缺失值。
init_score_file: 一个字符串,表示训练时的初始化分数文件的路径。默认为空字符串,表示train_data_file+”.init” (如果存在)
valid_init_score_file: 一个字符串,表示验证时的初始化分数文件的路径。默认为空字符串,表示valid_data_file+”.init” (如果存在)。如果有多个(对应于多个验证集),则可以用逗号, 来分隔。
目标函数的参数:

sigmoid: 一个浮点数,用sigmoid 函数的参数,默认为0。它用于二分类任务和lambdarank 任务。
alpha: 一个浮点数,用于Huber 损失函数和Quantile regression ,默认值为0。它用于huber回归任务和Quantile 回归任务。
fair_c: 一个浮点数,用于Fair 损失函数,默认值为0 。它用于fair 回归任务。
gaussian_eta: 一个浮点数,用于控制高斯函数的宽度,默认值为0 。它用于regression_l1 回归任务和huber回归任务。
posson_max_delta_step: 一个浮点数,用于Poisson regression 的参数,默认值为7 。它用于poisson 回归任务。
scale_pos_weight: 一个浮点数,用于调整正样本的权重,默认值为0它用于二分类任务。
boost_from_average: 一个布尔值,指示是否将初始得分调整为平均值(它可以使得收敛速度更快)。默认为True。它用于回归任务。
is_unbalance或者unbalanced_set : 一个布尔值,指示训练数据是否均衡的。默认为True。它用于二分类任务。
max_position: 一个整数,指示将在这个NDCG 位置优化。默认为 20 。它用于lambdarank 任务。
label_gain: 一个浮点数序列,给出了每个标签的增益。默认值为0,1,3,7,15,….它用于lambdarank 任务。
num_class或者num_classes : 一个整数,指示了多分类任务中的类别数量。默认为 1它用于多分类任务。
reg_sqrt: 一个布尔值,默认为False。如果为True,则拟合的结果为:\sqrt{label}。同时预测的结果被自动转换为:{pred}^2。它用于回归任务。
度量参数:

metric:一个字符串,指定了度量的指标,默认为:对于回归问题,使用l2 ;对于二分类问题,使用binary_logloss;对于lambdarank 问题,使用ndcg。如果有多个度量指标,则用逗号, 分隔。
‘l1’ 或者 mean_absolute_error或者 mae或者 regression_l1: 表示绝对值损失
‘l2’ 或者mean_squared_error或者 mse或者 regression_l2或者 regression:表示平方损失
‘l2_root’ 或者root_mean_squared_error或者 rmse:表示开方损失
‘quantile’: 表示Quantile 回归中的损失
‘mape’ 或者 ‘mean_absolute_percentage_error’ :表示MAPE 损失
‘huber’: 表示huber 损失
‘fair’: 表示fair 损失
‘poisson’: 表示poisson 回归的负对数似然
‘gamma’: 表示gamma 回归的负对数似然
‘gamma_deviance’: 表示gamma 回归的残差的方差
‘tweedie’: 表示Tweedie 回归的负对数似然
‘ndcg’: 表示NDCG
‘map’ 或者’mean_average_precision’: 表示平均的精度
‘auc’: 表示AUC
‘binary_logloss’或者’binary’: 表示二类分类中的对数损失函数
‘binary_error’: 表示二类分类中的分类错误率
‘multi_logloss’或者 ‘multiclass’或者 ‘softmax’或者 ‘multiclassova’或者 ‘multiclass_ova’,或者’ova’或者 ‘ovr’: 表示多类分类中的对数损失函数
‘multi_error’: 表示多分类中的分类错误率
‘xentropy’或者’cross_entropy’: 表示交叉熵
‘xentlambda’ 或者’cross_entropy_lambda’: 表示intensity 加权的交叉熵
‘kldiv’或者’kullback_leibler’: 表示KL 散度
metric_freq或者’output_freq’:一个正式,表示每隔多少次输出一次度量结果。默认为1。
train_metric 或者training_metric或者 is_training_metric: 一个布尔值,默认为False。如果为True,则在训练时就输出度量结果。
ndcg_at 或者 ndcg_eval_at 或者eval_at: 一个整数列表,指定了NDCG 评估点的位置。默认为1,2,3,4,5 。
参考链接:

http://lightgbm.apachecn.org/#/docs/6
http://www.huaxiaozhuan.com/%E5%B7%A5%E5%85%B7/lightgbm/chapters/lightgbm_usage.html
https://lightgbm.readthedocs.io/en/latest/Parameters.html

调参示例:

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

import lightgbm as lgb

X = df.iloc[:,:-1]

y = df.iloc[:,-1]

category_feature=[0,1,2,3,4,5,6,7,8,9,10,11,12,13]

cv_params = {

    'num_leaves': [13,14,15],

#     'max_depth': [-1,4,6,8],

#     'learning_rate': [0.07,0.08,0.09],

#     'n_estimators':[10,15,20],

#     'min_child_samples':[15,20,25],

#     'subsample':[0.4,0.5,0.6,0.7],

#     'colsample_bytree':[0.4,0.5,0.6,0.7],

#     'reg_alpha':[0,1,2,3,5,8],

#     'reg_lambda':[7,8,9,10],

#     'num_iterations':[30,40,50],

#     'min_data_in_leaf': [30, 50, 100, 300, 400],

#     'cat_smooth':[150,160,170,180,190]

}

# cv_params = {'learning_rate': [0.06,0.07,0.08,0.09]}

other_params = {

    'max_depth' : 4,

    'num_leaves': 15,

    'learning_rate': 0.07,

    'cat_smooth':180,

    'num_iterations':100,

    'colsample_bytree': 0.7,

    'subsample': 0.4,

    'reg_alpha':3,

    'reg_lambda':9,

}

model_lgb = lgb.LGBMRegressor(**other_params)

optimized_lgb = GridSearchCV(estimator=model_lgb, param_grid=cv_params, scoring='r2', cv=5, verbose=1, n_jobs=2)

optimized_lgb.fit(X, y, categorical_feature=category_feature)

print('参数的最佳取值:{0}'.format(optimized_lgb.best_params_))

print('最佳模型得分:{0}'.format(optimized_lgb.best_score_))

print(optimized_lgb.cv_results_['mean_test_score'])

print(optimized_lgb.cv_results_['params'])

sklearn接口形式的LightGBM示例

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

import lightgbm as lgb

from sklearn.metrics import mean_squared_error

from sklearn.model_selection import GridSearchCV

from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split

# 加载数据

iris = load_iris()

data = iris.data

target = iris.target

X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2)

# 创建模型,训练模型

gbm = lgb.LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.05, n_estimators=20)

gbm.fit(X_train, y_train, eval_set=[(X_test, y_test)], eval_metric='l1', early_stopping_rounds=5)

# 测试机预测

y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration_)

# 模型评估

print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5)

# feature importances

print('Feature importances:', list(gbm.feature_importances_))

# 网格搜索,参数优化

estimator = lgb.LGBMRegressor(num_leaves=31)

param_grid = {

    'learning_rate': [0.01, 0.1, 1],

    'n_estimators': [20, 40]

}

gbm = GridSearchCV(estimator, param_grid)

gbm.fit(X_train, y_train)

print('Best parameters found by grid search are:', gbm.best_params_)

原生形式使用lightgbm

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

import lightgbm as lgb

from sklearn.metrics import mean_squared_error

from sklearn.datasets import load_iris

from sklearn.model_selection import train_test_split

iris = load_iris()

data = iris.data

target = iris.target

X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2)

# 创建成lgb特征的数据集格式

lgb_train = lgb.Dataset(X_train, y_train)

lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train)

# 将参数写成字典下形式

params = {

    'task': 'train',

    'boosting_type': 'gbdt',  # 设置提升类型

    'objective': 'regression',  # 目标函数

    'metric': {'l2', 'auc'},  # 评估函数

    'num_leaves': 31,  # 叶子节点数

    'learning_rate': 0.05,  # 学习速率

    'feature_fraction': 0.9,  # 建树的特征选择比例

    'bagging_fraction': 0.8,  # 建树的样本采样比例

    'bagging_freq': 5,  # k 意味着每 k 次迭代执行bagging

    'verbose': 1  # <0 显示致命的, =0 显示错误 (警告), >0 显示信息

}

# 训练 cv and train

gbm = lgb.train(params, lgb_train, num_boost_round=20, valid_sets=lgb_eval, early_stopping_rounds=5)

# 保存模型到文件

gbm.save_model('model.txt')

# 预测数据集

y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration)

# 评估模型

print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5)

参数速查

xgblgbxgb.sklearnlgb.sklearn
booster=’gbtree’boosting=’gbdt’booster=’gbtree’boosting_type=’gbdt’
objective=’binary:logistic’application=’binary’objective=’binary:logistic’objective=’binary’
max_depth=7num_leaves=2**7max_depth=7num_leaves=2**7
eta=0.1learning_rate=0.1learning_rate=0.1learning_rate=0.1
num_boost_round=10num_boost_round=10n_estimators=10n_estimators=10
gamma=0min_split_gain=0.0gamma=0min_split_gain=0.0
min_child_weight=5min_child_weight=5min_child_weight=5min_child_weight=5
subsample=1bagging_fraction=1subsample=1.0subsample=1.0
colsample_bytree=1.0feature_fraction=1colsample_bytree=1.0colsample_bytree=1.0
alpha=0lambda_l1=0reg_alpha=0.0reg_alpha=0.0
lambda=1lambda_l2=0reg_lambda=1reg_lambda=0.0
scale_pos_weight=1scale_pos_weight=1scale_pos_weight=1scale_pos_weight=1
seedbagging_seed feature_fraction_seedrandom_state=888random_state=888
nthreadnum_threadsn_jobs=4n_jobs=4
evalsvalid_setseval_seteval_set
eval_metricmetriceval_metriceval_metric
early_stopping_roundsearly_stopping_roundsearly_stopping_roundsearly_stopping_rounds
verbose_evalverbose_evalverboseverbose

参考链接:https://bacterous.github.io/2018/09/13/LightGBM%E4%BD%BF%E7%94%A8/

更多参考

在模型fit数据的时候可以操作下面这些参数:(下面这些参数的具体含义上面基本都有)

Parameters
        ----------
        X : array-like or sparse matrix of shape = [n_samples, n_features]
            Input feature matrix.
        y : array-like of shape = [n_samples]
            The target values (class labels in classification, real numbers in regression).
        sample_weight : array-like of shape = [n_samples] or None, optional (default=None)
            Weights of training data.
        init_score : array-like of shape = [n_samples] or None, optional (default=None)
            Init score of training data.
        group : array-like or None, optional (default=None)
            Group data of training data.
        eval_set : list or None, optional (default=None)
            A list of (X, y) tuple pairs to use as validation sets.
        eval_names : list of strings or None, optional (default=None)
            Names of eval_set.
        eval_sample_weight : list of arrays or None, optional (default=None)
            Weights of eval data.
        eval_class_weight : list or None, optional (default=None)
            Class weights of eval data.
        eval_init_score : list of arrays or None, optional (default=None)
            Init score of eval data.
        eval_group : list of arrays or None, optional (default=None)
            Group data of eval data.
        eval_metric : string, list of strings, callable or None, optional (default=None)
            If string, it should be a built-in evaluation metric to use.
            If callable, it should be a custom evaluation metric, see note below for more details.
            In either case, the ``metric`` from the model parameters will be evaluated and used as well.
            Default: 'l2' for LGBMRegressor, 'logloss' for LGBMClassifier, 'ndcg' for LGBMRanker.
        early_stopping_rounds : int or None, optional (default=None)
            Activates early stopping. The model will train until the validation score stops improving.
            Validation score needs to improve at least every ``early_stopping_rounds`` round(s)
            to continue training.
            Requires at least one validation data and one metric.
            If there's more than one, will check all of them. But the training data is ignored anyway.
            To check only the first metric, set the ``first_metric_only`` parameter to ``True``
            in additional parameters ``**kwargs`` of the model constructor.
        verbose : bool or int, optional (default=True)
            Requires at least one evaluation data.
            If True, the eval metric on the eval set is printed at each boosting stage.
            If int, the eval metric on the eval set is printed at every ``verbose`` boosting stage.
            The last boosting stage or the boosting stage found by using ``early_stopping_rounds`` is also printed.

            .. rubric:: Example

            With ``verbose`` = 4 and at least one item in ``eval_set``,
            an evaluation metric is printed every 4 (instead of 1) boosting stages.

        feature_name : list of strings or 'auto', optional (default='auto')
            Feature names.
            If 'auto' and data is pandas DataFrame, data columns names are used.
        categorical_feature : list of strings or int, or 'auto', optional (default='auto')
            Categorical features.
            If list of int, interpreted as indices.
            If list of strings, interpreted as feature names (need to specify ``feature_name`` as well).
            If 'auto' and data is pandas DataFrame, pandas unordered categorical columns are used.
            All values in categorical features should be less than int32 max value (2147483647).
            Large values could be memory consuming. Consider using consecutive integers starting from zero.
            All negative values in categorical features will be treated as missing values.
            The output cannot be monotonically constrained with respect to a categorical feature.
        callbacks : list of callback functions or None, optional (default=None)
            List of callback functions that are applied at each iteration.
            See Callbacks in Python API for more information.

调参开始

部分参考博客:LightGBM调参笔记_浅笑古今的博客-CSDN博客

第一步:学习率和迭代次数


我们先把学习率先定一个较高的值,这里取 learning_rate = 0.1,其次确定估计器boosting/boost/boosting_type的类型,不过默认都会选gbdt。

迭代的次数,也可以说是残差树的数目,参数名为n_estimators/num_iterations/num_round/num_boost_round。我们可以先将该参数设成一个较大的数,然后在cv结果中查看最优的迭代次数,具体如代码。

在这之前,我们必须给其他重要的参数一个初始值。初始值的意义不大,只是为了方便确定其他参数。下面先给定一下初始值:

以下参数根据具体项目要求定:(如果是回归,那么objective中的binary需要修改为regression)

'boosting_type'/'boosting': 'gbdt'
'objective': 'binary'
'metric': 'auc'

以下是我选择的初始值:

'max_depth': 5     # 由于数据集不是很大,所以选择了一个适中的值,其实4-10都无所谓。
'num_leaves': 30   # 由于lightGBM是leaves_wise生长,官方说法是要小于2^max_depth
'subsample'/'bagging_fraction':0.8           # 数据采样
'colsample_bytree'/'feature_fraction': 0.8   # 特征采样
 

下面用cv确定迭代次数

import pandas as pd
import lightgbm as lgb
from sklearn.datasets import load_breast_cancer
from sklearn.cross_validation import train_test_split
 
canceData=load_breast_cancer()
X=canceData.data
y=canceData.target
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)
params = {    
          'boosting_type': 'gbdt',
          'objective': 'binary',
          'metric': 'auc',
          'nthread':4,
          'learning_rate':0.1,
          'num_leaves':30, 
          'max_depth': 5,   
          'subsample': 0.8, 
          'colsample_bytree': 0.8, 
    }
    
data_train = lgb.Dataset(X_train, y_train)
cv_results = lgb.cv(params, data_train, num_boost_round=1000, nfold=5, stratified=False, shuffle=True, metrics='auc',early_stopping_rounds=50,seed=0)
print('best n_estimators:', len(cv_results['auc-mean']))
print('best cv score:', pd.Series(cv_results['auc-mean']).max())
输出结果如下:

('best n_estimators:', 188)
('best cv score:', 0.99134716298085424)

我们根据以上结果,取n_estimators=188。

第二步:确定max_depth和num_leaves

这是提高精确度的最重要的参数。

max_depth :设置树深度,深度越大可能过拟合

num_leaves:因为 LightGBM 使用的是 leaf-wise 的算法,因此在调节树的复杂程度时,使用的是 num_leaves 而不是 max_depth。大致换算关系:num_leaves = 2^(max_depth),但是它的值的设置应该小于 2^(max_depth),否则可能会导致过拟合。

我们也可以同时调节这两个参数,对于这两个参数调优,我们先粗调,再细调:

这里我们引入sklearn里的GridSearchCV()函数进行搜索。

params_test1={'max_depth': range(3,8,1), 'num_leaves':range(5, 100, 5)}
              
gsearch1 = GridSearchCV(estimator = lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.1, n_estimators=188, max_depth=6, bagging_fraction = 0.8,feature_fraction = 0.8), 
                       param_grid = params_test1, scoring='roc_auc',cv=5,n_jobs=-1)
gsearch1.fit(X_train,y_train)
gsearch1.grid_scores_, gsearch1.best_params_, gsearch1.best_score_

 结果如下:

([mean: 0.99248, std: 0.01033, params: {'num_leaves': 5, 'max_depth': 3},
  mean: 0.99227, std: 0.01013, params: {'num_leaves': 10, 'max_depth': 3},
  mean: 0.99227, std: 0.01013, params: {'num_leaves': 15, 'max_depth': 3},
 ······
  mean: 0.99331, std: 0.00775, params: {'num_leaves': 85, 'max_depth': 7},
  mean: 0.99331, std: 0.00775, params: {'num_leaves': 90, 'max_depth': 7},
  mean: 0.99331, std: 0.00775, params: {'num_leaves': 95, 'max_depth': 7}],
 {'max_depth': 4, 'num_leaves': 10},
 0.9943573667711598)

如果metrics='rmse'(很多比赛都要求均方误差),这里必须说一下,sklearn模型评估里的scoring参数都是采用的higher return values are better than lower return values(较高的返回值优于较低的返回值)。但是,我采用的metric策略采用的是均方误差(rmse),越低越好,所以sklearn就提供了neg_mean_squared_erro参数,也就是返回metric的负数,所以就均方差来说,也就变成负数越大越好了。

如果用rmse:

所以,可以看到,最优解的分数为-1.860,转化为均方差为np.sqrt(-(-1.860)) = 1.3639。

第三步:确定min_data_in_leaf和max_bin in

说到这里,就该降低过拟合了。

min_data_in_leaf 是一个很重要的参数, 也叫min_child_samples,它的值取决于训练数据的样本个树和num_leaves. 将其设置的较大可以避免生成一个过深的树, 但有可能导致欠拟合。

min_sum_hessian_in_leaf:也叫min_child_weight,使一个结点分裂的最小海森值之和,真拗口(Minimum sum of hessians in one leaf to allow a split. Higher values potentially decrease overfitting)

我们采用跟上面相同的方法进行:

params_test2={'max_bin': range(5,256,10), 'min_data_in_leaf':range(1,102,10)}
              
gsearch2 = GridSearchCV(estimator = lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.1, n_estimators=188, max_depth=4, num_leaves=10,bagging_fraction = 0.8,feature_fraction = 0.8), 
                       param_grid = params_test2, scoring='roc_auc',cv=5,n_jobs=-1)
gsearch2.fit(X_train,y_train)
gsearch2.grid_scores_, gsearch2.best_params_, gsearch2.best_score_
([mean: 0.98715, std: 0.01044, params: {'min_data_in_leaf': 1, 'max_bin': 5},
  mean: 0.98809, std: 0.01095, params: {'min_data_in_leaf': 11, 'max_bin': 5},
  mean: 0.98809, std: 0.00952, params: {'min_data_in_leaf': 21, 'max_bin': 5},
······
  mean: 0.99363, std: 0.00812, params: {'min_data_in_leaf': 81, 'max_bin': 255},
  mean: 0.99133, std: 0.00788, params: {'min_data_in_leaf': 91, 'max_bin': 255},
  mean: 0.98882, std: 0.01223, params: {'min_data_in_leaf': 101, 'max_bin': 255}],
 {'max_bin': 15, 'min_data_in_leaf': 51},
 0.9952978056426331)

第四步:确定feature_fraction、bagging_fraction、bagging_freq

这两个参数都是为了降低过拟合的。

feature_fraction参数来进行特征的子抽样。这个参数可以用来防止过拟合及提高训练速度。

bagging_fraction+bagging_freq参数必须同时设置,bagging_fraction相当于subsample样本采样,可以使bagging更快的运行,同时也可以降拟合。bagging_freq默认0,表示bagging的频率,0意味着没有使用bagging,k意味着每k轮迭代进行一次bagging。

不同的参数,同样的方法。

 params_test3={'feature_fraction': [0.6,0.7,0.8,0.9,1.0],
              'bagging_fraction': [0.6,0.7,0.8,0.9,1.0],
              'bagging_freq': range(0,81,10)
}
              
gsearch3 = GridSearchCV(estimator = lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.1, n_estimators=188, max_depth=4, num_leaves=10,max_bin=15,min_data_in_leaf=51), 
                       param_grid = params_test3, scoring='roc_auc',cv=5,n_jobs=-1)
gsearch3.fit(X_train,y_train)
gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_
([mean: 0.99467, std: 0.00710, params: {'bagging_freq': 0, 'bagging_fraction': 0.6, 'feature_fraction': 0.6},
  mean: 0.99415, std: 0.00804, params: {'bagging_freq': 0, 'bagging_fraction': 0.6, 'feature_fraction': 0.7},
  mean: 0.99530, std: 0.00722, params: {'bagging_freq': 0, 'bagging_fraction': 0.6, 'feature_fraction': 0.8},
······
  mean: 0.99530, std: 0.00722, params: {'bagging_freq': 80, 'bagging_fraction': 1.0, 'feature_fraction': 0.8},
  mean: 0.99383, std: 0.00731, params: {'bagging_freq': 80, 'bagging_fraction': 1.0, 'feature_fraction': 0.9},
  mean: 0.99383, std: 0.00766, params: {'bagging_freq': 80, 'bagging_fraction': 1.0, 'feature_fraction': 1.0}],
 {'bagging_fraction': 0.6, 'bagging_freq': 0, 'feature_fraction': 0.8},
 0.9952978056426331)

第五步:确定lambda_l1和lambda_l2

正则化参数lambda_l1(reg_alpha), lambda_l2(reg_lambda),毫无疑问,是降低过拟合的,两者分别对应l1正则化和l2正则化。我们也来尝试一下使用这两个参数。
params_test4={'lambda_l1': [1e-5,1e-3,1e-1,0.0,0.1,0.3,0.5,0.7,0.9,1.0],
              'lambda_l2': [1e-5,1e-3,1e-1,0.0,0.1,0.3,0.5,0.7,0.9,1.0]
}
              
gsearch4 = GridSearchCV(estimator = lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.1, n_estimators=188, max_depth=4, num_leaves=10,max_bin=15,min_data_in_leaf=51,bagging_fraction=0.6,bagging_freq= 0, feature_fraction= 0.8), 
                       param_grid = params_test4, scoring='roc_auc',cv=5,n_jobs=-1)
gsearch4.fit(X_train,y_train)
gsearch4.grid_scores_, gsearch4.best_params_, gsearch4.best_score_
([mean: 0.99530, std: 0.00722, params: {'lambda_l1': 1e-05, 'lambda_l2': 1e-05},
  mean: 0.99415, std: 0.00804, params: {'lambda_l1': 1e-05, 'lambda_l2': 0.001},
  mean: 0.99331, std: 0.00826, params: {'lambda_l1': 1e-05, 'lambda_l2': 0.1},
·····
  mean: 0.99049, std: 0.01047, params: {'lambda_l1': 1.0, 'lambda_l2': 0.7},
  mean: 0.99049, std: 0.01013, params: {'lambda_l1': 1.0, 'lambda_l2': 0.9},
  mean: 0.99070, std: 0.01071, params: {'lambda_l1': 1.0, 'lambda_l2': 1.0}],
 {'lambda_l1': 1e-05, 'lambda_l2': 1e-05},
 0.9952978056426331)

第六步:确定 min_split_gain 

params_test5={'min_split_gain':[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]}
              
gsearch5 = GridSearchCV(estimator = lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.1, n_estimators=188, max_depth=4, num_leaves=10,max_bin=15,min_data_in_leaf=51,bagging_fraction=0.6,bagging_freq= 0, feature_fraction= 0.8,
lambda_l1=1e-05,lambda_l2=1e-05), 
                       param_grid = params_test5, scoring='roc_auc',cv=5,n_jobs=-1)
gsearch5.fit(X_train,y_train)
gsearch5.grid_scores_, gsearch5.best_params_, gsearch5.best_score_
([mean: 0.99530, std: 0.00722, params: {'min_split_gain': 0.0},
  mean: 0.99415, std: 0.00810, params: {'min_split_gain': 0.1},
  mean: 0.99394, std: 0.00898, params: {'min_split_gain': 0.2},
  mean: 0.99373, std: 0.00918, params: {'min_split_gain': 0.3},
  mean: 0.99404, std: 0.00845, params: {'min_split_gain': 0.4},
  mean: 0.99300, std: 0.00958, params: {'min_split_gain': 0.5},
  mean: 0.99258, std: 0.00960, params: {'min_split_gain': 0.6},
  mean: 0.99227, std: 0.01071, params: {'min_split_gain': 0.7},
  mean: 0.99342, std: 0.00872, params: {'min_split_gain': 0.8},
  mean: 0.99206, std: 0.01062, params: {'min_split_gain': 0.9},
  mean: 0.99206, std: 0.01064, params: {'min_split_gain': 1.0}],
 {'min_split_gain': 0.0},
 0.9952978056426331)

第七步:降低学习率,增加迭代次数,验证模型

model=lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.01, n_estimators=1000, max_depth=4, num_leaves=10,max_bin=15,min_data_in_leaf=51,bagging_fraction=0.6,bagging_freq= 0, feature_fraction= 0.8,
lambda_l1=1e-05,lambda_l2=1e-05,min_split_gain=0)
model.fit(X_train,y_train)
y_pre=model.predict(X_test)
print("acc:",metrics.accuracy_score(y_test,y_pre))
print("auc:",metrics.roc_auc_score(y_test,y_pre))

结果如下:

('acc:', 0.97368421052631582)
('auc:', 0.9744363289933311)

而使用默认参数时,模型表现如下:

model=lgb.LGBMClassifier()
model.fit(X_train,y_train)
y_pre=model.predict(X_test)
print("acc:",metrics.accuracy_score(y_test,y_pre))
print("auc:",metrics.roc_auc_score(y_test,y_pre))
('acc:', 0.96491228070175439)
('auc:', 0.96379803112099083)

我们可以看出在准确率和AUC得分都有所提高。

3.LightGBM的cv函数调参

这种方式比较省事儿,写好代码自动寻优,但需要有调参经验,如何设置较好的参数范围有一定的技术含量,这里直接给出代码。

import pandas as pd
import lightgbm as lgb
from sklearn import metrics
from sklearn.datasets import load_breast_cancer
from sklearn.cross_validation import train_test_split
 
canceData=load_breast_cancer()
X=canceData.data
y=canceData.target
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)
 
### 数据转换
print('数据转换')
lgb_train = lgb.Dataset(X_train, y_train, free_raw_data=False)
lgb_eval = lgb.Dataset(X_test, y_test, reference=lgb_train,free_raw_data=False)
 
### 设置初始参数--不含交叉验证参数
print('设置参数')
params = {
          'boosting_type': 'gbdt',
          'objective': 'binary',
          'metric': 'auc',
          'nthread':4,
          'learning_rate':0.1
          }
 
### 交叉验证(调参)
print('交叉验证')
max_auc = float('0')
best_params = {}
 
# 准确率
print("调参1:提高准确率")
for num_leaves in range(5,100,5):
    for max_depth in range(3,8,1):
        params['num_leaves'] = num_leaves
        params['max_depth'] = max_depth
 
        cv_results = lgb.cv(
                            params,
                            lgb_train,
                            seed=1,
                            nfold=5,
                            metrics=['auc'],
                            early_stopping_rounds=10,
                            verbose_eval=True
                            )
            
        mean_auc = pd.Series(cv_results['auc-mean']).max()
        boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()
            
        if mean_auc >= max_auc:
            max_auc = mean_auc
            best_params['num_leaves'] = num_leaves
            best_params['max_depth'] = max_depth
if 'num_leaves' and 'max_depth' in best_params.keys():          
    params['num_leaves'] = best_params['num_leaves']
    params['max_depth'] = best_params['max_depth']
 
# 过拟合
print("调参2:降低过拟合")
for max_bin in range(5,256,10):
    for min_data_in_leaf in range(1,102,10):
            params['max_bin'] = max_bin
            params['min_data_in_leaf'] = min_data_in_leaf
            
            cv_results = lgb.cv(
                                params,
                                lgb_train,
                                seed=1,
                                nfold=5,
                                metrics=['auc'],
                                early_stopping_rounds=10,
                                verbose_eval=True
                                )
                    
            mean_auc = pd.Series(cv_results['auc-mean']).max()
            boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()
 
            if mean_auc >= max_auc:
                max_auc = mean_auc
                best_params['max_bin']= max_bin
                best_params['min_data_in_leaf'] = min_data_in_leaf
if 'max_bin' and 'min_data_in_leaf' in best_params.keys():
    params['min_data_in_leaf'] = best_params['min_data_in_leaf']
    params['max_bin'] = best_params['max_bin']
 
print("调参3:降低过拟合")
for feature_fraction in [0.6,0.7,0.8,0.9,1.0]:
    for bagging_fraction in [0.6,0.7,0.8,0.9,1.0]:
        for bagging_freq in range(0,50,5):
            params['feature_fraction'] = feature_fraction
            params['bagging_fraction'] = bagging_fraction
            params['bagging_freq'] = bagging_freq
            
            cv_results = lgb.cv(
                                params,
                                lgb_train,
                                seed=1,
                                nfold=5,
                                metrics=['auc'],
                                early_stopping_rounds=10,
                                verbose_eval=True
                                )
                    
            mean_auc = pd.Series(cv_results['auc-mean']).max()
            boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()
 
            if mean_auc >= max_auc:
                max_auc=mean_auc
                best_params['feature_fraction'] = feature_fraction
                best_params['bagging_fraction'] = bagging_fraction
                best_params['bagging_freq'] = bagging_freq
 
if 'feature_fraction' and 'bagging_fraction' and 'bagging_freq' in best_params.keys():
    params['feature_fraction'] = best_params['feature_fraction']
    params['bagging_fraction'] = best_params['bagging_fraction']
    params['bagging_freq'] = best_params['bagging_freq']
 
 
print("调参4:降低过拟合")
for lambda_l1 in [1e-5,1e-3,1e-1,0.0,0.1,0.3,0.5,0.7,0.9,1.0]:
    for lambda_l2 in [1e-5,1e-3,1e-1,0.0,0.1,0.4,0.6,0.7,0.9,1.0]:
        params['lambda_l1'] = lambda_l1
        params['lambda_l2'] = lambda_l2
        cv_results = lgb.cv(
                            params,
                            lgb_train,
                            seed=1,
                            nfold=5,
                            metrics=['auc'],
                            early_stopping_rounds=10,
                            verbose_eval=True
                            )
                
        mean_auc = pd.Series(cv_results['auc-mean']).max()
        boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()
 
        if mean_auc >= max_auc:
            max_auc=mean_auc
            best_params['lambda_l1'] = lambda_l1
            best_params['lambda_l2'] = lambda_l2
if 'lambda_l1' and 'lambda_l2' in best_params.keys():
    params['lambda_l1'] = best_params['lambda_l1']
    params['lambda_l2'] = best_params['lambda_l2']
 
print("调参5:降低过拟合2")
for min_split_gain in [0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]:
    params['min_split_gain'] = min_split_gain
    
    cv_results = lgb.cv(
                        params,
                        lgb_train,
                        seed=1,
                        nfold=5,
                        metrics=['auc'],
                        early_stopping_rounds=10,
                        verbose_eval=True
                        )
            
    mean_auc = pd.Series(cv_results['auc-mean']).max()
    boost_rounds = pd.Series(cv_results['auc-mean']).idxmax()
 
    if mean_auc >= max_auc:
        max_auc=mean_auc
        
        best_params['min_split_gain'] = min_split_gain
if 'min_split_gain' in best_params.keys():
    params['min_split_gain'] = best_params['min_split_gain']
 
print(best_params)

结果如下:

{'bagging_fraction': 0.7,
 'bagging_freq': 30,
 'feature_fraction': 0.8,
 'lambda_l1': 0.1,
 'lambda_l2': 0.0,
 'max_bin': 255,
 'max_depth': 4,
 'min_data_in_leaf': 81,
 'min_split_gain': 0.1,
 'num_leaves': 10}

我们将训练得到的参数代入模型

model=lgb.LGBMClassifier(boosting_type='gbdt',objective='binary',metrics='auc',learning_rate=0.01, n_estimators=1000, max_depth=4, num_leaves=10,max_bin=255,min_data_in_leaf=81,bagging_fraction=0.7,bagging_freq= 30, feature_fraction= 0.8,
lambda_l1=0.1,lambda_l2=0,min_split_gain=0.1)
model.fit(X_train,y_train)
y_pre=model.predict(X_test)
print("acc:",metrics.accuracy_score(y_test,y_pre))
print("auc:",metrics.roc_auc_score(y_test,y_pre))

结果如下:

('acc:', 0.98245614035087714)
('auc:', 0.98189901556049541)

使用hyperopt对Lightgbm调参----自动调参

微软的lightgbm已经成为了数据挖掘竞赛的必用工具,运行速度快,准确率高等等各种优点。

调参也是竞赛中不可缺少的一步,常规的调参方法有网格搜索,贝叶斯调参等,或者就是部分大佬的手动直接调参,这种级别需要大量的经验累积,23333。

今天介绍一个调参包----hyperopt,可以对lgb进行自动调参,本次先介绍使用hyperopt对lightgbm进行自动调参,下次再更交叉验证~

关于Hyperopt

hyperopt:是python中的一个用于"分布式异步算法组态/超参数优化"的类库。使用它我们可以拜托繁杂的超参数优化过程,自动获取最佳的超参数。广泛意义上,可以将带有超参数的模型看作是一个必然的非凸函数,因此hyperopt几乎可以稳定的获取比手工更加合理的调参结果。尤其对于调参比较复杂的模型而言,其更是能以远快于人工调参的速度同样获得远远超过人工调参的最终性能。

使用iris数据集来进行演示:

导入数据

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
import lightgbm as lgb
from sklearn.model_selection import train_test_split
#导入数据
data_iris=load_iris()
X,y=data_iris.data,data_iris.target
#划分数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=100)
train_data = lgb.Dataset(data=X_train,label=y_train)
test_data = lgb.Dataset(data=X_test,label=y_test)

迁移一:自动调参

定义参数空间

使用hyperopt自带的函数定义参数空间,但是因为其randint()方法产生的数组范围是从0开始的,所以我额外定义了一个数据转换方法,对原始参数空间进行一次转换。

from hyperopt import fmin, tpe, hp, partial

# 自定义hyperopt的参数空间
space = {"max_depth": hp.randint("max_depth", 15),
         "num_trees": hp.randint("num_trees", 300),
         'learning_rate': hp.uniform('learning_rate', 1e-3, 5e-1),
         "bagging_fraction": hp.randint("bagging_fraction", 5),
         "num_leaves": hp.randint("num_leaves", 6),
         }

def argsDict_tranform(argsDict, isPrint=False):
    argsDict["max_depth"] = argsDict["max_depth"] + 5
    argsDict['num_trees'] = argsDict['num_trees'] + 150
    argsDict["learning_rate"] = argsDict["learning_rate"] * 0.02 + 0.05
    argsDict["bagging_fraction"] = argsDict["bagging_fraction"] * 0.1 + 0.5
    argsDict["num_leaves"] = argsDict["num_leaves"] * 3 + 10
    if isPrint:
        print(argsDict)
    else:
        pass

    return argsDict

创建模型工厂与分数获取器

lightgbm模型工厂用于生产我们需要的model,而分数获取器则是为了解耦。这样在实际的测试工作中可以更加方便地套用代码。

from sklearn.metrics import mean_squared_error

def lightgbm_factory(argsDict):
    argsDict = argsDict_tranform(argsDict)

    params = {'nthread': -1,  # 进程数
              'max_depth': argsDict['max_depth'],  # 最大深度
              'num_trees': argsDict['num_trees'],  # 树的数量
              'eta': argsDict['learning_rate'],  # 学习率
              'bagging_fraction': argsDict['bagging_fraction'],  # bagging采样数
              'num_leaves': argsDict['num_leaves'],  # 终点节点最小样本占比的和
              'objective': 'regression',
              'feature_fraction': 0.7,  # 样本列采样
              'lambda_l1': 0,  # L1 正则化
              'lambda_l2': 0,  # L2 正则化
              'bagging_seed': 100,  # 随机种子,light中默认为100
              }
    #rmse
    params['metric'] = ['rmse']

    model_lgb = lgb.train(params, train_data, num_boost_round=300, valid_sets=[test_data],early_stopping_rounds=100)

    return get_tranformer_score(model_lgb)

def get_tranformer_score(tranformer):

    model = tranformer
    prediction = model.predict(X_test, num_iteration=model.best_iteration)

    return mean_squared_error(y_test, prediction)

调用Hyperopt开始调参

之后我们调用hyperopt进行自动调参即可,同时通过返回值获取最佳模型的结果。

# 开始使用hyperopt进行自动调参
algo = partial(tpe.suggest, n_startup_jobs=1)
best = fmin(lightgbm_factory, space, algo=algo, max_evals=20, pass_expr_memo_ctrl=None)

结果:

Early stopping, best iteration is:
[125]   valid_0's rmse: 0.220095

展示结果

展示我们获取的最佳参数,以及该模型在训练集上的最终表现,如果想要使用交叉验证请参考其他教程。

RMSE = lightgbm_factory(best)
print('best :', best)
print('best param after transform :')
argsDict_tranform(best,isPrint=True)
print('rmse of the best lightgbm:', np.sqrt(RMSE))

结果:

Early stopping, best iteration is:
[135]   valid_0's rmse: 0.21918
best : {'bagging_fraction': 0.5, 'learning_rate': 0.050207534543127846, 'max_depth': 17, 'num_leaves': 25, 'num_trees': 250}
best param after transform :
{'bagging_fraction': 0.55, 'learning_rate': 0.05100415069086256, 'max_depth': 22, 'num_leaves': 85, 'num_trees': 400}
rmse of the best lightgbm: 0.219180276662925


原文链接:https://www.jianshu.com/p/017b7b1c505d
 

  • 10
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在Python中进行LightGBM调参可以通过设置一系列参数来实现。首先,可以调整学习率和估计器的数目。学习率(learning_rate)控制每个估计器对于前一个估计器的权重。较小的学习率可以使模型更加稳定,但可能需要更多的估计器来达到最佳性能。估计器的数目(num_estimators)表示要使用的决策树的数量,较大的数目可能会增加模型的复杂度。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [LightGBM调参](https://blog.csdn.net/weixin_41917143/article/details/110421742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [提升机器算法LightGBM(图解+理论+增量训练python代码+lightGBM调参方法)](https://blog.csdn.net/lamusique/article/details/95631638)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [LightGBM 如何调参](https://blog.csdn.net/weixin_44116269/article/details/103269604)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值