一周算法实践进阶day3:模型融合

数据说明

本次数据与之前数据不同: 下载
这份数据集是金融数据(非原始数据,已经处理过了),我们要做的是预测贷款用户是否会逾期。表格中 “status” 是结果标签:0表示未逾期,1表示逾期。

1任务

  • 模型融合:用你目前评分最高的模型作为基准模型,和其他模型进行stacking融合,得到最终模型及评分结果。

2概念介绍

学习器的结合策略有:平均法、投票法和学习法。
回归问题平均法就是对若干个学习器的输出进行平均得到最终的预测输出。复杂点还可以对每个学习器设置权重。
分类问题,投票法就是多数表决法(少数服从多数)。

Stacking学习法的代表方法,Stacking 是一种集成学习技术,Stacking简单理解就是讲几个简单的模型,一般采用将它们进行K折交叉验证输出预测结果,然后将每个模型输出的预测结果合并为新的特征,并使用新的模型加以训练。

以两层的情况为例,我们将弱学习器称为初级学习器,将用于结合的学习器称为次级学习器。对于测试集,我们首先用初级学习器预测一次,得到次级学习器的输入样本,再用次级学习器预测一次,得到最终的预测结果。

stacking有一张经典的图:
在这里插入图片描述
结合本练习然后对此图进行详细阐述。具体思路如下:
使用4种SVM、决策树、XGBoost和LightGBM作为初级分类器进行5折交叉验证,分别实施以下步骤,LR作为次级分类器。
1)把train分train1~train5,共5份,用其中4份预测剩下的那份,同时预测test数据,这样的过程做5次,生成5份train(原train样本数/5)数据和5份test数据。
2)把5份预测的train数据纵向叠起来(即为原来的整个train,只是顺序不同),把test预测的结果做平均。
将四个模型得到的train并列合并成一个4列的矩阵作为training-data,得到的test并列合并成一个4列的矩阵作为testing-data。让下一层的模型,基于他们进一步训练。

3完整代码及注释

#导入包
import pandas as pd
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.tree import DecisionTreeClassifier
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.metrics import accuracy_score,roc_auc_score

from mlxtend.classifier import StackingClassifier #Stacking库
from sklearn import model_selection#交叉验证

import warnings
warnings.filterwarnings("ignore")

#加载数据
data = pd.read_csv('data.csv',encoding='unicode_escape')#编码格式要注意
data.drop_duplicates(inplace=True)#是直接对原data进行操作,去除data中重复的行
print("数据行列数:",data.shape)
#划分数据集
X = data.drop(['status','Unnamed: 0'],axis=1)
X_num = X.select_dtypes(include='number').copy()#数值型
X_str = X.select_dtypes(exclude='number').copy()#非数值型
y = data['status']

#缺失值处理
#发现缺失值方法:缺失个数、缺失率
#查看每列是否有缺失值
#print(data.isnull().sum())
# 使用缺失率(可以了解比重)并按照值降序排序 ascending=False
X_num_miss = (X_num.isnull().sum() / len(X_num)).sort_values(ascending=False)
#print(X_num_miss.head())
#print('----------' * 5)
X_str_miss = (X_str.isnull().sum() / len(X_str)).sort_values(ascending=False)
#print(X_str_miss.head())
#缺失值较多的列student_feature进行删除
X_num = X_num.drop(['student_feature'],axis = 1)
#高缺失率特征处理:EM插补、多重插补。这里先将缺失值归为一类。可以用平均数、中位数、众数、固定值(比如0)填充
# 用0填充
X_num.fillna(0,inplace = True)#fillna()会填充nan数据,返回填充后的结果。如果希望在原数据集中修改,则把inplace设置为True
X_str.fillna(0,inplace = True)
# 用众数填充
# X_num.fillna(X_num.mode().iloc[0, :], inplace=True)
# X_str.fillna(X_str.mode().iloc[0, :], inplace=True)

#离散特征编码
"""
序号编码:用于有大小关系的数据
one-hot编码:用于无序关系的数据
"""
X_str_oh = pd.get_dummies(X_str['reg_preference_for_trad'])#对房名进行one-hot编码


#日期特征处理:因为后面fit() 要求输入的数据框都是数值格式的,而这个日期本身是字符串格式,如果要用的话,需要先对其进行转换
#对日期loans_latest_time,latest_query_time细分为年月周
X_date = pd.DataFrame()
X_date['latest_query_time_year'] = pd.to_datetime(X_str['latest_query_time']).dt.year#年
X_date['latest_query_time_month'] = pd.to_datetime(X_str['latest_query_time']).dt.month#月
X_date['latest_query_time_weekday'] = pd.to_datetime(X_str['latest_query_time']).dt.weekday#周
X_date['loans_latest_time_year'] = pd.to_datetime(X_str['loans_latest_time']).dt.year
X_date['loans_latest_time_month'] = pd.to_datetime(X_str['loans_latest_time']).dt.month
X_date['loans_latest_time_weekday'] = pd.to_datetime(X_str['loans_latest_time']).dt.weekday


#特征组合
X = pd.concat([X_num,X_str_oh,X_date],axis=1,sort=False)
#print(X.shape)

#数据集划分
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=2018)

