DATAWHALE打卡Task5-零基础入门金融风控之贷款违约预测挑战赛

参考:相关学习资料
参考2:相关博文

主要内容:

模型融合一般用于A榜比赛的尾声和B榜比赛的全程
主要包括以下基础方法:

  • 平均:
    • 简单平均法
    • 加权平均法
  • 投票:
    • 简单投票法
    • 加权投票法
  • 综合:
    • 排序融合
    • log融合
  • stacking:
    • 构建多层模型,并利用预测结果再拟合预测。
  • blending:
    • 选取部分数据预测训练得到预测结果作为新特征,带入剩下的数据中预测。
  • boosting/bagging

以上的方法从模型的结果, 样本集的集成和模型自身融合三个方面去记忆。
模型的结果方面:

  • 对于回归问题,我们可以对模型的结果进行加权融合等方式使得结果更好, - 对于分类问题,我们可以使用Voting的方式去得到最终的结果。
    样本集的集成技术方面:
  • 依靠Boosting和Bagging方式, 把多个弱分类器进行集成, 但是两者是不同的。
    模型自身的融合方面:
  • 依靠Stacking和Blending的原理及具体实现方法,介绍了mlxtend库里面的模型融合工具。

1、回归任务中的加权

这种加权融合的技术是从模型结果的层面来说的, 就是让每个模型跑一遍结果,用加权平均的方式将结果融合起来。

2、分类任务中的投票

投票法(Voting)是集成学习里面针对分类问题的一种结果结合策略。投票法的输出有两种类型:一种是直接输出类标签,另外一种是输出类概率,使用前者进行投票叫做硬投票(Majority/Hard voting),使用后者进行分类叫做软投票(Soft voting)。
硬投票:少数服从多数。
软投票:在使用soft voting时,把概率当做权值,加权计算。

#硬投票
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=4, min_child_weight=2, subsample=0.7,objective='binary:logistic')
 
vclf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2), ('xgb', clf3)])
vclf = vclf .fit(x_train,y_train)
print(vclf .predict(x_test))
#软投票
#在VotingClassifier中加入参数 voting='soft', weights=[2, 1, 1],weights用于调节基模型的权重
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
clf1 = LogisticRegression(random_state=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=4, min_child_weight=2, subsample=0.7,objective='binary:logistic')
 
vclf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2), ('xgb', clf3)], voting='soft', weights=[2, 1, 1])
vclf = vclf .fit(x_train,y_train)
print(vclf .predict(x_test))

3、stacking和blending的差异

  • stacking

将若干基学习器获得的预测结果,将预测结果作为新的训练集来训练一个次级分类器。
主要特点:
1)次级分类器一般比较简单:尽量选择线性模型
2)训练基分类器的时候的样本训练数据采用5折交叉验证进行,防止过拟合

  • blending
    直接把训练集分成两部分,70%作为新的训练集, 30%作为测试集,然后用这70%的训练集分别训练第一层的模型,然后在30%的测试集上进行预测, 把预测的结果作为第二层模型的训练集特征。以上为训练阶段

预测阶段:把真正的测试集先用第一层的模型预测,把预测结过作为第二层测试集的特征进行第二层的预测。

只不过stacking那里是每个模型都会经历K折交叉验证,也就是有多少模型,就会有多少次K折交叉验证,而blending这里是所有模型合起来只经历了一次K折交叉验证

Blending的优势在于:
•Blending比较简单,而Stacking相对比较复杂;
•能够防止信息泄露:generalizers和stackers使用不同的数据;

而缺点在于:
•只用了整体数据的一部分;
•最终模型可能对留出集(holdout set)过拟合;
•Stacking多次交叉验证要更加稳健

4、stacking的使用

stacking工具StackingCVRegressor:

from mxltend.regressor import StackingCVRegressor

