集成算法介紹

森林里有很多樹(shù)

通俗理解:
集成算法就是以各種形式將多種感知器算法揉搓成一個(gè)打算法,在實(shí)際應(yīng)用中有,揉搓方式一般有:

  • Bagging:以隨機(jī)森林為代表。
    f(x) = \frac{1}{M}\sum_{m=1}^{M}f_{m}(x)
  • Boosting:Adaboost和Xgboost為代表,
    F_{m}(x) = F_{m-1}(x)+argmin_{h}\sum_{i=1}^{n}L(y_{i},F_{m-1}(x_{i})+h(x_{i}))
  • stacking:使用不同分類器得到的結(jié)果同時(shí)作為第二次訓(xùn)練的輸入

隨機(jī)森林的簡(jiǎn)單介紹

例如:建立三課決策樹(shù),從100個(gè)樣本里有放回的選擇60到80個(gè)樣本,分別放入三棵決策樹(shù)中。在決策樹(shù)選擇特征的時(shí)候,也是從10里選擇6到8特征。然后三棵樹(shù)之間不存在相互影響,并行計(jì)算得到的分?jǐn)?shù)按照上述公式取平均值即可得到最終結(jié)果。

特征重要性評(píng)估

例如:一批數(shù)據(jù)有ABCD四個(gè)特征,若想知道B特征對(duì)整個(gè)評(píng)估標(biāo)準(zhǔn)的重要程度,

  1. 首先使用這四個(gè)特征進(jìn)行模型訓(xùn)練,得到錯(cuò)誤率error1。
  2. 之后經(jīng)過(guò)某種算法,破壞B特征中屬性值的規(guī)律性,使B變成B',使用AB’CD進(jìn)行訓(xùn)練得到error2。
  3. 若error1近似error2,證明B特征沒(méi)什么用,如果error2>>error1,證明B特征重要。
  4. 在確認(rèn)B特征確實(shí)無(wú)用后,在訓(xùn)練模型時(shí)可以去掉B特征。

??:在實(shí)際使用中,并不是樹(shù)越多越好。應(yīng)該具體場(chǎng)景具體分析。

boosting簡(jiǎn)單介紹

假如:

  1. 有一個(gè)小偷,他此次真實(shí)偷取了1000塊錢(真實(shí)的y值),
  2. 警察建立了一棵樹(shù),預(yù)測(cè)后他此次能偷取950塊錢(預(yù)測(cè)目標(biāo)其實(shí)想達(dá)到1000)
  3. 然后警察計(jì)算出了殘差值R=1000-950=50,然后建立第二棵樹(shù),目標(biāo)是結(jié)果要接近殘差值50,結(jié)果得到了30。
  4. 再次計(jì)算與上一次的殘差R=50-30=20,建立第三棵樹(shù),目標(biāo)是結(jié)果要接近新的殘差值20,結(jié)果得到15。
  5. 目前為止已經(jīng)預(yù)測(cè)到的值為950+30+15=995,這個(gè)值看上去已經(jīng)很漂亮了
Adaboost簡(jiǎn)單介紹

假如:

  1. 有一批數(shù)據(jù),隨機(jī)切分成5份為ABCDE,對(duì)應(yīng)5個(gè)分類器
  2. 將每批數(shù)據(jù)分別賦予權(quán)重0.2,在進(jìn)行一次預(yù)測(cè)后,ABDE都預(yù)測(cè)對(duì)了,而C預(yù)測(cè)錯(cuò)了。
  3. 根據(jù)預(yù)測(cè)結(jié)果,調(diào)整程序,加大對(duì)錯(cuò)誤數(shù)據(jù)的權(quán)重,減輕預(yù)測(cè)正確的數(shù)據(jù)權(quán)重。如0.1_0.1_0.6_0.1_0.1。
  4. 經(jīng)過(guò)新的權(quán)重訓(xùn)練后進(jìn)行預(yù)測(cè),可能會(huì)出現(xiàn)別的數(shù)據(jù)集預(yù)測(cè)錯(cuò)誤的情況,那么繼續(xù)調(diào)整相應(yīng)權(quán)重,以此類推。