#模型评估
def model_metrics(clf, X_train, X_test, y_train, y_test):
    y_train_pred = clf.predict(X_train)
    y_test_pred = clf.predict(X_test)

    if hasattr(clf,'decision_function'):
        y_train_proba = clf.decision_function(X_train)
        y_test_proda = clf.decision_function(X_test)
    else:
        y_train_proba = clf.predict_proba(X_train)[:,1]
        y_test_proda = clf.predict_proba(X_test)[:,1]

    #准确率
    print('<准确率>:')
    print('训练集:','%.4f'%accuracy_score(y_train,y_train_pred))
    print('测试集:','%.4f'%accuracy_score(y_test,y_test_pred))

    #auc值:用roc_auc_score或auc
    print('<auc值>:')
    print('训练集:','%.4f'%roc_auc_score(y_train,y_train_proba))
    print('测试集:','%.4f'%roc_auc_score(y_test,y_test_proda))

#模型构建
#特征归一化
sc = StandardScaler()
sc.fit(X_train)# 估算每个特征的平均值和标准差
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)


#1逻辑回归
lr = LogisticRegression(random_state=2018)

#SVM
svc = svm.SVC(C = 0.01,kernel='linear',probability=True)#SVC方法decision_function给每个样本中的每个类一个评分,当我们将probability设置为True之后,我们可以通过predict_proba和predict_log_proba可以对类别概率进行评估。

#决策树
clf = DecisionTreeClassifier(random_state=2018)

#XGBoost
xgbs = XGBClassifier(random_state=2018)

#LightGBM
lgbm = LGBMClassifier(random_state=2018)

#模型融合
#(1)最基本的使用方法,将初级分类器产生的类别标签作为新特征
sclf = StackingClassifier(classifiers=[svc,clf,xgbs,lgbm],meta_classifier=lr)
sclf.fit(X_train_std,y_train.values)
model_metrics(sclf,X_train_std,X_test_std,y_train,y_test)

print('5-fold cross validation:\n')#5折交叉验证

for clf,label in zip([svc,clf,xgbs,lgbm,sclf],['SVM','决策树','XGBoost','LightGBM','StackingClassifier']):
    scores = model_selection.cross_val_score(clf,X_train_std,y_train,cv = 5,scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"% (scores.mean(), scores.std(), label))


#(2)另一种使用,将初级分类器产生的输出类概率作为新特征
#StackingClassifier中的参数设置:对输出概率use_probas=True,average_probas的设置有两种:
#1.如果average_probas=True,则对分类器的结果求平均
#2.如果average_probas=False,则分类器的所有结果都保留作为新的特征(推荐这个)
sclf = StackingClassifier(classifiers=[svc,clf,xgbs,lgbm],meta_classifier=lr,use_probas=True,average_probas=False)
sclf.fit(X_train_std,y_train.values)
model_metrics(sclf,X_train_std,X_test_std,y_train,y_test)

print('5-fold cross validation:\n')#5折交叉验证

for clf,label in zip([svc,clf,xgbs,lgbm,sclf],['SVM','决策树','XGBoost','LightGBM','StackingClassifier']):
    scores = model_selection.cross_val_score(clf,X_train_std,y_train,cv = 5,scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"% (scores.mean(), scores.std(), label))

# print(type(X_train_std))
# print(type(y_train))

4代码运行结果

(1)直接将初级分类器产生的类别标签作为最后总的meta-classifier的输入数据的5折交叉验证的结果:

5-fold cross validation:

Accuracy: 0.79 (+/- 0.01) [SVM]
Accuracy: 0.69 (+/- 0.01) [决策树]
Accuracy: 0.79 (+/- 0.01) [XGBoost]
Accuracy: 0.79 (+/- 0.01) [LightGBM]
Accuracy: 0.73 (+/- 0.05) [StackingClassifier]

(2) 另一种使用,将初级分类器产生的输出类概率作为最后总的meta-classifier的输入数据的5折交叉验证的结果:

5-fold cross validation:

Accuracy: 0.79 (+/- 0.01) [SVM]
Accuracy: 0.73 (+/- 0.05) [决策树]
Accuracy: 0.79 (+/- 0.01) [XGBoost]
Accuracy: 0.79 (+/- 0.01) [LightGBM]
Accuracy: 0.79 (+/- 0.01) [StackingClassifier]

5结论

模型融合后的结果没有基础模型的效果好。

6遇到的问题

  1. sclf.fit(X,y)时会报错
    解决:注意X_train_std是array,而y_train是Series且索引不一定从0开始。此处我们取y_train_std.values,将y_train_std也转成array。
  2. 将SVM产生的输出类概率进行融合时,出现报错:
AttributeError: predict_proba is not available when  probability=False

解决:SVC方法decision_function给每个样本中的每个类一个评分,当我们将probability设置为True之后,我们可以通过predict_proba和predict_log_proba可以对类别概率进行评估。详情可见参考4

7参考

  1. 集成学习总结 & Stacking方法详解
  2. 模型融合—— stacking详细讲解
  3. StackingCVClassifier使用交叉验证扩展了标准的 StackingClassifier (实现为StackingClassifier)
  4. sklearn学习笔记(3)svm多分类
  5. 参考5
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值