介紹:模型融合一般能夠在各類不一樣的機器學習任務中使結果得到提高。顧名思義,模型融合就是綜合考慮不一樣模型的狀況,並將它們的結果融合到一塊兒。具體內容會從如下幾個方面來說:算法
一、Voting框架
二、Averagingdom
三、Ranking機器學習
四、Bagging學習
五、Boosting測試
六、Stackingrest
七、Blendingip
Voting即投票機制,分爲軟投票和硬投票兩種,其原理採用少數服從多數的思想。get
硬投票:對多個模型直接進行投票,最終投票數最多的類爲最終被預測的類。it
軟投票:和硬投票原理相同,增長了設置權重的功能,能夠爲不一樣模型設置不一樣權重,進而區別模型不一樣的重要度。
備註:此方法用於解決分類問題。
代碼實例以下:
硬投票:
iris = datasets.load_iris() x=iris.data y=iris.target x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3) clf1 = XGBClassifier(learning_rate=0.1, n_estimators=140, max_depth=1, min_child_weight=2, gamma=0, subsample=0.7, colsample_bytree=0.6, objective='binary:logistic', nthread=4, scale_pos_weight=1) clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4, min_samples_leaf=54,oob_score=True) clf3 = SVC(C=0.1, probability=True)# 硬投票eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='hard')for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']): scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy') print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
軟投票:
x=iris.data y=iris.target x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3) clf1 = XGBClassifier(learning_rate=0.1, n_estimators=140, max_depth=1, min_child_weight=2, gamma=0, subsample=0.7, colsample_bytree=0.6, objective='binary:logistic', nthread=4, scale_pos_weight=1) clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4, min_samples_leaf=54,oob_score=True) clf3 = SVC(C=0.1, probability=True)# 軟投票eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='soft', weights=[2, 1, 1]) clf1.fit(x_train, y_train)
Averaging,其原理是對模型結果取平均。
處理迴歸問題,直接取平均值做爲最終的預測值。(也可使用加權平均)
平均法存在問題就是若是不一樣迴歸方法的預測結果波動幅度相差比較大,那麼波動小的迴歸結果在融合時候起的做用就比較小。
Ranking的思想和Averaging一致,可是由於上述平均法存在必定的問題。
因此這裏採用了把排名作平均,若是有權重,則求n個模型權重比排名之和,即爲最後的結果。
Bagging方法的出現,能夠完美地解決了決策樹過擬合的問題,同時bagging的使用也會使分類器分類效果獲得了顯著的提升。
應用場景:對不穩定的分類器作Bagging是一個好主意。在機器學習中,若是訓練數據的一個小變化致使學習中的分類器的大變化,則該算法(或學習算法)被認爲是不穩定的。
Bagging就是採用有放回的方式進行抽樣,用抽樣的樣本創建子模型,對子模型進行訓練,這個過程重複屢次,最後進行融合。大概分爲兩步:
1.重複K次
有放回地重複抽樣建模
訓練子模型
2.模型融合
模型融合,若是是分類問題用voting解決 。若是是迴歸問題用average解決。
注意:在bagging集成中,各個模型的預測不會彼此依賴。Bagging算法不用咱們本身實現,隨機森林就是基於Bagging算法的一個典型例子,採用的基分類器是決策樹。能夠直接調用。
Boosting的思想是一種迭代的方法,它每次訓練使用的都是同一個訓練集。可是每次它會給這些分類錯誤的樣例增長更大的權重,下一次迭代的目標就是可以更容易辨別出上一輪分類錯誤的樣例。最終將這些弱分類器進行加權相加。
注意:Boosting下一次的迭代必須在上一次的基礎上。
一樣地,基於Boosting思想的有AdaBoost、GBDT等,也能夠直接調用。
stacking是一種分層模型集成框架。以兩層爲例,第一層由多個基學習器組成,其輸入爲原始訓練集,第二層的模型則是以第一層基學習器的輸出做爲訓練集進行再訓練,從而獲得完整的stacking模型。
stacking兩層模型都使用了所有的訓練數據。
第一層模型:
首先數據有訓練集和測試集兩部分
1.對訓練集進行五折交叉驗證,把訓練集劃分爲A,B兩部分
2.對A部分進行訓練,對B部分進行預測,獲得a1,五折後則爲a1,a2,a3,a4,a5,對他們合併,造成n行一列的數據
3.對測試集進行預測,會獲得b1,b2,b3,b4,b5,將各部分相加取平均獲得m行一列的數據
4,。以上是一個模型,若是有三個模型,則能夠獲得A1,A2,A3,B1,B2,B3
5.在此以後,咱們把A1,A2,A3並列合併獲得一個n行三列的矩陣做爲training data,B1,B2,B3並列合併獲得一個m行三列的矩陣做爲testing data。讓下一層的模型,基於他們進一步訓練。
代碼實例:
#建立訓練的數據集data, target = make_blobs(n_samples=50000, centers=2, random_state=0, cluster_std=0.60)#模型融合中使用到的各個單模型clfs = [RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'), RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'), ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'), ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'), GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]#切分一部分數據做爲測試集X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.33, random_state=2017) dataset_blend_train = np.zeros((X.shape[0], len(clfs))) dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))#5折stackingn_folds = 5skf = list(StratifiedKFold(y, n_folds))for j, clf in enumerate(clfs): #依次訓練各個單模型 dataset_blend_test_j = np.zeros((X_predict.shape[0], len(skf))) for i, (train, test) in enumerate(skf): #使用第i個部分做爲預測,剩餘的部分來訓練模型,得到其預測的輸出做爲第i部分的新特徵。 X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test] clf.fit(X_train, y_train) y_submission = clf.predict_proba(X_test)[:, 1] dataset_blend_train[test, j] = y_submission dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1] #對於測試集,直接用這k個模型的預測值均值做爲新的特徵。 dataset_blend_test[:, j] = dataset_blend_test_j.mean(1) print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))# clf = LogisticRegression()clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30) clf.fit(dataset_blend_train, y) y_submission = clf.predict_proba(dataset_blend_test)[:, 1]print("Linear stretch of predictions to [0,1]") y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))
備註:此處只是一部分代碼
Bending是一種模型融合方法,對於通常的Blending,主要思路是把原始的訓練集先分紅兩部分,好比70%的數據做爲新的訓練集,剩下30%的數據做爲測試集。第一層咱們在這70%的數據上訓練多個模型,而後去預測那30%數據的label。在第二層裏,咱們就直接用這30%數據在第一層預測的結果作爲新特徵繼續訓練便可。
Blending的優勢在於:
1.比stacking簡單(由於不用進行k次的交叉驗證來得到stacker feature)
2.避開了一個信息泄露問題:generlizers和stacker使用了不同的數據集
而缺點在於:
1.使用了不多的數據(第二階段的blender只使用training set10%的量)
2.blender可能會過擬合
3.stacking使用屢次的交叉驗證會比較穩健
對於實踐中的結果而言,stacking和blending的效果是差很少的,因此使用哪一種方法都沒什麼所謂,徹底取決於我的愛好。
代碼實例:
#建立訓練的數據集data, target = make_blobs(n_samples=50000, centers=2, random_state=0, cluster_std=0.60)#模型融合中使用到的各個單模型clfs = [RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'), RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'), ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'), ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'), GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]#切分一部分數據做爲測試集X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.33, random_state=2017)#5折stackingn_folds = 5skf = list(StratifiedKFold(y, n_folds))#切分訓練數據集爲d1,d2兩部分X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=2017) dataset_d1 = np.zeros((X_d2.shape[0], len(clfs))) dataset_d2 = np.zeros((X_predict.shape[0], len(clfs)))for j, clf in enumerate(clfs): #依次訓練各個單模型 clf.fit(X_d1, y_d1) y_submission = clf.predict_proba(X_d2)[:, 1] dataset_d1[:, j] = y_submission #對於測試集,直接用這k個模型的預測值做爲新的特徵。 dataset_d2[:, j] = clf.predict_proba(X_predict)[:, 1] print("val auc Score: %f" % roc_auc_score(y_predict, dataset_d2[:, j]))#融合使用的模型clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30) clf.fit(dataset_d1, y_d2) y_submission = clf.predict_proba(dataset_d2)[:, 1]print("Linear stretch of predictions to [0,1]") y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))
以上的七種模型融合方法,在必定狀況下能夠提升模型的準確率,方法沒有好壞之分,各有本身的優缺點,具體實施可針對具體場景。