集成算法工具包推薦:ml-ens

ROC和AUC介紹

簡(jiǎn)單回顧一下混淆矩陣,橫坐標(biāo)是預(yù)測(cè)值,縱坐標(biāo)是真實(shí)的ylabel。

真\預(yù) 0 1
0 TN FP
1 FN TP

FPRate = \frac {FP}{N}
TPRate = \frac {TP}{P}
recall = \frac {TP}{P}
precision = \frac {TP}{TP+FP}
accuracy = \frac {TP+TN}{N+P}
F-measure = \frac {2}{\frac {1}{ precision } + \frac {1}{recall}}

roc曲線

AUC即為圖中陰影面積,如圖可知,面積越大,即AUC值越大,證明預(yù)測(cè)效果越好。

??:經(jīng)過(guò)實(shí)踐,我們發(fā)現(xiàn)使用集成算法,在處理數(shù)據(jù)的時(shí)候,只要你牛逼,可以根據(jù)自己需要調(diào)整到很高的精度和很高的泛化能力,但是計(jì)算量真的不小,所以集成算法不適合處理實(shí)時(shí)數(shù)據(jù)。。

代碼展示

以下,使用美國(guó)黨派捐贈(zèng)情況表,來(lái)通過(guò)各個(gè)特征預(yù)測(cè)某一次捐贈(zèng)可能屬于哪個(gè)黨派的行為。表結(jié)構(gòu)和部分?jǐn)?shù)據(jù)為:


表結(jié)構(gòu)和部分?jǐn)?shù)據(jù)展示
  • 老樣子,導(dǎo)入數(shù)據(jù)集,切分?jǐn)?shù)據(jù),同時(shí)將部分?jǐn)?shù)據(jù)離散化,one-hot編碼
SEED = 222
np.random.seed(SEED)

df = pd.read_csv('input.csv')

# 切分?jǐn)?shù)據(jù)集
def get_train_test(test_size=0.95):

    y = 1 * (df.cand_pty_affiliation == "REP") # 標(biāo)簽值轉(zhuǎn)變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) #去掉標(biāo)準(zhǔn)差為0的列(因?yàn)檫@樣的數(shù)據(jù)對(duì)程序沒(méi)卵用)
    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()
  • 查看兩個(gè)黨派的具體分布
df.cand_pty_affiliation.value_counts(normalize=True).plot(
    kind="bar", title="Share of No. donations")
plt.show()
兩黨數(shù)據(jù)分布
  • 構(gòu)建一棵3層的決策樹(shù),并計(jì)算出AUC值
#打印出決策樹(shù)的圖片
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

#構(gòu)建深度為3的決策樹(shù)
t2 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
t2.fit(xtrain, ytrain)
p = t2.predict_proba(xtest)[:, 1]

#計(jì)算出AUC
print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.751
#繪制出決策樹(shù)的圖片,根據(jù)圖中內(nèi)容發(fā)現(xiàn)過(guò)擬合,
print_graph(t2, xtrain.columns)
三層決策樹(shù)

我們可以發(fā)現(xiàn),絕大部分?jǐn)?shù)據(jù)通過(guò)預(yù)測(cè),都落入了DEM里,這樣的樹(shù)極有可能出現(xiàn)過(guò)擬合現(xiàn)象。如果出現(xiàn)這種情況,我們可以通過(guò)去掉決策能力最強(qiáng)的Transaction_amt后重新建立第二個(gè)樹(shù)模型,來(lái)看一看接下來(lái)會(huì)發(fā)生怎樣的情況。

