lightgbm做二分类,多分类以及回归任务(含python源码)

点击上方蓝字关注我们

1. 简介

内心一直想把自己前一段时间写的代码整理一下,梳理一下知识点,方便以后查看,同时也方便和大家交流。希望我的分享能帮助到一些小白用户快速前进,也希望大家看到不足之处慷慨的指出,相互学习,快速成长。我将从三个部分介绍数据挖掘类比赛中常用的一些方法,分别是lightgbm、xgboost和keras实现的mlp模型,分别介绍他们实现的二分类任务、多分类任务和回归任务,并给出完整的开源python代码。这篇文章主要介绍基于lightgbm实现的三类任务。源码地址:https://github.com/QLMX/data_mining_models

2.数据加载

该部分数据是基于拍拍贷比赛截取的一部分特征,随机选择了5000个训练数据,3000个测试数据。针对其中gender、cell_province等类别特征,直接进行重新编码处理。原始数据的lable是0-32,共有33个类别的数据。针对二分类任务,将原始label为32的数据直接转化为1,label为其他的数据转为0;回归问题就是将这些类别作为待预测的目标值。代码如下:其中gc是释放不必要的内存。

  
    
  
  
  
  1. ## category feature one_hot

  2. test_data['label'] = -1

  3. data = pd.concat([train_data, test_data])

  4. cate_feature = ['gender', 'cell_province', 'id_province', 'id_city', 'rate', 'term']

  5. for item in cate_feature:

  6. data[item] = LabelEncoder().fit_transform(data[item])


  7. train = data[data['label'] != -1]

  8. test = data[data['label'] == -1]


  9. ## Clean up the memory

  10. del data, train_data, test_data

  11. gc.collect()


  12. ## get train feature

  13. del_feature = ['auditing_date', 'due_date', 'label']

  14. features = [i for i in train.columns if i not in del_feature]


  15. ## Convert the label to two categories

  16. train['label'] = train['label'].apply(lambda x: 1 if x==32 else 0)

  17. train_x = train[features]

  18. train_y = train['label'].values

  19. test = test[features]

3.二分类任务

  
    
  
  
  
  1. params = {'num_leaves': 60, #结果对最终效果影响较大,越大值越好,太大会出现过拟合

  2. 'min_data_in_leaf': 30,

  3. 'objective': 'binary', #定义的目标函数

  4. 'max_depth': -1,

  5. 'learning_rate': 0.03,

  6. "min_sum_hessian_in_leaf": 6,

  7. "boosting": "gbdt",

  8. "feature_fraction": 0.9, #提取的特征比率

  9. "bagging_freq": 1,

  10. "bagging_fraction": 0.8,

  11. "bagging_seed": 11,

  12. "lambda_l1": 0.1, #l1正则

  13. # 'lambda_l2': 0.001, #l2正则

  14. "verbosity": -1,

  15. "nthread": -1, #线程数量,-1表示全部线程,线程越多,运行的速度越快

  16. 'metric': {'binary_logloss', 'auc'}, ##评价函数选择

  17. "random_state": 2019, #随机数种子,可以防止每次运行的结果不一致

  18. # 'device': 'gpu' ##如果安装的事gpu版本的lightgbm,可以加快运算

  19. }


  20. folds = KFold(n_splits=5, shuffle=True, random_state=2019)

  21. prob_oof = np.zeros((train_x.shape[0], ))

  22. test_pred_prob = np.zeros((test.shape[0], ))



  23. ## train and predict

  24. feature_importance_df = pd.DataFrame()

  25. for fold_, (trn_idx, val_idx) in enumerate(folds.split(train)):

  26. print("fold {}".format(fold_ + 1))

  27. trn_data = lgb.Dataset(train_x.iloc[trn_idx], label=train_y[trn_idx])

  28. val_data = lgb.Dataset(train_x.iloc[val_idx], label=train_y[val_idx])



  29. clf = lgb.train(params,

  30. trn_data,

  31. num_round,

  32. valid_sets=[trn_data, val_data],

  33. verbose_eval=20,

  34. early_stopping_rounds=60)

  35. prob_oof[val_idx] = clf.predict(train_x.iloc[val_idx], num_iteration=clf.best_iteration)


  36. fold_importance_df = pd.DataFrame()

  37. fold_importance_df["Feature"] = features

  38. fold_importance_df["importance"] = clf.feature_importance()

  39. fold_importance_df["fold"] = fold_ + 1

  40. feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)


  41. test_pred_prob += clf.predict(test[features], num_iteration=clf.best_iteration) / folds.n_splits


  42. threshold = 0.5

  43. for pred in test_pred_prob:

  44. result = 1 if pred > threshold else 0

上面的参数中目标函数采用的事 binary,评价函数采用的是 {'binary_logloss','auc'},可以根据需要对评价函数做调整,可以设定一个或者多个评价函数;'num_leaves'对最终的结果影响较大,如果值设置的过大会出现过拟合现象。

针对模型训练部分,采用的事5折交叉训练的方法,常用的5折统计有两种:StratifiedKFoldKFold,其中最大的不同是StratifiedKFold分层采样交叉切分,确保训练集,测试集中各类别样本的比例与原始数据集中相同,实际使用中可以根据具体的数据分别测试两者的表现。

最后 fold_importance_df表存放的事模型的特征重要性,可以方便分析特征重要性

