集成算法介紹

森林里有很多樹(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:使用不同分類(lèi)器得到的結(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塊錢(qián)(真實(shí)的y值)极谊,
  2. 警察建立了一棵樹(shù),預(yù)測(cè)后他此次能偷取950塊錢(qián)(預(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è)分類(lèi)器
  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)重婶肩,以此類(lèi)推。

集成算法工具包推薦: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è)哑蔫《で蓿“l(fā)og2”是另一種相似類(lèi)型的選項(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)始作死腥沽,嘗試用不同分類(lèi)器進(jìn)行集成逮走,得到一個(gè)龐大分類(lèi)器,進(jìn)行預(yù)測(cè)看看效果今阳。一下包含兩個(gè)方法师溅,建立
#構(gòu)建基礎(chǔ)分類(lèi)器(分類(lèi)器大合集)
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(#第二階段分類(lèi)器
    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)俳酪淮析荩苋菀壮霈F(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)解決這種粗暴的拆分方式,具體代碼這里不寫(xiě)了创译,請(qǐng)參考另一篇文章離散型隨機(jī)變量的二分類(lèi)預(yù)測(cè)案例
,里面有關(guān)于交叉驗(yàn)證具體的操作代碼抵知。

  • 然而之前推薦的mlens庫(kù)中自帶了集成算法的框架,就和隨機(jī)森林一樣软族,不用我們這樣造輪子了刷喜,里面已經(jīng)寫(xiě)好了并行訓(xùn)練多分類(lèi)器,交叉驗(yàn)證等操作,上代碼:
from mlens.ensemble import SuperLearner

# 集成算法分類(lèi)器
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”是另一種相似類(lèi)型的選項(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è)多種分類(lèi)器的集成模型
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ǔ)分類(lèi)器(分類(lèi)器大合集)
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(#第二階段分類(lèi)器
    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)俳酪淮未保苋菀壮霈F(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

# 集成算法分類(lèi)器
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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市补履,隨后出現(xiàn)的幾起案子添坊,更是在濱河造成了極大的恐慌,老刑警劉巖箫锤,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贬蛙,死亡現(xiàn)場(chǎng)離奇詭異雨女,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)阳准,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)氛堕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人野蝇,你說(shuō)我怎么就攤上這事讼稚。” “怎么了绕沈?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵锐想,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我乍狐,道長(zhǎng)赠摇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任浅蚪,我火速辦了婚禮藕帜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掘鄙。我一直安慰自己耘戚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布操漠。 她就那樣靜靜地躺著收津,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浊伙。 梳的紋絲不亂的頭發(fā)上撞秋,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音嚣鄙,去河邊找鬼吻贿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哑子,可吹牛的內(nèi)容都是我干的舅列。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼卧蜓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帐要!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起弥奸,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榨惠,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赠橙,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耽装,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了期揪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掉奄。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖横侦,靈堂內(nèi)的尸體忽然破棺而出挥萌,到底是詐尸還是另有隱情,我是刑警寧澤枉侧,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布引瀑,位于F島的核電站,受9級(jí)特大地震影響榨馁,放射性物質(zhì)發(fā)生泄漏憨栽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一翼虫、第九天 我趴在偏房一處隱蔽的房頂上張望屑柔。 院中可真熱鬧,春花似錦珍剑、人聲如沸掸宛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唧瘾。三九已至,卻和暖如春别凤,著一層夾襖步出監(jiān)牢的瞬間饰序,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工规哪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留求豫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓诉稍,卻偏偏與公主長(zhǎng)得像蝠嘉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杯巨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一是晨、集成算法分為三類(lèi): 幾大算法之間的關(guān)系:https://blog.csdn.net/shange19/arti...
    羽天驛閱讀 194評(píng)論 0 0
  • 為什么使用集成算法 ?簡(jiǎn)單算法一般復(fù)雜度低,速度快舔箭,易展示結(jié)果,但預(yù)測(cè)效果往往不是特別好。每種算法好像一種專家层扶,集...
    xieyan0811閱讀 11,834評(píng)論 0 7
  • 3镜会、結(jié)論集成方法 表示如何選擇一種結(jié)合策略將個(gè)體學(xué)習(xí)器集合起來(lái)檬寂,形成強(qiáng)學(xué)習(xí)器,針對(duì)的是不同個(gè)體學(xué)習(xí)器的訓(xùn)練結(jié)果戳表,我...
    博觀厚積閱讀 840評(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,523評(píng)論 16 22
  • 今天感恩節(jié)哎价涝,感謝一直在我身邊的親朋好友女蜈。感恩相遇!感恩不離不棄色瘩。 中午開(kāi)了第一次的黨會(huì)伪窖,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,567評(píng)論 0 11