#去掉先前最重要特征,再看看新決策樹(shù)是否會(huì)有好轉(zhuǎn)
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)
第二棵三層樹(shù)模型
  • 不好意思打臉了。。。那么既然是介紹集成算法,不妨我們把兩棵樹(shù)集成起來(lái),使用bagging思想,看一下有沒(méi)有好轉(zhuǎn)。
#使用bagging思想,手動(dòng)求平均分
p1 = t2.predict_proba(xtest)[:, 1]
p2 = t3.predict_proba(xtest_slim)[:, 1]
p = np.mean([p1, p2], axis=0)#計(jì)算平均值
print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.783

我們發(fā)現(xiàn)AUC明顯變高了。

  • 既然是兩棵樹(shù)集成的模型,不如我們直接使用隨機(jī)森林,因?yàn)閟klearn里有現(xiàn)成的隨機(jī)森林庫(kù),代碼少,活還好。
'''
max_features:隨機(jī)森林允許單個(gè)決策樹(shù)使用特征的最大數(shù)量。 Python為最大特征數(shù)提供了多個(gè)可選項(xiàng)。 下面是其中的幾個(gè):
    Auto/None :簡(jiǎn)單地選取所有特征,每顆樹(shù)都可以利用他們。這種情況下,每顆樹(shù)都沒(méi)有任何的限制。
    sqrt :此選項(xiàng)是每顆子樹(shù)可以利用總特征數(shù)的平方根個(gè)。 例如,如果變量(特征)的總數(shù)是100,所以每顆子樹(shù)只能取其中的10個(gè)?!發(fā)og2”是另一種相似類型的選項(xiàng)。
    0.2:此選項(xiàng)允許每個(gè)隨機(jī)森林的子樹(shù)可以利用變量(特征)數(shù)的20%。如果想考察的特征x%的作用, 我們可以使用“0.X”的格式
'''
rf = RandomForestClassifier(
    n_estimators=10,#搞10棵樹(shù)
    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的值明顯比之前又搞出了好多。

  • 接下來(lái)開(kāi)始作死,嘗試用不同分類器進(jìn)行集成,得到一個(gè)龐大分類器,進(jìn)行預(yù)測(cè)看看效果。一下包含兩個(gè)方法,建立
#構(gòu)建基礎(chǔ)分類器(分類器大合集)
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

#訓(xùn)練模型
def train_predict(model_list):

    P = np.zeros((ytest.shape[0], len(model_list))) # 初始化好結(jié)果集框架
    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 #設(shè)置表頭

    print("Done.\n")
    return P

#評(píng)估
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")

#開(kāi)始作死
models = get_models()
P = train_predict(models)
score_models(P, ytest)

通過(guò)預(yù)測(cè),我們得到了一下結(jié)果:

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

直接取個(gè)平均值。這里仍然使用的是bagging思想

print("Ensemble ROC-AUC score: %.3f" % roc_auc_score(ytest, P.mean(axis=1)))#bagging一下,0.884

AUC提升至0.884。

  • 另外,我們可以通過(guò)mlens庫(kù),通過(guò)各算法產(chǎn)生的結(jié)果,反推出各個(gè)算法之間的相關(guān)性:
#使用mlens將集成算法的關(guān)系和計(jì)算結(jié)果可視化
corrmat(P.corr(), inflate=False)
plt.show()
相關(guān)性
  • 同學(xué)們可以看到,之前一直使用AUC進(jìn)行模型評(píng)估,那么以上各個(gè)算法的ROC曲線到底長(zhǎng)啥樣?集成算法的ROC又長(zhǎng)啥樣?
#繪制roc曲線,y值,預(yù)測(cè)值,集成值,標(biāo)簽名列表,集成標(biāo)簽名
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個(gè)單獨(dú)算法+1個(gè)集成算法

    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")
ROC曲線
  • 我們也可以展示出不同算法計(jì)算出的REP(真值)占比
#各個(gè)算法預(yù)測(cè)的共和黨占比
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()
各算法預(yù)測(cè)的REP占比

通過(guò)圖像,我們可以看到,svm和mpl-nn預(yù)測(cè)出的占比和實(shí)際數(shù)據(jù)差太多了,索性干掉他們倆。操作的話,這里不做解釋了,刪掉相關(guān)代碼即可。

  • 那么每次都要通過(guò)觀察來(lái)刪掉不好的算法,太人工了,一點(diǎn)也不智能。那么我們可以使用stacking的方式進(jìn)行操作,在大集合算法拿到的預(yù)測(cè)值,再找一個(gè)裝B的算法進(jìn)行二階段的訓(xùn)練,來(lái)調(diào)整每個(gè)算法的權(quán)重配比。
meta_learner = GradientBoostingClassifier(#第二階段分類器
    n_estimators=1000,
    loss="exponential",
    max_features=4,
    max_depth=3,
    subsample=0.5,
    learning_rate=0.005,
    random_state=SEED
)
  • 當(dāng)?shù)谝浑A段的結(jié)果在第二階段繼續(xù)訓(xùn)練,已經(jīng)產(chǎn)生了權(quán)重上的傾斜,即嚼過(guò)的飯?jiān)俳酪淮?,很容易出現(xiàn)過(guò)擬合,可采用交叉驗(yàn)證的思想。將訓(xùn)練集一分為二。

