sсikit-learnのVotingClassifier:分類モデルのアンサンブルの構築と最適化

センチメント分析(レビュー分析)の大きなタスクの実装の一部として、その別個の要素の追加研究に時間を割くことに決めました-sklearn.ensembleモジュールのVotingClassifierを分類モデルのアンサンブルを構築し、予測の最終品質を改善するためのツールとして使用します。 なぜこれが重要で、ニュアンスは何ですか?







データ分析の適用された問題を解決する過程で、どのトレーニングモデルが最適であるかがすぐに明らかではない(またはまったく明らかではない)ことがよくあります。 1つの解決策は、利用可能なデータの性質に基づいて、最も人気のあるモデルおよび/または直感的に適切なモデルを選択することです。 この場合、選択されたモデルのパラメーターは最適化され(GridSearchCVなどを使用)、作業で使用されます。 別のアプローチは、複数のモデルの結果が最終結果の形成に同時に関与している場合に、モデルのアンサンブルを使用することです。 この記事の目的は、モデルのアンサンブルまたはその構築の原則を使用することの利点を説明することではなく(これはここにあります )、特定の例を使用して問題を解決し、そのようなソリューション中に発生するニュアンスを分析するための個別に適用されたアプローチの1つです。



グローバルな問題の声明は次のとおりです:携帯電話でテストサンプルとして与えられたのは100件のレビューのみであり、これら100件のレビューで最良の結果を示す事前トレーニングモデルが必要です。つまり、レビューが肯定的か否定的かを判断します。 問題の条件からわかるように、追加の難しさはトレーニングサンプルの不足です。 Beautiful Soupライブラリの助けを借りてこの困難を克服するために、ロシアのサイトの1つからの携帯電話に関する10,000件のレビューと評価が成功しました。



解析、データの前処理、および初期構造の調査の段階をスキップして、次の時点に進みます。





どのモデルがあなたに最適であるかを決定する方法は? モデルを手動で反復する機能はありません。 100件のレビューのみのテストサンプルは、一部のモデルがこのテストサンプルに単に適しているという大きなリスクをもたらしますが、私たちから隠された追加のサンプルまたは「バトル」で使用すると、結果は平均以下になります。



この問題を解決するために、Scikit-learnライブラリーにはVotingClassifierモジュールがあります 。これは、互いに異なる複数の機械学習モデルを使用し、それらを1つの分類器に結合するための優れたツールです。 これにより、個々のモデルの結果が誤って解釈されるだけでなく、再トレーニングのリスクが軽減されます。 VotingClassifierモジュールは、次のコマンドでインポートされます

from sklearn.ensemble import VotingClassifier







このモジュールを使用する際の実用的な詳細:



1)最初の最も重要なことは、結合された分類器の個々の予測が、それに含まれる各モデルから予測を受け取った後にどのように取得されるかです。 VotingClassifierパラメーターには、「hard」と「soft」の2つの可能な値を持つ投票パラメーターがあります。



1.1)最初のケースでは、共同分類子の最終回答は、そのメンバーの過半数の「意見」に対応します。 たとえば、組み合わせた分類器は3つの異なるモデルのデータを使用します。 特定の観測に関するそれらのうちの2つは応答「正のフィードバック」を予測し、3つ目は「負のフィードバック」を予測します。 したがって、この観測では、2つの「for」と1つの「against」があるため、最終的な予測は「正のフィードバック」になります。



1.2)2番目の場合、つまり 投票パラメータの「ソフト」値を使用すると、 クラスのモデル予測の本格的な「投票」と重み付けが行われるため、結合された分類器の最終的な答えは、予測確率の合計のargmaxです。 重要! このような「投票」メソッドを使用できるようにするには、アンサンブルの分類子がpredict_proba()メソッドをサポートして、各クラスでの発生確率の定量的推定値を取得する必要があります。 すべての分類子モデルがこのメソッドをサポートしているわけではないことに注意してください。したがって、加重確率のメソッド(ソフト投票)を使用する場合、VotingClassifierのフレームワーク内で使用できます。



例を見てみましょう 。3つの分類子と2つのクラスのレビューがあります:ポジティブとネガティブです。 各分類子は、predict_probaメソッドを介して、特定の確率値(p)を提供します。特定の観測値は、それによってクラス1に割り当てられ、したがって、確率(1-p)でクラス2に割り当てられます。 結合された分類器は、各モデルから回答を受け取った後、得られた推定値の重み付けを実行し、次のように得られた最終結果を与えます。

