05モデルフュージョン

モデル融合の目標:調整されたさまざまなモデルのモデル融合

モデルフュージョンはゲーム後半の重要な部分であり、一般的には次のタイプがあります。

1.シンプルな加重フュージョン:

  • 回帰(分類確率):算術平均、幾何平均。
#简单加权平均,结果直接融合
## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

# y_test_true 代表第模型的真实值
y_test_true = [1, 3, 2, 6] 

import numpy as np
import pandas as pd

## 定义结果的加权平均函数
def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
    Weighted_result = w[0]*pd.Series(test_pre1)+w[1]*pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
    return Weighted_result



from sklearn import metrics
# 各模型的预测结果计算MAE
print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
print('Pred3 MAE:',metrics.mean_absolute_error(y_test_true, test_pre3))



## 根据加权计算MAE
w = [0.3,0.4,0.3] # 定义比重权值
Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))

## 定义结果的加权平均函数
def Mean_method(test_pre1,test_pre2,test_pre3):
    Mean_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).mean(axis=1)
    return Mean_result


Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3)
print('Mean_pre MAE:',metrics.mean_absolute_error(y_test_true, Mean_pre))

 

  • カテゴリ:投票
#分类模型融合

from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold

#Voting投票机制
#Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。

'''
硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
'''
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=150, max_depth=3, min_child_weight=2, subsample=0.7,
                     colsample_bytree=0.6, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                              min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1)

# 硬投票
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=150, max_depth=3, min_child_weight=2, subsample=0.8,
                     colsample_bytree=0.8, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                              min_samples_leaf=63,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)

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



 

  • 合成:ランク平均、対数融合

 

2.スタッキング/ブレンド:

  • 多層モデルを構築し、予測結果を使用して予測に適合させます。

積み重ねとは

簡単に言うと、スタッキングとは、初期トレーニングデータを使用していくつかの基本的な学習者を学習し、これらの学習者の予測結果を新しい学習セットとして使用して、新しい学習者を学習することです。

個々の学習者を組み合わせるときに使用される方法は、組み合わせ戦略と呼ばれます。分類の問題については、投票方法を使用して、最も出力クラスを選択できます。回帰問題の場合、分類子によって出力された結果を平均化できます。

上記の投票方法と平均化方法は非常に効果的な組み合わせ戦略です。別の組み合わせ戦略は、別の機械学習アルゴリズムを使用して個々の機械学習者の結果を組み合わせる方法です。この方法はスタッキングです。

スタッキング方式では、個々の学習者を一次学習者と呼び、結合に使用される学習者を二次学習者またはメタ学習者と呼び、二次学習者がトレーニングに使用するデータを二次学習セットと呼びます。セカンダリトレーニングセットは、トレーニングセットのプライマリ学習者とともに取得されます。

 

積み方

アルゴリズムの概略図は次のとおりです。

  • プロセス1-3は、主要な学習者である個々の学習者をトレーニングすることです。
  • プロセス5-9は、訓練された個々の学習者を使用して予測結果を取得することです。これは、二次学習者のトレーニングセットとして使用されます。
  • プロセス11は、一次学習者が予測した結果で二次学習者をトレーニングし、最終的にトレーニングしたモデルを取得することです。

スタッキング方式

まず、「それほど正しくない」が、理解しやすいスタッキング方法から始めましょう。

スタッキングモデルは基本的に階層構造です。簡単にするために、第2レベルのスタッキングのみが分析されます。2つのベースモデルModel1_1、Model1_2、およびセカンダリモデルModel2があるとします。

ステップ1.モデルModel1_1をベースにして、トレーニングセットtrainをトレーニングし、トレーニングとテストのラベル列をそれぞれ予測するために使用するP1、T1

Model1_1モデルトレーニング:

トレーニング済みモデルModel1_1は、トレーニングとテストでそれぞれ予測され、予測されたラベルはそれぞれP1とT1です。

 

ステップ2.モデルModel1_2をベースにして、トレーニングセットtrainをトレーニングし、trainおよびtestのラベル列をそれぞれ予測するために使用するP2、T2