1.用交叉訓(xùn)練集訓(xùn)練模型,
2.交叉驗(yàn)證集產(chǎn)生第二階段的輸入即可解決(畢竟交叉驗(yàn)證集沒(méi)有進(jìn)行反向傳播調(diào)整權(quán)重)

#切分交叉訓(xùn)練集和驗(yàn)證集
xtrain_base, xpred_base, ytrain_base, ypred_base = train_test_split(
    xtrain, ytrain, test_size=0.5, random_state=SEED)

#訓(xùn)練模型方法
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")


# 第一階段預(yù)測(cè)出作為第二階段輸入的值
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

#對(duì)stacking模型進(jìn)行訓(xùn)練
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]

#開(kāi)始訓(xùn)練
train_base_learners(base_learners, xtrain_base, ytrain_base)
#交叉預(yù)測(cè),可拿到第二階段的輸入
P_base = predict_base_learners(base_learners, xpred_base)
#在第二階段進(jìn)行各個(gè)算法的權(quán)重訓(xùn)練,即完成對(duì)mata_learner的訓(xùn)練
meta_learner.fit(P_base, ypred_base)
#用測(cè)試集進(jìn)行最終測(cè)試
P_pred, p = ensemble_predict(base_learners, meta_learner, xtest)
print("\nEnsemble ROC-AUC score: %.3f" % roc_auc_score(ytest, p)) #0.880

但我們發(fā)現(xiàn)效果并沒(méi)有好多少,那是因?yàn)槲覀冊(cè)谟?xùn)練階段拿到的數(shù)據(jù)少了一半,效果肯定不好啊!那么我們可以采用真正的交叉驗(yàn)證來(lái)解決這種粗暴的拆分方式,具體代碼這里不寫了,請(qǐng)參考另一篇文章離散型隨機(jī)變量的二分類預(yù)測(cè)案例
,里面有關(guān)于交叉驗(yàn)證具體的操作代碼。

  • 然而之前推薦的mlens庫(kù)中自帶了集成算法的框架,就和隨機(jī)森林一樣,不用我們這樣造輪子了,里面已經(jīng)寫好了并行訓(xùn)練多分類器,交叉驗(yàn)證等操作,上代碼:
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)

# 訓(xùn)練
sl.fit(xtrain, ytrain)

# 評(píng)分
p_sl = sl.predict_proba(xtest)

print("\nSuper Learner ROC-AUC score: %.3f" % roc_auc_score(ytest, p_sl[:, 1]))#0.889