$$ディスプレイ$$ max(w1 * p1 + w2 * p1 + w3 * p1、w1 * p2 + w2 * p2 + w3 * p3)$$ディスプレイ$$





、ここで、w1、w2、w3はアンサンブルに含まれる分類器の重みであり、デフォルトでは等しい重みを持ち、p1、p2はそれぞれのクラス1またはクラス2に属することの評価です。 また、ソフト投票を使用する場合の分類子の重みは、weightsパラメーターを使用して変更できるため、モジュール呼び出しは次のようになります。

... = VotingClassifier(estimators=[('..', clf1), ('..', clf2), ('...', clf3)], voting='soft', weights=[*,*,*])



、アスタリスクは各モデルに必要な重みを示す場合があります。



2)モジュールVotingClassifierとGridSearchを同時に使用して、アンサンブルに含まれる各分類子のハイパーパラメーターを最適化する機能。



アンサンブルを使用する予定で、それに含まれるモデルを最適化する場合は、統合分類器で既にGridSearchを使用できます。 そして、以下のコードは、統合された分類器(VotingClassifier)のフレームワーク内に留まりながら、それに含まれるモデル(ロジスティック回帰、単純ベイズ、確率的勾配降下)を使用する方法を示しています。



 clf1 = LogisticRegression() clf2 = MultinomialNB() clf3 = SGDClassifier(max_iter=1000, loss='log') eclf = VotingClassifier(estimators=[ ('lr', clf1), ('nb', clf2),('sgd', clf3)], voting='hard') #      (hard voting), . . 1.1 <b>params = {'lr__C' : [0.5,1,1.5], 'lr__class_weight': [None,'balanced'], 'nb__alpha' : [0.1,1,2], 'sgd__penalty' : ['l2', 'l1'], 'sgd__alpha': [0.0001,0.001,0.01]} </b> #       ,  ,     grid = GridSearchCV(estimator=eclf, param_grid=params, cv=5, scoring='accuracy', n_jobs=-1) grid = grid.fit(data_messages_vectorized, df_texts['Binary_Rate']) #    ,      5     
      
      





したがって、GridSearchを介してアクセスするときに、モデルのアンサンブル内のどのパラメーターが最適化する値を持つパラメーターを参照するかを判断できるように、params辞書を設定する必要があります。



VotingClassifierツールをモデルのアンサンブルを構築して最適化する方法として完全に使用するために知っておく必要があるのはそれだけです。 結果を見てみましょう:



  print grid.best_params_ {'lr__class_weight': 'balanced', 'sgd__penalty': 'l1', 'nb__alpha': 1, 'lr__C': 1, 'sgd__alpha': 0.001}
      
      





パラメーターの最適な値が見つかりました。分類器のアンサンブル(VotingClassifier)の作業結果を最適なパラメーターと比較し、トレーニングサンプルを交差検証し、モデルを最適なパラメーターとそれらで構成されるアンサンブルと比較します。



 for clf, label in zip([clf1, clf2, clf3, eclf], ['Logistic Regression', 'Naive Bayes', 'SGD', 'Ensemble_HardVoting']): scores = cross_val_score(clf, data_messages_vectorized, df_texts['Binary_Rate'], cv=3, scoring='accuracy') print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
      
      





最終結果:



精度:0.75(±0.02)[ロジスティック回帰]

精度:0.79(±0.02)[単純ベイズ]

精度:0.79(±0.02)[SGD]

精度:0.79(±0.02)[Ensemble_HardVoting]



ご覧のとおり、トレーニングサンプルではモデルの表示が多少異なります(標準パラメーターでは、この違いはより顕著でした)。 さらに、アンサンブルの合計値(精度メトリックによる)は、アンサンブルに含まれるモデルの最適値を超える必要はありません。 アンサンブルはかなり安定したモデルであり、テストセットと「戦闘」で±同様の結果を示すことができます。つまり、再トレーニング、トレーニングセットへの適合、およびトレーニングに関連するその他の問題分類子のリスクを減らします。 適用された問題を解決するのに頑張ってください、あなたの注意をありがとう!



PSサンドボックスでの公開の詳細と規則を考えると、テストセットとそのモデルをチェックするためのツールを提供したInClassコンペティションのフレームワークで、この記事で提供されている分析用のgithubとソースコードへのリンク、およびKaggleへのリンクを提供することはできません。 このアンサンブルがベースラインを大幅に上回り、テストセットをチェックした後、リーダーボードで正当な位置を占めたとしか言えません。 私が共有できる次の出版物で願っています。



All Articles