【实战篇】集成算法建模(三)

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 思想集成都是按照平均来算的,但是这样公平吗?有些拖后腿的模型是不是应该把它去掉呢?我们下节见~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352