文章目录
数据传送门(data.csv): https://pan.baidu.com/s/1G1b2QJjYkkk7LDfGorbj5Q
目标:数据集是金融数据(非脱敏),要预测贷款用户是否会逾期。表格中 “status” 是结果标签:0表示未逾期,1表示逾期。
任务:用你目前评分最高的模型作为基准模型,和其他模型进行stacking融合,得到最终模型及评分果。
一、集成学习
集成学习是将几种机器学习算法组合成一个预测模型的算法,以达到减小方差(bagging)、偏差(boosting)或改进预测(stacking)的效果。
1、Bagging
基本思想:给定大小为
n
n
n 的训练集
D
D
D,Bagging 从中均匀、有放回地选出
m
m
m 个大小为
n
′
n'
n′ 的子集
D
i
D_i
Di,作为新的训练集。在这么
m
m
m 个训练集上使用分类、回归等算法,可以得到
m
m
m 个模型,再通过平均值(常用于回归问题)、投票法(常用于分类问题)等方法综合产生预测结果,即可得到 Bagging 模型。
优点:高效、可并行实现、能不经修改的适用于多分类和回归任务、包外估计。
典型模型:随机森林(Random Forest)
2、Boosting
基本思想:个体学习器之间存在强依赖关系,必须串行序列化生成的集成学习方法。对训练样本分布调整,主要是通过增加误分类样本的权重,降低正确分类样本的权重。
工作机制如下:
- 先从初始训练集中学习一个基学习器;
- 根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续收到更多关注;
- 基于调整后的样本分布来训练下一个基学习器;
- 如此反复,直到基学习器数目达到 T,最终将这 T 个基学习器进行加权结合。
典型模型:Adaboost
3、Stacking
概述:将个体机器学习器的结果结合在一起,即对学习器的结果再加上一层学习器。将训练集学习器的学习结果作为输入,将训练集的输出作为输出,重新训练一个学习器来得到最终结果。(也就是常说的两层)
术语:
- 弱学习器称为初级学习器,将用于结合的学习器称为次级学习器;
- 对于测试集,我们首先用初级学习器预测一次,得到次级学习器的输入样本,再用次级学习器预测一次,得到最终的预测结果。
(1)核心图解
对于每一轮的 5-fold,Model 1都要做满5次的训练和预测。
a、构建新的训练集
- 先将训练集 D ( T r a i n i n g D a t a ) D(Training Data) D(TrainingData) 拆成 k k k 个大小相似但互不相交的子集 D 1 , D 2 , … , D k D_1,D_2,…,D_k D1,D2,…,Dk;
- 令 D j ′ = D − D j D_j'= D - D_j Dj′=D−Dj,在 D j ′ D_j' Dj′ 上训练一个弱学习器 L j L_j Lj 。将 D j D_j Dj 作为测试集,获得 L j L_j Lj 在 D j D_j Dj 上的输出 D j ′ ′ D_j'' Dj′′ ;
- 步骤2可以得到 k k k 个弱学习器以及 k k k 个相应的输出 D j ′ ′ D_j'' Dj′′ ,这个 k k k 个输出加上原本的类标构成新的训练集 D n D_n Dn ;
- 在 D n D_n Dn 训练次学习器 L L L , L L L 即为最后的学习器。
b、构建新的测试集
- 对于每个训练好的一个弱学习器 L j L_j Lj,在测试集(Test Data,图中所示绿色部分,不要与上面的“测试集”混淆。注意:此处是测试集的全部)进行预测,将 k k k 次的预测结果取平均作为新的预测集。
c、最终的训练与预测
- 训练集为构建新的训练集步骤得到的训练集,测试集为构建新的测试集得到的测试集
- 训练分类器并预测。
(2)示例
a、构建新的训练集
Train Data有890行。(请对应图中的上层部分)
每1次的fold,都会生成 713行 小train, 178行 小test。我们用Model 1来训练 713行的小train,然后预测 178行 小test。预测的结果是长度为 178 的预测值。
这样的动作走5次! 长度为178 的预测值 X 5 = 890 预测值,刚好和Train data长度吻合。这个890预测值是Model 1产生的,我们先存着,因为,一会让它将是第二层模型的训练来源。
重点:这一步产生的预测值我们可以转成 890 X 1 (890 行,1列),记作 P1 (大写P)
b、构建新的测试集
Test Data 有 418 行。(请对应图中的下层部分,对对对,绿绿的那些框框)
每1次的fold,713行 小train训练出来的Model 1要去预测我们全部的Test Data(全部!因为Test Data没有加入5-fold,所以每次都是全部!)。此时,Model 1的预测结果是长度为418的预测值。
这样的动作走5次!我们可以得到一个 5 X 418 的预测值矩阵。然后我们根据行来就平均值,最后得到一个 1 X 418 的平均预测值。
重点:这一步产生的预测值我们可以转成 418 X 1 (418行,1列),记作 p1 (小写p)
c、多模型的处理
走到这里,你的第一层的Model 1完成了它的使命。
第一层还会有其他Model的,比如Model 2,同样的走一遍, 我们有可以得到 890 X 1 (P2) 和 418 X 1 (p2) 列预测值。
这样吧,假设你第一层有3个模型,这样你就会得到:
来自5-fold的预测值矩阵 890 X 3,(P1,P2, P3) 和 来自Test Data预测值矩阵 418 X 3, (p1, p2, p3)。
d、最终的训练与预测
来自5-fold的预测值矩阵 890 X 3 作为你的Train Data,训练第二层的模型
来自Test Data预测值矩阵 418 X 3 就是你的Test Data,用训练好的模型来预测他们吧。
三、实现
目前单模型评分最高的模型是 XGBoost,其评分如下:
准确率: 训练集: 0.8458 测试集: 0.7898
1、手动实现
## 手动实现,stacking方法
def get_oof(clf, X_train, y_train, X_test):
oof_train = np.zeros((ntrain,)) # 1 * 3327
oof_test = np.zeros((ntest,)) # 1 * 1427
oof_test_skf = np.empty((5, ntest)) # 5 * 1427
# for clf in clfs:
for i,(train_index, test_index) in enumerate(kf.split(X_train)): # X_train:3327*33
print(train_index)
kf_X_train = X_train.iloc[train_index] # 2661*33
kf_y_train = y_train.iloc[train_index] # 2661*33
kf_X_test = X_train.iloc[test_index] # 666*7
clf.fit(kf_X_train, kf_y_train) # 学习分类器
oof_train[test_index] = clf.predict(kf_X_test) # 1*666
oof_test_skf[i, :] = clf.predict(X_test) # 测试集的预测作为测试数据
oof_test[:] = oof_test_skf.mean(axis=0) # 测试集的均值作为stcking的测试集
return oof_train.reshape(-1, 1), oof_test.reshape(-1, 1)
## 使用多模型实现
rf_model = RandomForestClassifier()
xgbt_model = xgb.XGBClassifier()
gdbt_model = GradientBoostingClassifier()
dt_model = DecisionTreeClassifier()
train_sets = []
test_sets = []
for clf in [rf_model, xgbt_model, gdbt_model]:
train_set, test_set = get_oof(clf, X_train, y_train, X_test)
train_sets.append(train_set)
test_sets.append(test_set)
meta_train = np.concatenate([result_set for result_set in train_sets], axis=1)
meta_test = np.concatenate([y_test_set for y_test_set in test_sets], axis=1)
# 使用决策树作为次级分类器
dt_model = DecisionTreeClassifier()
dt_model.fit(meta_train,y_train)
# df_predict = dt_model.predict(meta_test)
## 模型评估
model_metrics(dt_model, meta_train, meta_test, y_train, y_test)
==》
<准确率>:
训练集: 0.8031
测试集: 0.7884
<auc值>:
训练集: 0.6853
测试集: 0.6579
2、StackingClassifier类实现
## 使用多模型实现
from mlxtend.classifier import StackingClassifier
rf_model = RandomForestClassifier()
xgbt_model = xgb.XGBClassifier()
gdbt_model = GradientBoostingClassifier()
dt_model = DecisionTreeClassifier()
sclf = StackingClassifier(classifiers=[rf_model,xgbt_model,gdbt_model],meta_classifier=dt_model)
sclf.fit(X_train,y_train)
for clf,label in zip([rf_model,xgbt_model,gdbt_model,sclf],['随机森林','XGBoost','GBDT','StackingClassifier']):
scores = cross_val_score(clf,X_train,y_train,cv = 5,scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]"% (scores.mean(), scores.std(), label))
==》
Accuracy: 0.77 (+/- 0.01) [随机森林]
Accuracy: 0.80 (+/- 0.00) [XGBoost]
Accuracy: 0.79 (+/- 0.01) [GBDT]
Accuracy: 0.78 (+/- 0.01) [StackingClassifier]
小结
- 从结果来看,本文的Stacking结果和只是用XGBoost的结果基本持平(实际略低于XGBoost)。
- 换用一些弱分类器作为基本分类器效果会怎么样?