Model1_2モデルトレーニング:

トレーニング済みモデルModel1_2は、トレーニングとテストでそれぞれ予測され、予測されたラベルはそれぞれP2とT2です。

 

ステップ3. P1、P2およびT1、T2をそれぞれ組み合わせて、新しいトレーニングセットとテストセットtrain2、test2を取得します。

次に、セカンダリモデルModel2を使用して、実際のトレーニングセットラベルをラベルとしてトレーニングし、train2を機能としてトレーニングして、test2を予測し、最終的なテストセットの予測ラベル列を取得します。

これは、2層スタッキングの基本的なオリジナルのアイデアです。さまざまなモデルの予測結果に基づいて、モデルの別のレイヤーを追加し、再トレーニングしてモデルの最終的な予測を取得します。

スタッキングは本質的にそのような単純なアイデアですが、トレーニングセットとテストセットが均一に分散されていない場合は、少し問題になることがあります。問題は、初期モデルでトレーニングされたラベルが実際のラベルで再トレーニングされることです。特定のモデルがトレーニングセットにオーバーフィットすることは間違いありません。したがって、テストセットに対するモデルの汎化能力または効果はある程度低下するため、再トレーニングのオーバーフィットを減らす方法が問題になります。 、ここでは一般的に2つの方法があります。

    1. 二次モデルに単純な線形モデルを選択してみてください
    1. K分割を使用した交差検証

K分割交差検証:トレーニング:

画像

予報:

# Stacking融合(回归)

from sklearn import linear_model

def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
    model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
    Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
    return Stacking_result



## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
train_reg1 = [3.2, 8.2, 9.1, 5.2]
train_reg2 = [2.9, 8.1, 9.0, 4.9]
train_reg3 = [3.1, 7.9, 9.2, 5.0]
# y_test_true 代表第模型的真实值
y_train_true = [3, 8, 9, 5] 

test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

# y_test_true 代表第模型的真实值
y_test_true = [1, 3, 2, 6] 



model_L2= linear_model.LinearRegression()
Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
                               test_pre1,test_pre2,test_pre3,model_L2)
print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))

分類されたスタッキング\融合融合

スタッキングは、レイヤードモデル統合フレームワークです。

2つのレイヤーを例にとると、最初のレイヤーは複数の基本学習者で構成され、その入力は元のトレーニングセットであり、2番目のレイヤーのモデルは、基本学習者の最初のレイヤーの出力を再トレーニングのトレーニングセットとして使用して、完全なトレーニングを取得します。スタッキングモデルでは、両方のスタッキングモデルがすべてのトレーニングデータを使用します。

'''
5-Fold Stacking
'''
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier,GradientBoostingClassifier
import pandas as pd
#创建训练的数据集
data_0 = iris.data
data = data_0[:100,:]

target_0 = iris.target
target = target_0[:100]

#模型融合中使用到的各个单模型
clfs = [LogisticRegression(solver='lbfgs'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        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.3, random_state=2020)

dataset_blend_train = np.zeros((X.shape[0], len(clfs)))
dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))

#5折stacking
n_splits = 5
skf = StratifiedKFold(n_splits)
skf = skf.split(X, y)

for j, clf in enumerate(clfs):
    #依次训练各个单模型
    dataset_blend_test_j = np.zeros((X_predict.shape[0], 5))
    for i, (train, test) in enumerate(skf):
        #5-Fold交叉训练,使用第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(solver='lbfgs')
clf.fit(dataset_blend_train, y)
y_submission = clf.predict_proba(dataset_blend_test)[:, 1]

print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))

 

実際、ブレンドは、スタックとのマルチレイヤーモデルフュージョンと同様の形式です。

主なアイデアは、元のトレーニングセットを2つの部分に分割することです。たとえば、データの70%は新しいトレーニングセットとして使用され、残りの30%はテストセットとして使用されます。

最初のレイヤーでは、70%のデータで複数のモデルをトレーニングし、30%のデータのラベルを予測し、テストセットのラベルも予測します。

