通俗理解:
集成算法就是以各种形式将多种感知器算法揉搓成一个打算法,在实际应用中有,揉搓方式一般有:
- Bagging:以随机森林为代表。
- Boosting:Adaboost和Xgboost为代表,
- stacking:使用不同分类器得到的结果同时作为第二次训练的输入
随机森林的简单介绍
例如:建立三课决策树,从100个样本里有放回的选择60到80个样本,分别放入三棵决策树中。在决策树选择特征的时候,也是从10里选择6到8特征。然后三棵树之间不存在相互影响,并行计算得到的分数按照上述公式取平均值即可得到最终结果。
特征重要性评估
例如:一批数据有ABCD四个特征,若想知道B特征对整个评估标准的重要程度,
- 首先使用这四个特征进行模型训练,得到错误率error1。
- 之后经过某种算法,破坏B特征中属性值的规律性,使B变成B',使用AB’CD进行训练得到error2。
- 若error1近似error2,证明B特征没什么用,如果error2>>error1,证明B特征重要。
- 在确认B特征确实无用后,在训练模型时可以去掉B特征。
⚠️:在实际使用中,并不是树越多越好。应该具体场景具体分析。
boosting简单介绍
假如:
- 有一个小偷,他此次真实偷取了1000块钱(真实的y值),
- 警察建立了一棵树,预测后他此次能偷取950块钱(预测目标其实想达到1000)
- 然后警察计算出了残差值R=1000-950=50,然后建立第二棵树,目标是结果要接近残差值50,结果得到了30。
- 再次计算与上一次的残差R=50-30=20,建立第三棵树,目标是结果要接近新的残差值20,结果得到15。
- 目前为止已经预测到的值为950+30+15=995,这个值看上去已经很漂亮了
Adaboost简单介绍
假如:
- 有一批数据,随机切分成5份为ABCDE,对应5个分类器
- 将每批数据分别赋予权重0.2,在进行一次预测后,ABDE都预测对了,而C预测错了。
- 根据预测结果,调整程序,加大对错误数据的权重,减轻预测正确的数据权重。如0.1_0.1_0.6_0.1_0.1。
- 经过新的权重训练后进行预测,可能会出现别的数据集预测错误的情况,那么继续调整相应权重,以此类推。
集成算法工具包推荐:ml-ens
ROC和AUC介绍
简单回顾一下混淆矩阵,横坐标是预测值,纵坐标是真实的ylabel。
真\预 | 0 | 1 |
---|---|---|
0 | TN | FP |
1 | FN | TP |
AUC即为图中阴影面积,如图可知,面积越大,即AUC值越大,证明预测效果越好。
⚠️:经过实践,我们发现使用集成算法,在处理数据的时候,只要你牛逼,可以根据自己需要调整到很高的精度和很高的泛化能力,但是计算量真的不小,所以集成算法不适合处理实时数据。。
代码展示
以下,使用美国党派捐赠情况表,来通过各个特征预测某一次捐赠可能属于哪个党派的行为。表结构和部分数据为:
- 老样子,导入数据集,切分数据,同时将部分数据离散化,one-hot编码
SEED = 222
np.random.seed(SEED)
df = pd.read_csv('input.csv')
# 切分数据集
def get_train_test(test_size=0.95):
y = 1 * (df.cand_pty_affiliation == "REP") # 标签值转变0。1值
X = df.drop(["cand_pty_affiliation"], axis=1) #制作X,所以去掉y的那一列
X = pd.get_dummies(X) #属性值离散化
X.drop(X.columns[X.std() == 0], axis=1, inplace=True) #去掉标准差为0的列(因为这样的数据对程序没卵用)
return train_test_split(X, y, test_size=test_size, random_state=SEED)
print("\nExample data:")
print(df.head())
xtrain, xtest, ytrain, ytest = get_train_test()
- 查看两个党派的具体分布
df.cand_pty_affiliation.value_counts(normalize=True).plot(
kind="bar", title="Share of No. donations")
plt.show()
- 构建一棵3层的决策树,并计算出AUC值
#打印出决策树的图片
def print_graph(clf, feature_names):
graph = export_graphviz(
clf,
label="root",
proportion=True,
impurity=False,
out_file=None,
feature_names=feature_names,
class_names={0: "D", 1: "R"},
filled=True,
rounded=True
)
graph = pydotplus.graph_from_dot_data(graph)
img = Image(graph.create_png())
graph.write_png("partycontri.png")
return img
#构建深度为3的决策树
t2 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
t2.fit(xtrain, ytrain)
p = t2.predict_proba(xtest)[:, 1]
#计算出AUC
print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.751
#绘制出决策树的图片,根据图中内容发现过拟合,
print_graph(t2, xtrain.columns)
我们可以发现,绝大部分数据通过预测,都落入了DEM里,这样的树极有可能出现过拟合现象。如果出现这种情况,我们可以通过去掉决策能力最强的Transaction_amt后重新建立第二个树模型,来看一看接下来会发生怎样的情况。
#去掉先前最重要特征,再看看新决策树是否会有好转
drop = ["transaction_amt"]
xtrain_slim = xtrain.drop(drop, axis=1)
xtest_slim = xtest.drop(drop, axis=1)
t3 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
t3.fit(xtrain_slim, ytrain)
p = t3.predict_proba(xtest_slim)[:, 1]
print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.740
print_graph(t3, xtrain_slim.columns)
- 不好意思打脸了。。。那么既然是介绍集成算法,不妨我们把两棵树集成起来,使用bagging思想,看一下有没有好转。
#使用bagging思想,手动求平均分
p1 = t2.predict_proba(xtest)[:, 1]
p2 = t3.predict_proba(xtest_slim)[:, 1]
p = np.mean([p1, p2], axis=0)#计算平均值
print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.783
我们发现AUC明显变高了。
- 既然是两棵树集成的模型,不如我们直接使用随机森林,因为sklearn里有现成的随机森林库,代码少,活还好。
'''
max_features:随机森林允许单个决策树使用特征的最大数量。 Python为最大特征数提供了多个可选项。 下面是其中的几个:
Auto/None :简单地选取所有特征,每颗树都可以利用他们。这种情况下,每颗树都没有任何的限制。
sqrt :此选项是每颗子树可以利用总特征数的平方根个。 例如,如果变量(特征)的总数是100,所以每颗子树只能取其中的10个。“log2”是另一种相似类型的选项。
0.2:此选项允许每个随机森林的子树可以利用变量(特征)数的20%。如果想考察的特征x%的作用, 我们可以使用“0.X”的格式
'''
rf = RandomForestClassifier(
n_estimators=10,#搞10棵树
max_features=3,
random_state=SEED
)
rf.fit(xtrain, ytrain)
p = rf.predict_proba(xtest)[:, 1]
print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.844
AUC的值明显比之前又搞出了好多。
- 接下来开始作死,尝试用不同分类器进行集成,得到一个庞大分类器,进行预测看看效果。一下包含两个方法,建立
#构建基础分类器(分类器大合集)
def get_models():
nb = GaussianNB()
svc = SVC(C=100, probability=True)
knn = KNeighborsClassifier(n_neighbors=3)
lr = LogisticRegression(C=100, random_state=SEED)
nn = MLPClassifier((80, 10), early_stopping=False, random_state=SEED)
gb = GradientBoostingClassifier(n_estimators=100, random_state=SEED)
rf = RandomForestClassifier(n_estimators=10, max_features=3, random_state=SEED)
models = {'svm': svc,
'knn': knn,
'naive bayes': nb,
'mlp-nn': nn,
'random forest': rf,
'gbm': gb,
'logistic': lr,
}
return models
#训练模型
def train_predict(model_list):
P = np.zeros((ytest.shape[0], len(model_list))) # 初始化好结果集框架
P = pd.DataFrame(P)
print("Fitting models.")
cols = list()
for i, (name, m) in enumerate(model_list.items()):
print("%s..." % name, end=" ", flush=False)
m.fit(xtrain, ytrain)
P.iloc[:, i] = m.predict_proba(xtest)[:, 1]
cols.append(name)
print("done")
P.columns = cols #设置表头
print("Done.\n")
return P
#评估
def score_models(P, y):
print("Scoring models.")
for m in P.columns:
score = roc_auc_score(y, P.loc[:, m]) #P.loc[:, m]含义:取列名为m的列的所有行(即取出名为m的列)
print("%-26s: %.3f" % (m, score))
print("Done.\n")
#开始作死
models = get_models()
P = train_predict(models)
score_models(P, ytest)
通过预测,我们得到了一下结果:
Scoring models.
svm : 0.845
knn : 0.779
naive bayes : 0.803
mlp-nn : 0.873
random forest : 0.844
gbm : 0.878
logistic : 0.853
直接取个平均值。这里仍然使用的是bagging思想
print("Ensemble ROC-AUC score: %.3f" % roc_auc_score(ytest, P.mean(axis=1)))#bagging一下,0.884
AUC提升至0.884。
- 另外,我们可以通过mlens库,通过各算法产生的结果,反推出各个算法之间的相关性:
#使用mlens将集成算法的关系和计算结果可视化
corrmat(P.corr(), inflate=False)
plt.show()
- 同学们可以看到,之前一直使用AUC进行模型评估,那么以上各个算法的ROC曲线到底长啥样?集成算法的ROC又长啥样?
#绘制roc曲线,y值,预测值,集成值,标签名列表,集成标签名
def plot_roc_curve(ytest, P_base_learners, P_ensemble, labels, ens_label):
plt.figure(figsize=(10, 8))
plt.plot([0, 1], [0, 1], 'k--') #'‐‐' 破折线
cm = [plt.cm.rainbow(i)
for i in np.linspace(0, 1.0, P_base_learners.shape[1] + 1)] #7个单独算法+1个集成算法
for i in range(P_base_learners.shape[1]):
p = P_base_learners[:, i]
fpr, tpr, _ = roc_curve(ytest, p)
plt.plot(fpr, tpr, label=labels[i], c=cm[i + 1])
fpr, tpr, _ = roc_curve(ytest, P_ensemble)
plt.plot(fpr, tpr, label=ens_label, c=cm[0])
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve')
plt.legend(frameon=False)
plt.show()
plot_roc_curve(ytest, P.values, P.mean(axis=1), list(P.columns), "ensemble")
- 我们也可以展示出不同算法计算出的REP(真值)占比
#各个算法预测的共和党占比
p = P.apply(lambda x: 1*(x >= 0.5).value_counts(normalize=True))
p.index = ["DEM", "REP"]
p.loc["REP", :].sort_values().plot(kind="bar")
plt.axhline(0.25, color="k", linewidth=0.5)
plt.text(0., 0.23, "True share republicans")
plt.show()
通过图像,我们可以看到,svm和mpl-nn预测出的占比和实际数据差太多了,索性干掉他们俩。操作的话,这里不做解释了,删掉相关代码即可。
- 那么每次都要通过观察来删掉不好的算法,太人工了,一点也不智能。那么我们可以使用stacking的方式进行操作,在大集合算法拿到的预测值,再找一个装B的算法进行二阶段的训练,来调整每个算法的权重配比。
meta_learner = GradientBoostingClassifier(#第二阶段分类器
n_estimators=1000,
loss="exponential",
max_features=4,
max_depth=3,
subsample=0.5,
learning_rate=0.005,
random_state=SEED
)
- 当第一阶段的结果在第二阶段继续训练,已经产生了权重上的倾斜,即嚼过的饭再嚼一次,很容易出现过拟合,可采用交叉验证的思想。将训练集一分为二。
1.用交叉训练集训练模型,
2.交叉验证集产生第二阶段的输入即可解决(毕竟交叉验证集没有进行反向传播调整权重)
#切分交叉训练集和验证集
xtrain_base, xpred_base, ytrain_base, ypred_base = train_test_split(
xtrain, ytrain, test_size=0.5, random_state=SEED)
#训练模型方法
def train_base_learners(base_learners, inp, out, verbose=True):
if verbose: print("Fitting models.")
for i, (name, m) in enumerate(base_learners.items()):
if verbose: print("%s..." % name, end=" ", flush=False)
m.fit(inp, out)
if verbose: print("done")
# 第一阶段预测出作为第二阶段输入的值
def predict_base_learners(pred_base_learners, inp, verbose=True):
P = np.zeros((inp.shape[0], len(pred_base_learners)))
if verbose: print("Generating base learner predictions.")
for i, (name, m) in enumerate(pred_base_learners.items()):
if verbose: print("%s..." % name, end=" ", flush=False)
p = m.predict_proba(inp)
P[:, i] = p[:, 1]
if verbose: print("done")
return P
#对stacking模型进行训练
def ensemble_predict(base_learners, meta_learner, inp, verbose=True):
P_pred = predict_base_learners(base_learners, inp, verbose=verbose)
return P_pred, meta_learner.predict_proba(P_pred)[:, 1]
#开始训练
train_base_learners(base_learners, xtrain_base, ytrain_base)
#交叉预测,可拿到第二阶段的输入
P_base = predict_base_learners(base_learners, xpred_base)
#在第二阶段进行各个算法的权重训练,即完成对mata_learner的训练
meta_learner.fit(P_base, ypred_base)
#用测试集进行最终测试
P_pred, p = ensemble_predict(base_learners, meta_learner, xtest)
print("\nEnsemble ROC-AUC score: %.3f" % roc_auc_score(ytest, p)) #0.880
但我们发现效果并没有好多少,那是因为我们在训练阶段拿到的数据少了一半,效果肯定不好啊!那么我们可以采用真正的交叉验证来解决这种粗暴的拆分方式,具体代码这里不写了,请参考另一篇文章离散型随机变量的二分类预测案例
,里面有关于交叉验证具体的操作代码。
- 然而之前推荐的mlens库中自带了集成算法的框架,就和随机森林一样,不用我们这样造轮子了,里面已经写好了并行训练多分类器,交叉验证等操作,上代码:
from mlens.ensemble import SuperLearner
# 集成算法分类器
sl = SuperLearner(
folds=10,
random_state=SEED,
verbose=2,
backend="multiprocessing"
)
# 指定各阶段的算法
sl.add(list(base_learners.values()), proba=True)
sl.add_meta(meta_learner, proba=True)
# 训练
sl.fit(xtrain, ytrain)
# 评分
p_sl = sl.predict_proba(xtest)
print("\nSuper Learner ROC-AUC score: %.3f" % roc_auc_score(ytest, p_sl[:, 1]))#0.889
效果不错。
以上内容介绍了集成算法的一些思想,通过代码从决策树,随机森林,stacking等角度实践了预测方法,对于数据的预处理没有进行过多操作。
完整代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
import pydotplus
from IPython.display import Image
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier
from mlens.visualization import corrmat
from sklearn.metrics import roc_curve
# 指定随机种子
SEED = 222
np.random.seed(SEED)
df = pd.read_csv('input.csv')
# 切分数据集
def get_train_test(test_size=0.95):
y = 1 * (df.cand_pty_affiliation == "REP") # 标签值转变0。1值
X = df.drop(["cand_pty_affiliation"], axis=1) #制作X,所以去掉y的那一列
X = pd.get_dummies(X) #属性值离散化
X.drop(X.columns[X.std() == 0], axis=1, inplace=True) #去掉标准差为0的列(因为这样的数据对程序没卵用)
return train_test_split(X, y, test_size=test_size, random_state=SEED)
print("\nExample data:")
print(df.head())
xtrain, xtest, ytrain, ytest = get_train_test()
# #以占比形式展示两个党派的数据分布,normalize=True:以百分比形式展示
# df.cand_pty_affiliation.value_counts(normalize=True).plot(
# kind="bar", title="Share of No. donations")
# plt.show()
# #打印出决策树的图片
# def print_graph(clf, feature_names):
# graph = export_graphviz(
# clf,
# label="root",
# proportion=True,
# impurity=False,
# out_file=None,
# feature_names=feature_names,
# class_names={0: "D", 1: "R"},
# filled=True,
# rounded=True
# )
# graph = pydotplus.graph_from_dot_data(graph)
# img = Image(graph.create_png())
# graph.write_png("partycontri.png")
# return img
#
# #构建深度为3的决策树
# t2 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
# t2.fit(xtrain, ytrain)
# p = t2.predict_proba(xtest)[:, 1]
#
# #计算出AUC
# print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.751
# #绘制出决策树的图片,根据图中内容发现过拟合,
# # print_graph(t2, xtrain.columns)
#
#
# #去掉先前最重要特征,再看看新决策树是否会有好转
# drop = ["transaction_amt"]
# xtrain_slim = xtrain.drop(drop, axis=1)
# xtest_slim = xtest.drop(drop, axis=1)
# t3 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
# t3.fit(xtrain_slim, ytrain)
# p = t3.predict_proba(xtest_slim)[:, 1]
# print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.740
# print_graph(t3, xtrain_slim.columns)
#
# #开始集成部分!
# #使用bagging思想,手动求平均分
# p1 = t2.predict_proba(xtest)[:, 1]
# p2 = t3.predict_proba(xtest_slim)[:, 1]
# p = np.mean([p1, p2], axis=0)#计算平均值
# print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.783
#使用bagging思想,使用sklearn提供的决策森林直接玩
# '''
# max_features:随机森林允许单个决策树使用特征的最大数量。 Python为最大特征数提供了多个可选项。 下面是其中的几个:
# Auto/None :简单地选取所有特征,每颗树都可以利用他们。这种情况下,每颗树都没有任何的限制。
# sqrt :此选项是每颗子树可以利用总特征数的平方根个。 例如,如果变量(特征)的总数是100,所以每颗子树只能取其中的10个。“log2”是另一种相似类型的选项。
# 0.2:此选项允许每个随机森林的子树可以利用变量(特征)数的20%。如果想考察的特征x%的作用, 我们可以使用“0.X”的格式
# '''
# rf = RandomForestClassifier(
# n_estimators=10,#搞10棵树
# max_features=3,
# random_state=SEED
# )
#
# rf.fit(xtrain, ytrain)
# p = rf.predict_proba(xtest)[:, 1]
# print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))
# #====================================================================================================================
#
#
# #使用bagging思想搞一个多种分类器的集成模型
from sklearn.svm import SVC, LinearSVC
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.kernel_approximation import Nystroem
from sklearn.kernel_approximation import RBFSampler
from sklearn.pipeline import make_pipeline
#构建基础分类器(分类器大合集)
def get_models():
nb = GaussianNB()
svc = SVC(C=100, probability=True)
knn = KNeighborsClassifier(n_neighbors=3)
lr = LogisticRegression(C=100, random_state=SEED)
nn = MLPClassifier((80, 10), early_stopping=False, random_state=SEED)
gb = GradientBoostingClassifier(n_estimators=100, random_state=SEED)
rf = RandomForestClassifier(n_estimators=10, max_features=3, random_state=SEED)
models = {'svm': svc,
'knn': knn,
'naive bayes': nb,
'mlp-nn': nn,
'random forest': rf,
'gbm': gb,
'logistic': lr,
}
return models
#训练模型
def train_predict(model_list):
P = np.zeros((ytest.shape[0], len(model_list))) # 初始化好结果集框架
P = pd.DataFrame(P)
print("Fitting models.")
cols = list()
for i, (name, m) in enumerate(model_list.items()):
print("%s..." % name, end=" ", flush=False)
m.fit(xtrain, ytrain)
P.iloc[:, i] = m.predict_proba(xtest)[:, 1]
cols.append(name)
print("done")
P.columns = cols #设置表头
print("Done.\n")
return P
#评估
def score_models(P, y):
print("Scoring models.")
for m in P.columns:
score = roc_auc_score(y, P.loc[:, m]) #P.loc[:, m]含义:取列名为m的列的所有行(即取出名为m的列)
print("%-26s: %.3f" % (m, score))
print("Done.\n")
models = get_models()
P = train_predict(models)
score_models(P, ytest)
#使用mlens将集成算法的关系和计算结果可视化
corrmat(P.corr(), inflate=False)
plt.show()
print("Ensemble ROC-AUC score: %.3f" % roc_auc_score(ytest, P.mean(axis=1)))#bagging一下,0.884
#绘制roc曲线,y值,预测值,集成值,标签名列表,集成标签名
def plot_roc_curve(ytest, P_base_learners, P_ensemble, labels, ens_label):
plt.figure(figsize=(10, 8))
plt.plot([0, 1], [0, 1], 'k--') #'‐‐' 破折线
cm = [plt.cm.rainbow(i)
for i in np.linspace(0, 1.0, P_base_learners.shape[1] + 1)] #7个单独算法+1个集成算法
for i in range(P_base_learners.shape[1]):
p = P_base_learners[:, i]
fpr, tpr, _ = roc_curve(ytest, p)
plt.plot(fpr, tpr, label=labels[i], c=cm[i + 1])
fpr, tpr, _ = roc_curve(ytest, P_ensemble)
plt.plot(fpr, tpr, label=ens_label, c=cm[0])
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve')
plt.legend(frameon=False)
plt.show()
plot_roc_curve(ytest, P.values, P.mean(axis=1), list(P.columns), "ensemble")
#各个算法预测的共和党占比
p = P.apply(lambda x: 1*(x >= 0.5).value_counts(normalize=True))
p.index = ["DEM", "REP"]
p.loc["REP", :].sort_values().plot(kind="bar")
plt.axhline(0.25, color="k", linewidth=0.5)
plt.text(0., 0.23, "True share republicans")
plt.show()
#
# 通过上一步展示的图片发现svm和mlp-nn和真实的共和党比例相差太大,那么我们手动直接干掉,
include = [c for c in P.columns if c not in ["mlp-nn"]]
print("Truncated ensemble ROC-AUC score: %.3f" % roc_auc_score(ytest, P.loc[:, include].mean(axis=1)))
#====================================================================================================
#手动去找麻烦,可利用stacking的思想,在第二阶段训练每个算法的权重值
base_learners = get_models()
meta_learner = GradientBoostingClassifier(#第二阶段分类器
n_estimators=1000,
loss="exponential",
max_features=4,
max_depth=3,
subsample=0.5,
learning_rate=0.005,
random_state=SEED
)
#当第一阶段的结果在第二阶段继续训练,嚼过的饭再嚼一次,很容易出现过拟合,可采用交叉验证,用交叉训练集训练模型,交叉验证集产生第二阶段的输入即可解决(毕竟交叉验证集没有进行反向传播调整权重)
#切分交叉训练集和验证集
xtrain_base, xpred_base, ytrain_base, ypred_base = train_test_split(
xtrain, ytrain, test_size=0.5, random_state=SEED)
#训练模型方法
def train_base_learners(base_learners, inp, out, verbose=True):
if verbose: print("Fitting models.")
for i, (name, m) in enumerate(base_learners.items()):
if verbose: print("%s..." % name, end=" ", flush=False)
m.fit(inp, out)
if verbose: print("done")
# 第一阶段预测出作为第二阶段输入的值
def predict_base_learners(pred_base_learners, inp, verbose=True):
P = np.zeros((inp.shape[0], len(pred_base_learners)))
if verbose: print("Generating base learner predictions.")
for i, (name, m) in enumerate(pred_base_learners.items()):
if verbose: print("%s..." % name, end=" ", flush=False)
p = m.predict_proba(inp)
P[:, i] = p[:, 1]
if verbose: print("done")
return P
#对stacking模型进行训练
def ensemble_predict(base_learners, meta_learner, inp, verbose=True):
P_pred = predict_base_learners(base_learners, inp, verbose=verbose)
return P_pred, meta_learner.predict_proba(P_pred)[:, 1]
#开始训练
train_base_learners(base_learners, xtrain_base, ytrain_base)
#交叉预测,可拿到第二阶段的输入
P_base = predict_base_learners(base_learners, xpred_base)
#在第二阶段进行各个算法的权重训练,即完成对mata_learner的训练
meta_learner.fit(P_base, ypred_base)
#用测试集进行最终测试
P_pred, p = ensemble_predict(base_learners, meta_learner, xtest)
print("\nEnsemble ROC-AUC score: %.3f" % roc_auc_score(ytest, p)) #0.880
#由于之前的暴力切分验证集,导致数据损失了一半,可以进行真正的交叉验证,具体代码可参考信用卡欺诈
#现在利用现成的集成算法库mlens实现
from mlens.ensemble import SuperLearner
# 集成算法分类器
sl = SuperLearner(
folds=10,
random_state=SEED,
verbose=2,
backend="multiprocessing"
)
# 指定各阶段的算法
sl.add(list(base_learners.values()), proba=True)
sl.add_meta(meta_learner, proba=True)
# 训练
sl.fit(xtrain, ytrain)
# 评分
p_sl = sl.predict_proba(xtest)
print("\nSuper Learner ROC-AUC score: %.3f" % roc_auc_score(ytest, p_sl[:, 1]))#0.889