效果不錯(cuò)。
以上內(nèi)容介紹了集成算法的一些思想,通過(guò)代碼從決策樹(shù),隨機(jī)森林,stacking等角度實(shí)踐了預(yù)測(cè)方法,對(duì)于數(shù)據(jù)的預(yù)處理沒(méi)有進(jìn)行過(guò)多操作。
完整代碼:

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


# 指定隨機(jī)種子
SEED = 222
np.random.seed(SEED)

df = pd.read_csv('input.csv')

# 切分?jǐn)?shù)據(jù)集
def get_train_test(test_size=0.95):

    y = 1 * (df.cand_pty_affiliation == "REP") # 標(biāo)簽值轉(zhuǎn)變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) #去掉標(biāo)準(zhǔn)差為0的列(因?yàn)檫@樣的數(shù)據(jù)對(duì)程序沒(méi)卵用)
    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()



# #以占比形式展示兩個(gè)黨派的數(shù)據(jù)分布,normalize=True:以百分比形式展示
# df.cand_pty_affiliation.value_counts(normalize=True).plot(
#     kind="bar", title="Share of No. donations")
# plt.show()



# #打印出決策樹(shù)的圖片
# 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
#
# #構(gòu)建深度為3的決策樹(shù)
# t2 = DecisionTreeClassifier(max_depth=3, random_state=SEED)
# t2.fit(xtrain, ytrain)
# p = t2.predict_proba(xtest)[:, 1]
#
# #計(jì)算出AUC
# print("Decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.751
# #繪制出決策樹(shù)的圖片,根據(jù)圖中內(nèi)容發(fā)現(xiàn)過(guò)擬合,
# # print_graph(t2, xtrain.columns)
#
#
# #去掉先前最重要特征,再看看新決策樹(shù)是否會(huì)有好轉(zhuǎn)
# 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)
#
# #開(kāi)始集成部分!
# #使用bagging思想,手動(dòng)求平均分
# p1 = t2.predict_proba(xtest)[:, 1]
# p2 = t3.predict_proba(xtest_slim)[:, 1]
# p = np.mean([p1, p2], axis=0)#計(jì)算平均值
# print("Average of decision tree ROC-AUC score: %.3f" % roc_auc_score(ytest, p))#0.783


#使用bagging思想,使用sklearn提供的決策森林直接玩
# '''
# max_features:隨機(jī)森林允許單個(gè)決策樹(shù)使用特征的最大數(shù)量。 Python為最大特征數(shù)提供了多個(gè)可選項(xiàng)。 下面是其中的幾個(gè):
#     Auto/None :簡(jiǎn)單地選取所有特征,每顆樹(shù)都可以利用他們。這種情況下,每顆樹(shù)都沒(méi)有任何的限制。
#     sqrt :此選項(xiàng)是每顆子樹(shù)可以利用總特征數(shù)的平方根個(gè)。 例如,如果變量(特征)的總數(shù)是100,所以每顆子樹(shù)只能取其中的10個(gè)。“l(fā)og2”是另一種相似類型的選項(xiàng)。
#     0.2:此選項(xiàng)允許每個(gè)隨機(jī)森林的子樹(shù)可以利用變量(特征)數(shù)的20%。如果想考察的特征x%的作用, 我們可以使用“0.X”的格式
# '''
# rf = RandomForestClassifier(
#     n_estimators=10,#搞10棵樹(shù)
#     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思想搞一個(gè)多種分類器的集成模型
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


#構(gòu)建基礎(chǔ)分類器(分類器大合集)
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


#訓(xùn)練模型
def train_predict(model_list):

    P = np.zeros((ytest.shape[0], len(model_list))) # 初始化好結(jié)果集框架
    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 #設(shè)置表頭

    print("Done.\n")
    return P

#評(píng)估
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將集成算法的關(guān)系和計(jì)算結(jié)果可視化
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值,預(yù)測(cè)值,集成值,標(biāo)簽名列表,集成標(biāo)簽名
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個(gè)單獨(dú)算法+1個(gè)集成算法

    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")


