基本路线:
1.搭建环境/数据读入
2.数据分析
3.特征工程
4.建模调参
5.模型融合
异常处理:
- 通过箱线图(或 3-Sigma)分析删除异常值;
- BOX-COX 转换(处理有偏分布);
- 长尾截断;
特征筛选常用方法:
- 过滤式(filter):先对数据进行特征选择,然后在训练学习器,常见的方法有 Relief/方差选择发/相关系数法/卡方检验法/互信息法;
- 包裹式(wrapper):直接把最终将要使用的学习器的性能作为特征子集的评价准则,常见方法有 LVM(Las Vegas Wrapper) ;
- 嵌入式(embedding):结合过滤式和包裹式,学习器训练过程中自动进行了特征选择,常见的有 lasso 回归;
调参三种方法:
贪心
局部最优解
网格
def grid_search(command_dict, tmux_name='search'):server = libtmux.Server()sess = server.new_session(tmux_name)for i, (name, command_) in enumerate(command_dict.items()):if i == 0:window = sess.windows[-1]else:window = sess.new_window()window.rename_window(name)pane = window.panes[0]pane.send_keys(command_)def search_lr():"""搜索最优学习率"""devices = [1, 3, 4]command_dict = {} for i, lr in enumerate([1e-6, 1e-5, 1e-4]):name = f'lr_{lr}'command_dict[name] = f'CUDA_VISIBLE_DEVICES={devices[i]} python train.py train train.lr {lr} output_dir ../outputs/grid_attr_lr_{lr}'grid_search(command_dict, 'search_lr')search_lr()
贝叶斯
定义优化函数
def rf_cv_lgb(num_leaves, max_depth, bagging_fraction, feature_fraction, bagging_freq, min_data_in_leaf, min_child_weight, min_split_gain, reg_lambda, reg_alpha):# 建立模型model_lgb = lgb.LGBMClassifier(boosting_type='gbdt', bjective='binary', metric='auc',learning_rate=0.1, n_estimators=5000,num_leaves=int(num_leaves), max_depth=int(max_depth), bagging_fraction=round(bagging_fraction, 2), feature_fraction=round(feature_fraction, 2),bagging_freq=int(bagging_freq), min_data_in_leaf=int(min_data_in_leaf),min_child_weight=min_child_weight, min_split_gain=min_split_gain,reg_lambda=reg_lambda, reg_alpha=reg_alpha,n_jobs= 8)val = cross_val_score(model_lgb, X_train_split, y_train_split, cv=5, scoring='roc_auc').mean()return val
定义优化参数并开始优化
from bayes_opt import BayesianOptimization
"""定义优化参数"""
bayes_lgb = BayesianOptimization(rf_cv_lgb, {'num_leaves':(10, 200),'max_depth':(3, 20),'bagging_fraction':(0.5, 1.0),'feature_fraction':(0.5, 1.0),'bagging_freq':(0, 100),'min_data_in_leaf':(10,100),'min_child_weight':(0, 10),'min_split_gain':(0.0, 1.0),'reg_alpha':(0.0, 10),'reg_lambda':(0.0, 10),}
)"""开始优化"""
bayes_lgb.maximize(n_iter=10)
根据优化后的参数建立新的模型,降低学习率并寻找最优模型迭代次数
"""调整一个较小的学习率,并通过cv函数确定当前最优的迭代次数"""
base_params_lgb = {'boosting_type': 'gbdt','objective': 'binary','metric': 'auc','learning_rate': 0.01,'num_leaves': 14,'max_depth': 19,'min_data_in_leaf': 37,'min_child_weight':1.6,'bagging_fraction': 0.98,'feature_fraction': 0.69,'bagging_freq': 96,'reg_lambda': 9,'reg_alpha': 7,'min_split_gain': 0.4,'nthread': 8,'seed': 2020,'silent': True,'verbose': -1,
}cv_result_lgb = lgb.cv(train_set=train_matrix,early_stopping_rounds=1000, num_boost_round=20000,nfold=5,stratified=True,shuffle=True,params=base_params_lgb,metrics='auc',seed=0
)print('迭代次数{}'.format(len(cv_result_lgb['auc-mean'])))
print('最终模型的AUC为{}'.format(max(cv_result_lgb['auc-mean'])))
迭代次数已经确定,建立最终模型并对验证集进行验证
import lightgbm as lgb
"""使用lightgbm 5折交叉验证进行建模预测"""
cv_scores = []
for i, (train_index, valid_index) in enumerate(kf.split(X_train, y_train)):print('************************************ {} ************************************'.format(str(i+1)))X_train_split, y_train_split, X_val, y_val = X_train.iloc[train_index], y_train[train_index], X_train.iloc[valid_index], y_train[valid_index]train_matrix = lgb.Dataset(X_train_split, label=y_train_split)valid_matrix = lgb.Dataset(X_val, label=y_val)params = {'boosting_type': 'gbdt','objective': 'binary','metric': 'auc','learning_rate': 0.01,'num_leaves': 14,'max_depth': 19,'min_data_in_leaf': 37,'min_child_weight':1.6,'bagging_fraction': 0.98,'feature_fraction': 0.69,'bagging_freq': 96,'reg_lambda': 9,'reg_alpha': 7,'min_split_gain': 0.4,'nthread': 8,'seed': 2020,'silent': True,}model = lgb.train(params, train_set=train_matrix, num_boost_round=14269, valid_sets=valid_matrix, verbose_eval=1000, early_stopping_rounds=200)val_pred = model.predict(X_val, num_iteration=model.best_iteration)cv_scores.append(roc_auc_score(y_val, val_pred))print(cv_scores)print("lgb_scotrainre_list:{}".format(cv_scores))
print("lgb_score_mean:{}".format(np.mean(cv_scores)))
print("lgb_score_std:{}".format(np.std(cv_scores)))
确定最后模型 并使用验证集进行模型预测
"""预测并计算roc的相关指标"""
val_pre_lgb = final_model_lgb.predict(X_val)
fpr, tpr, threshold = metrics.roc_curve(y_val, val_pre_lgb)
roc_auc = metrics.auc(fpr, tpr)
print('调参后lightgbm单模型在验证集上的AUC:{}'.format(roc_auc))
"""画出roc曲线图"""
plt.figure(figsize=(8, 8))
plt.title('Validation ROC')
plt.plot(fpr, tpr, 'b', label = 'Val AUC = %0.4f' % roc_auc)
plt.ylim(0,1)
plt.xlim(0,1)
plt.legend(loc='best')
plt.title('ROC')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
# 画出对角线
plt.plot([0,1],[0,1],'r--')
plt.show()
保存模型到本地
# 保存模型
import pickle
pickle.dump(final_model_lgb, open('dataset/model_lgb_best.pkl', 'wb'))
模型融合
简单加权融合:
- 回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
- 分类:投票(Voting)
- 综合:排序融合(Rank averaging),log融合
stacking/blending:
- 构建多层模型,并利用预测结果再拟合预测。
- stacking个人理解:第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为特征加入训练集进行再训练,从而得到完整的模型。
- Blending:个人理解:与stacking不同的是,第一层取一部分,第二层取另一部分
boosting/bagging:
boosting
-
从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的)
-
每次使用一个训练集得到一个模型,k个训练集共得到k个模型。(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等)
-
对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同)
bagging
-
AdaBoosting方式每次使用的是全部的样本,每轮训练改变样本的权重。下一轮训练的目标是找到一个函数f 来拟合上一轮的残差。当残差足够小或者达到设置的最大迭代次数则停止。Boosting会减小在上一轮训练正确的样本的权重,增大错误样本的权重。(对的残差小,错的残差大)
梯度提升的Boosting方式是使用代价函数对上一轮训练出的模型函数f的偏导来拟合残差。