2番目のレイヤーでは、最初のレイヤーで予測された30%データの結果を新しい機能として直接使用してトレーニングを続行し、テストセットを使用してラベルの最初のレイヤーを特徴として予測し、モデルの2番目のレイヤーを使用してさらに予測します

利点は次のとおりです。

  • 1.スタッキングよりも簡単(スタッカーフィーチャーを取得するためにk回の相互検証が必要ないため)
  • 2.情報漏えいの問題を回避する:ジェネラライザとスタッカは異なるデータセットを使用します

欠点は次のとおりです。

  • 1.使用されるデータはほとんどありません(第2段階のブレンダーはトレーニングセット10%のみを使用します)
  • 2.ブレンダーがオーバーフィットする可能性があります
  • 3.複数の相互検証を使用したスタッキングはより堅牢になります ''
'''
Blending
'''
 
#创建训练的数据集
#创建训练的数据集
data_0 = iris.data
data = data_0[:100,:]

target_0 = iris.target
target = target_0[:100]
 
#模型融合中使用到的各个单模型
clfs = [LogisticRegression(solver='lbfgs'),
        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.3, random_state=2020)

#切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=2020)
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("Val auc Score of Blending: %f" % (roc_auc_score(y_predict, y_submission)))

Classified Stacking Fusion(mlxtendを使用)

!pip install mlxtend

import warnings
warnings.filterwarnings('ignore')
import itertools
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingClassifier

from sklearn.model_selection import cross_val_score
from mlxtend.plotting import plot_learning_curves
from mlxtend.plotting import plot_decision_regions

# 以python自带的鸢尾花数据集为例
iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target

clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], 
                          meta_classifier=lr)

label = ['KNN', 'Random Forest', 'Naive Bayes', 'Stacking Classifier']
clf_list = [clf1, clf2, clf3, sclf]

fig = plt.figure(figsize=(10,8))
gs = gridspec.GridSpec(2, 2)
grid = itertools.product([0,1],repeat=2)

clf_cv_mean = []
clf_cv_std = []
for clf, label, grd in zip(clf_list, label, grid):
        
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
    print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
    clf_cv_mean.append(scores.mean())
    clf_cv_std.append(scores.std())
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(label)

plt.show()

ベースモデルは「KNN」、「ランダムフォレスト」、「ナイーブベイズ」を使用し、セカンダリモデルと「LogisticRegression」に基づいて、モデルテストの効果が非常に改善されていることがわかります。

 

要約:

  • 1)結果レベルでの融合。これは最も一般的な融合方法であり、結果のスコアに基づく重み付け融合、logおよびexp処理など、実行可能な融合方法は数多くあります。結果の融合を行う際の重要な条件は、モデル結果のスコアが比較的類似していることと、結果の差が比較的大きいことです。このような結果の融合は、多くの場合より効果的です。

  • 2)機能レベルの融合。このレベルは、実際には融合とは呼ばれません。正確にセグメンテーションと呼ぶことができます。多くの場合、同じモデルのトレーニングを使用すると、機能を異なるモデルに分割して、後でモデルまたは結果の融合を実行できます。時にはそれはより良い結果を生み出すことができます。

  • 3)モデルレベルの融合。モデルレベルの融合には、ステーキングレイヤーの追加などのモデルのスタッキングと設計、および一部のモデルの結果を特徴の入力として使用することが含まれます。これらにはさらに実験と思考が必要であり、モデルレベルに基づく融合が最適です。異なるモデルタイプには特定の違いがあり、同じモデルの異なるパラメーターを使用する利点は一般に比較的小さいものです。

3.ブースティング/バギング(xgboost、Adaboost、GBDTですでに使用されています):

  • マルチツリーリフティング法

参考資料:

https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.15.1cd8593a4gdfJ6&postId=95535

 

21件のオリジナル記事を掲載 いいね1 訪問者1823

おすすめ

転載: blog.csdn.net/wjsjjss/article/details/105316332