转载知乎专栏ML与DL成长之路,作者QLMX
链接https://zhuanlan.zhihu.com/p/76615507
-
1.简介
该部分是代码整理的第二部分,为了方便一些初学者调试代码,作者已将该部分代码打包成一个工程文件,包含简单的数据处理、xgboost配置、五折交叉训练和模型特征重要性打印四个部分。数据处理部分参考:代码整理一,这里只介绍不同的部分。本文主要是介绍一些重点的参数部分,一是方便自己以后再次查询,也希望帮助一些初学者快速的使用该项目,应用到自己的工程或者比赛中。如果只是想要阅读代码,可直接移步到尾部链接。
2. 数据处理
data = pd.concat([train_data, test_data]) cate_feature = ['gender', 'cell_province', 'id_province', 'id_city', 'rate', 'term'] for item in cate_feature: data[item] = LabelEncoder().fit_transform(data[item]) item_dummies = pd.get_dummies(data[item]) item_dummies.columns = [item + str(i + 1) for i in range(item_dummies.shape[1])] data = pd.concat([data, item_dummies], axis=1) data.drop(cate_feature,axis=1,inplace=True)
该部分在lightgbm中只进行了labelEncoder编码处理,然后通过categorical_feature变量处理,在lightgbm中使用了类别特征的最优切分进行了处理,具体详情参考:柯国霖大佬的回答。xgboost中没有对类别特征做处理,这里对其进行了onehot编码处理。而在工程中,如果类别过多,我一般会放弃进行onehot,主要是由于进行onehot会导致特征过于稀疏,运算速度变慢,严重影响模型的迭代速度,并且最终对结果提升很有限,我通常只会进行labelEncoder, 也可以对特征进行embeding处理。
3.模型
3.1 参数
和lightgbm一样,xgboost也是使用key-value字典的方式存储参数,下面给出的事二分类的参数
params = { 'booster': 'gbtree', 'objective': 'binary:logistic', 'eval_metric': 'auc', 'gamma': 0.1, 'max_depth': 8, 'alpha': 0, 'lambda': 0, 'subsample': 0.7, 'colsample_bytree': 0.5, 'min_child_weight': 3, 'silent': 0, 'eta': 0.03, 'nthread': -1, 'seed': 2019, }
- objective:目标函数
- 二分类:常用的是
binary:logistic
- 多分类:
multi:softmax
,当是多分类任务时需要指定类别数量,eg:'num_class':33
; - 回归任务:
reg:linear
- 二分类:常用的是
- eval_metric:评价函数,如果该参数没有指定,缺省值是通过目标函数来做匹配,
- 二分类:常用
auc
和logloss
- 多分类:
mlogloss
- 回归任务:均方误差:
mse
,均方根误差:rmse
, 平均绝对值误差:mae
- 二分类:常用
- gamma:用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子
- max_depth:树的深度,对结果影响较大,越深越容易过拟合
- alpha:L1正则,树的深度过大时,可以适大该参数
- lambda:L2正则
- subsample:随机采样的比率,通俗理解就是选多少样本做为训练集,选择小于1的比例可以减少方差,即防止过拟合
- colsample_bytree:这里是选择多少列作为训练集,具体的理解就是选择多少特征
- min_child_weight:决定最小叶子节点样本权重和。当它的值较大时,可以避免模型学习到局部的特殊样本。但如果这个值过高,会导致欠拟合
- eta:学习率
- silent: 是否打印训练过程中的信息,0表示打印,1反之
- nthread:运行的线程数,-1所有线程,该值需要根据具体情况调整,线程对最终结果有一点影响,曾今测试,线程越多,结果会变差一丢丢
- seed:这个随机指定一个常数,防止每次结果不一致
3.2 五折交叉
folds = KFold(n_splits=5, shuffle=True, random_state=2019)
采用五折交叉统计实际就是训练多个模型和平均值融合,如果时间允许的情况下10折交叉会好于5折。5折交叉还可以采用StratifiedKFold做切分。
3.3 数据加载
XGBoost可以加载多种数据格式的训练数据:libsvm 格式的文本数据、Numpy 的二维数组、XGBoost 的二进制的缓存文件。加载的数据存储在对象 DMatrix 中,而llightgbm是存储在Dataset中
trn_data = xgb.DMatrix(train_x.iloc[trn_idx], label=train_y[trn_idx]) val_data = xgb.DMatrix(train_x.iloc[val_idx], label=train_y[val_idx])
3.4 训练和预测
##训练部分 watchlist = [(trn_data, 'train'), (val_data, 'valid')] clf = xgb.train(params, trn_data, num_round, watchlist, verbose_eval=200, early_stopping_rounds=200) ##预测部分 test_pred_prob += clf.predict(xgb.DMatrix(test), ntree_limit=clf.best_ntree_limit) / folds.n_splits
- params:参数字典
- trn_data :训练的数据
- num_round:迭代次数
- watchlist:这是一个列表,用于对训练过程中进行评估列表中的元素。形式是evals =[(dtrain,’train’),(dval,’val’)]或者是evals =[(dtrain,’train’)],对于第一种情况,它使得我们可以在训练过程中观察验证集的效果。
- verbose_eval: 如果为True ,则对evals中元素的评估结果会输出在结果中;如果输入数字,假设为5,则每隔5个迭代输出一次。
- ntree_limit:验证集中最好的结果做预测
4.模型重要性
模型重要性是根据树模型中该特征的分裂次数做统计的,可以基于此重要性来判断特种的重要程度,深入的挖掘特征,具体代码如下:
##保存特征重要性 fold_importance_df = pd.DataFrame() fold_importance_df["Feature"] = clf.get_fscore().keys() fold_importance_df["importance"] = clf.get_fscore().values() fold_importance_df["fold"] = fold_ + 1 feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0) ##特征重要性显示 ## plot feature importance cols = (feature_importance_df[["Feature", "importance"]] .groupby("Feature").mean(). sort_values(by="importance", ascending=False).index) best_features = feature_importance_df.loc[feature_importance_df.Feature.isin(cols)] .sort_values(by='importance',ascending=False) plt.figure(figsize=(8, 15)) sns.barplot(y="Feature", x="importance", data=best_features.sort_values(by="importance", ascending=False)) plt.title('LightGBM Features (avg over folds)') plt.tight_layout() plt.savefig('../../result/xgb_importances.png')
在lightgbm中对应的事
clf.feature_importance()
函数,而在xgboost中对应的是clf.get_fscore()
函数。如果特征过多无法完成显示,可以只取topN显示,如只显示top5cols = (feature_importance_df[["Feature", "importance"]].groupby("Feature").mean() .sort_values(by="importance", ascending=False)[:5].index)
5.小总结
xgboost和lightgbm对比,它的速度会慢很多,使用也没有lighgbm方便,但是可以将xgboost训练的结果和lightgbm做融合,提升最终的结果。
代码地址:data_mining_models
- objective:目标函数