#各個(gè)算法預(yù)測(cè)的共和黨占比
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()
#
# 通過(guò)上一步展示的圖片發(fā)現(xiàn)svm和mlp-nn和真實(shí)的共和黨比例相差太大,那么我們手動(dòng)直接干掉,
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)))
#====================================================================================================
#手動(dòng)去找麻煩,可利用stacking的思想,在第二階段訓(xùn)練每個(gè)算法的權(quán)重值
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
)

#當(dāng)?shù)谝浑A段的結(jié)果在第二階段繼續(xù)訓(xùn)練,嚼過(guò)的飯?jiān)俳酪淮?,很容易出現(xiàn)過(guò)擬合,可采用交叉驗(yàn)證,用交叉訓(xùn)練集訓(xùn)練模型,交叉驗(yàn)證集產(chǎn)生第二階段的輸入即可解決(畢竟交叉驗(yàn)證集沒(méi)有進(jìn)行反向傳播調(diào)整權(quán)重)

#切分交叉訓(xùn)練集和驗(yàn)證集
xtrain_base, xpred_base, ytrain_base, ypred_base = train_test_split(
    xtrain, ytrain, test_size=0.5, random_state=SEED)

#訓(xùn)練模型方法
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")


# 第一階段預(yù)測(cè)出作為第二階段輸入的值
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

#對(duì)stacking模型進(jìn)行訓(xùn)練
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]

#開(kāi)始訓(xùn)練
train_base_learners(base_learners, xtrain_base, ytrain_base)
#交叉預(yù)測(cè),可拿到第二階段的輸入
P_base = predict_base_learners(base_learners, xpred_base)
#在第二階段進(jìn)行各個(gè)算法的權(quán)重訓(xùn)練,即完成對(duì)mata_learner的訓(xùn)練
meta_learner.fit(P_base, ypred_base)
#用測(cè)試集進(jìn)行最終測(cè)試
P_pred, p = ensemble_predict(base_learners, meta_learner, xtest)
print("\nEnsemble ROC-AUC score: %.3f" % roc_auc_score(ytest, p)) #0.880


#由于之前的暴力切分驗(yàn)證集,導(dǎo)致數(shù)據(jù)損失了一半,可以進(jìn)行真正的交叉驗(yàn)證,具體代碼可參考信用卡欺詐

#現(xiàn)在利用現(xiàn)成的集成算法庫(kù)mlens實(shí)現(xiàn)
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)

# 訓(xùn)練
sl.fit(xtrain, ytrain)

# 評(píng)分
p_sl = sl.predict_proba(xtest)

print("\nSuper Learner ROC-AUC score: %.3f" % roc_auc_score(ytest, p_sl[:, 1]))#0.889
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、集成算法分為三類: 幾大算法之間的關(guān)系:https://blog.csdn.net/shange19/arti...
    羽天驛閱讀 268評(píng)論 0 0
  • 為什么使用集成算法 ?簡(jiǎn)單算法一般復(fù)雜度低,速度快,易展示結(jié)果,但預(yù)測(cè)效果往往不是特別好。每種算法好像一種專家,集...
    xieyan0811閱讀 12,060評(píng)論 0 7
  • 3、結(jié)論集成方法 表示如何選擇一種結(jié)合策略將個(gè)體學(xué)習(xí)器集合起來(lái),形成強(qiáng)學(xué)習(xí)器,針對(duì)的是不同個(gè)體學(xué)習(xí)器的訓(xùn)練結(jié)果,我...
    博觀厚積閱讀 887評(píng)論 0 0
  • 久違的晴天,家長(zhǎng)會(huì)。 家長(zhǎng)大會(huì)開(kāi)好到教室時(shí),離放學(xué)已經(jīng)沒(méi)多少時(shí)間了。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,788評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    余生動(dòng)聽(tīng)閱讀 10,798評(píng)論 0 11

友情鏈接更多精彩內(nèi)容