Hello,大家好~ 今天是农历 2021 年的最后一天 - 除夕,小鱼在这里先给大家拜年啦,祝您和您的家人虎虎生威,虎年大吉!
下面,我们正式开始充电啦~
书接上一篇连载:我们分别使用决策树、以及随机森林实现了建模,并最终在未进行任何调参的情况下,使用随机森林得到了 0.869 的 ROC-AUC Score 值。
其中,随机森林其实就是 Bagging 的集成思想,通过构造一批不同的决策树,来综合考虑每棵树的结果,得到最终的值。相比于单棵树,结果得到了更大的提升,不仅泛化能力强,过拟合风险小,而且大幅提升了模型的准确性。
今天,我们将进一步提升模型的泛化能力以及准确性。随机森林的基础模型都是决策树,那我们是否可以使用不同的算法,构造出不同的基础模型呢?如 KNN,LR,SVM,RF 等等。
最后将所有模型得到的预测结果取平均,做为最终的预测值:
下面,我们不妨来尝试一下~
代码实现
导入集成时用到的各类型分类器:
from sklearn.svm import SVC
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
构建基础的模型,并以字典的形式批量返回所有模型:
def get_models():
"""Generate a library of base learners."""
nb = GaussianNB()
svc = SVC(C=100, probability=True)
knn = KNeighborsClassifier(n_neighbors=3)
lr = LogisticRegression(C=100, random_state=SEED, solver="liblinear")
nn = MLPClassifier((80,10), early_stopping=False, random_state=SEED)
gb = GradientBoostingClassifier(n_estimators=100, random_state=SEED)
rf = RandomForestClassifier(n_estimators=10, max_depth=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(models):
"""Fit models in list on training set and return preds"""
P = np.zeros((ytest.shape[0], len(models)))
P = pd.DataFrame(P)
print("Fitting models.")
cols = list()
for i, (name, m) in enumerate(models.items()):
print("{} ...".format(name), end=" ", flush=False)
m.fit(x_over_sample_train, y_over_sample_train)
P.iloc[:, i] = m.predict_proba(xtest)[:, 1]
cols.append(name)
print("done")
P.columns = cols
print("Fitting models Done.")
return P
其中 P
用来存放所有模型的预测结果,P
中的行对应测试集中每个样本通过不同的模型预测的结果值,列为具体的算法模型的所有预测值。因此,测试集有多少个样本,P
就有多少行;有多少个模型,P
就有多少列。
接下来,就是使用 for
循环,分别使用不同的模型进行训练以及预测,并将预测结果保存在 P
中。此处小鱼没有并行地训练多个分类器,一方面小鱼训练集的数据比较少,另一方面呢,没有交叉验证,调参的过程。整个过程还是比较快的。
最后,将预测结果 P
进行返回。
拿到预测结果的组合 P
之后,就可以分别计算各模型的 AUC-ROC Score 啦~
def score_model(P, y):
"""Score model in prediction DF"""
print("Scoring models.")
s = pd.Series()
for m in P.columns:
score = roc_auc_score(y, P.loc[:, m])
s.loc[m] = score
print(s.sort_values())
print("Scoring models Done.")
训练模型,观察结果
models = get_models()
P = train_predict(models)
训练和预测过程的终端输出:
Fitting models.
svm ... done
knn ... done
naive bayes ... done
mlp-nn ... done
random forest ... done
gbm ... done
logistic ... done
Fitting models Done.
各模型预测的 ROC-AUC Score:
>> score_model(P, ytest)
Scoring models.
svm 0.721109
naive bayes 0.739966
knn 0.804353
random forest 0.805589
logistic 0.852700
mlp-nn 0.865270
gbm 0.876627
dtype: float64
Scoring models Done.
其中,各模型预测的结果 P
如下:
P.head()
通过计算 P
的相关系数,可以了解各模型之间的相似层度:
P.corr()
每个模型自然和自身的相关性最强,因此对角线上的值为 1 ;值越大,相关系越强,反之,相关系越弱。
当然了,也可以借助 ML-Ensemble 为我们提供的可视化工具来直观地观察出模型的相似层度:
from mlens.visualization import corrmat
corrmat(P.corr(), inflate=False)
注:需要安装
pip install mlens
库。
绘制结果:
通过观察相关性矩阵,可以发现 mlp-nn
模型、gbm
模型以及 logistic
模型的相关度是比较高的。
计算所有模型预测的结果
最后,我们将所有模型预测的结果值取平均,计算 ROC-AUC Score:
>> print("Ensemble ROC-AUC score: %.3f" % roc_auc_score(ytest, P.mean(axis=1)))
Ensemble ROC-AUC score: 0.880
在 bagging 集成时,通过集成不同算法类型的模型,获得的结果值又得到了提升。可见,继承算法一方面可以使得边界更平稳,降低过拟合的风险,提高模型的泛化能力;另一方面可以有效地提高模型的评分。
下面,是逻辑回归、随机森林、SVM 以及集成算法分类的示意图:
绘制 ROC 曲线
定义绘制 ROC 曲线的函数:
from sklearn.metrics import roc_curve
def plot_roc_curve(ytest, P_base_learners, P_ensemble, labels, ens_label):
"""Plot the roc curve for base learners and ensemble."""
plt.figure(figsize=(5, 4), dpi=120)
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)]
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()
上述代码中,plt.plot([0, 1], [0, 1], 'k--')
在 (0,0)和(1,1)之间绘制一条虚线,表示随机的预测结果。ROC 曲线基本会分布在该曲线上方。
cm
为绘制不同模型的 ROC 曲线时使用的 Clolor Map。plt.plot()
绘图时,首先使用 for
循环绘制了所有的基础模型的 ROC 曲线,之后单独绘制集成模型的 ROC 曲线。
from sklearn.metrics import roc_curve
可以根据真实值和预测值,计算出 False Positive Rate 和 True Positive Rate。
绘图:
plot_roc_curve(ytest, P.values, P.mean(axis=1), list(P.columns), "ensemble")
emsemble 曲线既平滑,面积又是最大的!此外,逻辑回归作为机器学习中最简单的模型,结果也是非常棒的。正如小鱼前面所说,在机器学习中,模型并非越复杂越好,逻辑回归也是一把宝刀~
以上就是今天的内容啦~小鱼里一个思考问题:我们上述使用 Bagging 思想集成都是按照平均来算的,但是这样公平吗?有些拖后腿的模型是不是应该把它去掉呢?我们下节见~