4.多分类任务

  
    
  
  
  
  1. params = {'num_leaves': 60,

  2. 'min_data_in_leaf': 30,

  3. 'objective': 'multiclass',

  4. 'num_class': 33,

  5. 'max_depth': -1,

  6. 'learning_rate': 0.03,

  7. "min_sum_hessian_in_leaf": 6,

  8. "boosting": "gbdt",

  9. "feature_fraction": 0.9,

  10. "bagging_freq": 1,

  11. "bagging_fraction": 0.8,

  12. "bagging_seed": 11,

  13. "lambda_l1": 0.1,

  14. "verbosity": -1,

  15. "nthread": 15,

  16. 'metric': 'multi_logloss',

  17. "random_state": 2019,

  18. # 'device': 'gpu'

  19. }



  20. folds = KFold(n_splits=5, shuffle=True, random_state=2019)

  21. prob_oof = np.zeros((train_x.shape[0], 33))

  22. test_pred_prob = np.zeros((test.shape[0], 33))


  23. ## train and predict

  24. feature_importance_df = pd.DataFrame()

  25. for fold_, (trn_idx, val_idx) in enumerate(folds.split(train)):

  26. print("fold {}".format(fold_ + 1))

  27. trn_data = lgb.Dataset(train_x.iloc[trn_idx], label=train_y.iloc[trn_idx])

  28. val_data = lgb.Dataset(train_x.iloc[val_idx], label=train_y.iloc[val_idx])


  29. clf = lgb.train(params,

  30. trn_data,

  31. num_round,

  32. valid_sets=[trn_data, val_data],

  33. verbose_eval=20,

  34. early_stopping_rounds=60)

  35. prob_oof[val_idx] = clf.predict(train_x.iloc[val_idx], num_iteration=clf.best_iteration)



  36. fold_importance_df = pd.DataFrame()

  37. fold_importance_df["Feature"] = features

  38. fold_importance_df["importance"] = clf.feature_importance()

  39. fold_importance_df["fold"] = fold_ + 1

  40. feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)


  41. test_pred_prob += clf.predict(test[features], num_iteration=clf.best_iteration) / folds.n_splits

  42. result = np.argmax(test_pred_prob, axis=1)

该部分同上面最大的区别就是该表了损失函数和评价函数。分别更换为 'multiclass''multi_logloss',当进行多分类任务是必须还要指定类别数:'num_class'

5.回归任务

  
    
  
  
  
  1. params = {'num_leaves': 38,

  2. 'min_data_in_leaf': 50,

  3. 'objective': 'regression',

  4. 'max_depth': -1,

  5. 'learning_rate': 0.02,

  6. "min_sum_hessian_in_leaf": 6,

  7. "boosting": "gbdt",

  8. "feature_fraction": 0.9,

  9. "bagging_freq": 1,

  10. "bagging_fraction": 0.7,

  11. "bagging_seed": 11,

  12. "lambda_l1": 0.1,

  13. "verbosity": -1,

  14. "nthread": 4,

  15. 'metric': 'mae',

  16. "random_state": 2019,

  17. # 'device': 'gpu'

  18. }



  19. def mean_absolute_percentage_error(y_true, y_pred):

  20. return np.mean(np.abs((y_true - y_pred) / (y_true))) * 100


  21. def smape_func(preds, dtrain):

  22. label = dtrain.get_label().values

  23. epsilon = 0.1

  24. summ = np.maximum(0.5 + epsilon, np.abs(label) + np.abs(preds) + epsilon)

  25. smape = np.mean(np.abs(label - preds) / summ) * 2

  26. return 'smape', float(smape), False



  27. folds = KFold(n_splits=5, shuffle=True, random_state=2019)

  28. oof = np.zeros(train_x.shape[0])

  29. predictions = np.zeros(test.shape[0])


  30. train_y = np.log1p(train_y) # Data smoothing

  31. feature_importance_df = pd.DataFrame()

  32. for fold_, (trn_idx, val_idx) in enumerate(folds.split(train_x)):

  33. print("fold {}".format(fold_ + 1))

  34. trn_data = lgb.Dataset(train_x.iloc[trn_idx], label=train_y.iloc[trn_idx])

  35. val_data = lgb.Dataset(train_x.iloc[val_idx], label=train_y.iloc[val_idx])



  36. clf = lgb.train(params,

  37. trn_data,

  38. num_round,

  39. valid_sets=[trn_data, val_data],

  40. verbose_eval=200,

  41. early_stopping_rounds=200)

  42. oof[val_idx] = clf.predict(train_x.iloc[val_idx], num_iteration=clf.best_iteration)


  43. fold_importance_df = pd.DataFrame()

  44. fold_importance_df["Feature"] = features

  45. fold_importance_df["importance"] = clf.feature_importance()

  46. fold_importance_df["fold"] = fold_ + 1

  47. feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)


  48. predictions += clf.predict(test, num_iteration=clf.best_iteration) / folds.n_splits


  49. print('mse %.6f' % mean_squared_error(train_y, oof))

  50. print('mae %.6f' % mean_absolute_error(train_y, oof))


  51. result = np.expm1(predictions) #reduction

  52. result = predictions

在回归任务中对目标函数值添加了一个log平滑,如果待预测的结果值跨度很大,做log平滑很有很好的效果提升。

    AI成长社,分享技术,分享生活!

长按识别二维码关注

点击“阅读原文”

本文分享自微信公众号 - AI成长社(ai-growth)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章