StackingCVRegressorAPI及参数如下:
StackingCVRegressor(regressors,meta_regressor,cv = 5,shuffle = True,use_features_in_secondary = False)
•regressors: 基回归器,列表的形式,第一层的模型,可以这么写[xgb, lgb], 当然xgb,lgb是事先定义好的。
•meta_regressor: 元回归器, 这个可以理解为第二层的那个模型,即将前面回归器结果合起来的那个回归器,推荐使用lr,因为第二层的模型不要太复杂
•cv: 交叉验证策略, 默认是5折交叉验证。
•use_features_in_secondary: 默认是false, 意思是第二层的回归器只接收第一层回归器的结果进行训练和预测, 和我们上面介绍的原理样,如果设置为true,意思是第二层的回归器不仅接收第一层回归器的结果,还接收原始的数据集一块进行训练。
•shuffle: 如果设置为true, 则在交叉验证之前的训练数据将在拟合阶段打乱顺序。

方法:
•依然是.fit(x,y)进行训练, 但这里的x和y要求是数组了, 所以如果是DataFrame, 需要np.array()一下。并且X的shape[n_samples, n_features], y的shape, [n_samples]
•预测依然是.redict(x_test), 只不过这里的x_test依然是数组, 形状和上面的一样。
示例:

# 使用lgb和xgb那两个模型
def bulid_modl_xgb(x_train, y_train):
    model = XGBRegressor(n_estimators=400, learning_rate=0.05, gamma=0, subsample=0.8, colsample_bytree=0.9, max_depth=7)
    model.fit(x_train, y_train)
    return model

def bulid_modl_lgb(x_train, y_train):
    model = LGBMRegressor(n_estimators=1100, leaves=200, learning_rate=0.05, objective='regression_l1')
    model.fit(x_train, y_train)
    return model


def build_model_stackReg(x_train, y_train, xgb, lgb, lr):
    model = StackingCVRegressor(regressors=(xgb, lgb), meta_regressor=lr)
    model.fit(np.array(x_train), np.array(y_train))
    return model
# Stacking
xgb = XGBRegressor(n_estimators=4000, learning_rate=0.05, gamma=0, subsample=0.8, colsample_bytree=0.9, max_depth=7)
lgb = LGBMRegressor(n_estimators=11000, leaves=200, learning_rate=0.05, objective='regression_l1')
lr = LinearRegression()
model_stack = build_model_stackReg(X, Y, xgb, lgb, lr)
val_stack = model_stack.predict(np.array(XTest))
MAE_stack = mean_absolute_error(Ytrue, np.expm1(val_stack))
print(MAE_stack)    

StackingClassifierAPI及参数如下:
StackingClassifier(classifiers, meta_classifier, use_probas=False, average_probas=False, verbose=0, use_features_in_secondary=False), 这里的参数和上面的StackingCVRegressor基本上差不多
•classifiers: 基分类器, 数组形式[clf1, clf2, clf3], 每个基分类器的属性被存储在类属性 self.clfs_.
•meta_classifier: 目标分类器,即将前面分类器合起来的分类器
•use_probas : bool (default: False) ,如果设置为True, 那么目标分类器的输入就是前面分类输出的类别概率值而不是类别标签
•average_probas : bool (default: False),用来设置上一个参数当使用概率值输出的时候是否使用平均值。
•verbose : int, optional (default=0)。用来控制使用过程中的日志输出,当 verbose = 0时,什么也不输出, verbose = 1,输出回归器的序号和名字。verbose = 2,输出详细的参数信息。verbose > 2, 自动将verbose设置为小于2的,
•use_features_in_secondary : bool (default: False). 如果设置为True,那么最终的目标分类器就被基分类器产生的数据和最初的数据集同时训练。如果设置为False,最终的分类器只会使用基分类器产生的数据训练。

方法: .fit(), .predict()常用

使用示例:

from mlxtend.classifier import StackingCVClassifier
# 上面的这个操作,如果换成StackingClassifier, 是这样的形式:
clf1 = RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini')
clf2 = ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini')
clf3 = ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy')
clf4 = GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)
clf5 = LogisticRegression(solver='lbfgs')

sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3, clf4], meta_classifier=clf5, cv=3)
sclf.fit(X, y)
# 5这交叉验证
#scores = cross_val_score(sclf, X, y, cv=3, scoring='accuracy')

y_submission = sclf.predict(X_predict)

print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))

5、bleding 的实现[参考2]

# 模型融合中用到的单个模型
clfs = [LogisticRegression(solver='lbfgs'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]

# 切分一部分数据作为训练集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=2020)

dataset_blend_train = np.zeros((int(X.shape[0]/n_splits), len(clfs)))   # 每个模型的预测作为第二层的特征
dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))

# 5折stacking
n_splits = 5
skf = StratifiedKFold(n_splits)
skf = skf.split(X, y)

fold = {}
for i, (train, test) in enumerate(skf):
    fold[i] = (X[train], y[train], X[test], y[test])
Y_blend = []
for j, clf in enumerate(clfs):
    # 依次训练各个单模型
    dataset_blend_test_j = np.zeros((X_predict.shape[0], 5))
    
    # 5——fold交叉训练,使用第i个部分作为预测, 剩余的部分来训练模型, 获得其预测的输出作为第i部分的新特征。
    X_train, y_train, X_test, y_test = fold[j]
    clf.fit(X_train, y_train)
    dataset_blend_train[:, j] =  clf.predict(X_test)
    Y_blend.extend(y_test)
    
    # 对于测试集,直接用这k个模型的预测值作为新的特征
    dataset_blend_test[:, j] = clf.predict(X_predict)
        
    print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))

dataset_blend_train = dataset_blend_train.T.reshape(70, -1)
dataset_blend_test = np.mean(dataset_blend_test, axis=1).reshape(-1, 1)
Y_blend = np.array(Y_blend).reshape(-1, 1)

clf = LogisticRegression(solver='lbfgs')
clf.fit(dataset_blend_train, Y_blend)
y_submission = clf.predict(dataset_blend_test)

print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))

## 结果:
Val auc Score of Stacking: 1.000000

6、鸢尾花任务中的blending

# 以python自带的鸢尾花数据集为例
data_0 = iris.data
data = data_0[:100,:]


target_0 = iris.target
target = target_0[:100]
 
#模型融合中基学习器
clfs = [LogisticRegression(),
        RandomForestClassifier(),
        ExtraTreesClassifier(),
        GradientBoostingClassifier()]
 
#切分一部分数据作为测试集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=914)


#切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=914)
dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
dataset_d2 = np.zeros((X_predict.shape[0], len(clfs)))
 
for j, clf in enumerate(clfs):
    #依次训练各个单模型
    clf.fit(X_d1, y_d1)
    y_submission = clf.predict_proba(X_d2)[:, 1]
    dataset_d1[:, j] = y_submission
    #对于测试集,直接用这k个模型的预测值作为新的特征。
    dataset_d2[:, j] = clf.predict_proba(X_predict)[:, 1]
    print("val auc Score: %f" % roc_auc_score(y_predict, dataset_d2[:, j]))


#融合使用的模型
clf = GradientBoostingClassifier()
clf.fit(dataset_d1, y_d2)
y_submission = clf.predict_proba(dataset_d2)[:, 1]
print("Val auc Score of Blending: %f" % (roc_auc_score(y_predict, y_submission)))

7、模型的部署与保存

pickle序列化和反序列化

import pickle

"""第一种, pickle的序列化和反序列化"""
#模型的保存
pickle.dump(model, open('./model/xgb1.pkl', 'wb'))
#模型的载入
model1 = pickle.load(open('./model/xgb1.pkl', 'rb'))
#模型的预测
model1.predict(dtest)

joblib序列化与反序列化

"""第二种模型的存储与导入方式 - sklearn的joblib"""
from sklearn.externals import joblib
#模型的保存
joblib.dump(model, './model/xgb.pkl')
#模型的载入
model2 = joblib.load('./model/xgb.pkl')
#模型的预测
model2.predict(dtest)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值