機械学習
記事内に商品プロモーションを含む場合があります

多数決アンサンブル分類器(VotingClassifier)の使った精度向上テクニック

Aru

機械学習では、予測精度を向上させるために複数の予測モデルを組み合わせるアンサンブル手法が有効です。自力でアンサンブルのコードを作成しても良いですが、ライブラリがあるのならそちらを利用した方が効率的です。この記事では、scikit-learnの「多数決アンサンブル分類器(VotingClassifier)」を使って、複数のモデルを統合する方法について解説します。

VotingClassfierとは

VotingClassifierは、scikit-learnライブラリに含まれるアンサンブル学習の手法の一つです。アンサンブル学習は、複数の機械学習モデルを組み合わせて、単一のモデルよりも優れた性能を達成することを目的としています。

VotingClassifierでは、複数の分類器(クラス分類器)の予測結果を組み合わせ、最終的な予測を決定します。具体的には、異なる種類の分類器(例: ロジスティック回帰、決定木、ランダムフォレストなど)を用意し、各分類機の結果投票によって予測結果を決定します。

VotingClassifierでは、主に以下の2つの方法で投票を行います

  • ハード
    各分類器の予測の多数決による投票
  • ソフト
    各分類器のクラス確率の平均を計算し、最も確率の高いクラスを選択

この記事では、VotingClassifierの使い方を、具体例を交えて解説します。

VotingClassifierの使い方を、実際に動作するコードで確認していきます。

Votingclassfierの使い方①

データセット(iris)

利用するデータセットは、おなじみのscikit-learnのirisデータセットです。

このデータセットを使って、花びら(petal)/がく片(sepal)の長さと幅(cm)という4つの特徴量から、あやめの種類(setosa, versicolor, virginicaの3種類)を予測します。

まずは、load_iris()でデータを読み込んで、訓練データ(train)とテストデータ(test)に分けます。

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

iris = load_iris()

X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25)

KNNで予測

1つ目の予測器はKNN(k近傍法)にしました。KNNはscikit-learnで用意されているものを利用します。

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier()
knn.fit(X_train, y_train)

y_pred1 = knn.predict(X_test)
print(y_pred1)
# [0 2 0 1 0 1 0 2 1 2 2 2 1 1 0 2 2 1 1 0 2 1 2 1 0 0 1 2 1 2 0 1 0 2 1 2 0 1]

SVCで予測

2つ目の予測器はSVM(サポートベクターマシン)です。こちらもscikit-learnで用意されているものを利用します。probability=Trueのオプションは、VotingClassifierでsoftを使う場合に必要になるため設定しています。

from sklearn.svm import SVC
svc = SVC(probability=True)
svc.fit(X_train, y_train)

y_pred2 = svc.predict(X_test)
print(y_pred2)
# [0 2 0 1 0 1 0 2 1 2 2 2 1 1 0 2 2 1 1 0 2 1 2 1 0 0 1 2 1 2 0 1 0 2 1 2 0 1]

LightGBMで予測

3つ目はkaggleなどでもよく利用されているLightGBMです。ここでは、scikit-learnの形式のインタフェースを利用しています。

import lightgbm as lgb
lgbm = lgb.LGBMClassifier(verbose=-1)
lgbm.fit(X_train, y_train)
y_pred3 = lgbm.predict(X_test)
print(y_pred3)
# [0 2 0 1 0 1 0 2 1 2 2 2 1 1 0 2 2 1 1 0 2 1 2 1 0 0 1 2 1 2 0 1 0 2 1 2 0 1]

予測精度を確認

3つの予測器の予測精度を表示してみます。

# 3つの結果を表示
print(accuracy_score(y_test, y_pred1))
print(accuracy_score(y_test, y_pred2))
print(accuracy_score(y_test, y_pred3))

題材の問題か、予測精度は全ての予測機で同じでした。

予測結果がばらつかないとアンサンブルが面白くないかも

0.9473684210526315
0.9473684210526315
0.9473684210526315

VotingClassifierで予測

3つの予測器を用意しましたので、VotingClassifierで3つの予測器を使って予測してみます。

使い方

VotingClassifierでは、estimatorsパラメータで予測機の(名前と予測器)のリストを渡します。VotingClassifierの主な引数は以下になります。

VotingClassifierの主な引数
引数名説明
estimators分類器を設定するパラメータ。[('name', model), …]のように分類器の名前と分類器のオブジェクトのペアをリスト形式で渡します
voting投票方法を設定するパラメータ。hardの場合は多数決。softの場合は、書く予測器の予測値(確率)の平均をとって、最も確率が高いクラスを返します
weights各予測機の重みのリスト
n_jobs並列実行の数。-1を設定した場合はすべてのプロセッサを利用
verboseverboseのon/off

後の使い方は、他の分類器と同じfit()predict()の順で呼び出します。

VotingClassifier(HARD)で予測

voting='hard'で予測した結果です。3つの予測器の結果が同じなので、投票結果も同じです。

from sklearn.ensemble import VotingClassifier

voting_classifier = VotingClassifier(estimators=[('knn', knn), ('lgb', lgbm), ('svc', svc)], voting='hard')

voting_classifier.fit(X_train, y_train)

y_pred = voting_classifier.predict(X_test)

print(y_pred)
print(accuracy_score(y_test, y_pred))
[0 2 0 1 0 1 0 2 1 2 2 2 1 1 0 2 2 1 1 0 2 1 2 1 0 0 1 2 1 2 0 1 0 2 1 2 0 1]
0.9473684210526315

VotingClassifier(SOFT)で予測

voting='hard'で予測した結果です。こちらも同じ結果になりました。

from sklearn.ensemble import VotingClassifier

voting_classifier = VotingClassifier(estimators=[('knn', knn), ('lgb', lgbm), ('svc', svc)], voting='soft')

voting_classifier.fit(X_train, y_train)

y_pred = voting_classifier.predict(X_test)

print(y_pred)
print(accuracy_score(y_test, y_pred))

[0 2 0 1 0 1 0 2 1 2 2 2 1 1 0 2 2 1 1 0 2 1 2 1 0 0 1 2 1 2 0 1 0 2 1 2 0 1] 0.9473684210526315

Votingclassfierの使い方②

irisデータの結果が面白くなかったので、別のデータセットでVotingClassifierを試してみます。今回は、データセットをmake_classificationを使って生成します。

make_classificationを使ってデータセットを作成

scikit-learnのmake_classification関数を使うと、「ランダムな n クラス分類問題」を生成することができます。ここでは、これを使ってデータセットを作ってVotingClassificationの動作を確認してみます。

あわせて読みたい
scikit-learnで機械学習用データセットを自動生成する方法【初級 深層学習講座】
scikit-learnで機械学習用データセットを自動生成する方法【初級 深層学習講座】

使い方

使い方は簡単です。以下のように呼び出すだけで、データXとラベルyを作成してくれます。データポイントはガウス分布に従い生成されるため、実際に分類問題のサンプルとして利用することができます。

今回は、この擬似データを使って分類を試します。

X, y = make_classification(n_samples=1000, n_features=20, random_state=1234)

この関数の引数は以下になります(一部省略しています)。

make_classificationの代表的な引数
引数内容
n_samplesサンプル数
n_features特徴量の数
n_informative目的変数のラベルと相関が強い特徴量の数
random_state乱数のシード

VotingClassifier(2クラス分類)サンプル

make_classificationで2クラスのデータセットを作成して予測を行ってみます。

ここでは、XGBoost, LightGBM, KNNの3つを組み合わせています。

LightGBMとXGBoostはどちらもブースティングなので、アンサンブルするには向かないかもしれませんが、私が頻繁に利用しているのでサンプルに組み入れました。

from sklearn.ensemble import VotingClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

from sklearn.neighbors import KNeighborsClassifier
import lightgbm as lgb
from xgboost import XGBClassifier

# lgbm = lgb.LGBMClassifier(verbose=-1)

# サンプルデータの生成
#   n_samples	サンプル数
#   n_features	特徴量の数
#   n_informative	目的変数のラベルと相関が強い特徴量の数
X, y = make_classification(n_samples=1000, n_features=20, random_state=42, n_informative=12)

# モデルの定義
model1 = XGBClassifier()
model2 = lgb.LGBMClassifier(verbose=-1)
model3 = KNeighborsClassifier()

# 投票分類器の構築
voting_classifier = VotingClassifier(estimators=[('xgb', model1), ('lgb', model2), ('knn', model3)], voting='hard')

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model1.fit(X_train, y_train)
model2.fit(X_train, y_train)
model3.fit(X_train, y_train)
voting_classifier.fit(X_train, y_train)

# 予測
y_pred1 = model1.predict(X_test)
y_pred2 = model2.predict(X_test)
y_pred3 = model3.predict(X_test)
y_pred = voting_classifier.predict(X_test)


# 精度の評価
accuracy1 = accuracy_score(y_test, y_pred1)
accuracy2 = accuracy_score(y_test, y_pred2)
accuracy3 = accuracy_score(y_test, y_pred3)
accuracy = accuracy_score(y_test, y_pred)

print(f'Accuracy1: {accuracy1}')
print(f'Accuracy2: {accuracy2}')
print(f'Accuracy3: {accuracy3}')

print(f'Voting Accuracy: {accuracy}')

結果は、それぞれの予測器単体より、投票した結果が良くなっています(期待通りの結果となりました)。

Accuracy1: 0.935
Accuracy2: 0.935
Accuracy3: 0.93
Voting Accuracy: 0.94

VotingClassifier(5クラス分類)サンプル

同様に5クラスのデータセットを作成して予測してみました。プログラム的にはほぼ同じです。

from sklearn.ensemble import VotingClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

from sklearn.neighbors import KNeighborsClassifier
import lightgbm as lgb
from xgboost import XGBClassifier



# サンプルデータの生成
X, y = make_classification(n_samples=1000, n_features=20, random_state=42,  n_classes=5, n_informative=12)

# モデルの定義
model1 = XGBClassifier()
model2 = lgb.LGBMClassifier(verbose=-1)
model3 = KNeighborsClassifier()

# 投票分類器の構築
voting_classifier = VotingClassifier(estimators=[('xgb', model1), ('lgb', model2), ('knn', model3)], voting='hard')

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの訓練
model1.fit(X_train, y_train)
model2.fit(X_train, y_train)
model3.fit(X_train, y_train)
voting_classifier.fit(X_train, y_train)

# 予測
y_pred1 = model1.predict(X_test)
y_pred2 = model2.predict(X_test)
y_pred3 = model3.predict(X_test)
y_pred = voting_classifier.predict(X_test)


# 精度の評価
accuracy1 = accuracy_score(y_test, y_pred1)
accuracy2 = accuracy_score(y_test, y_pred2)
accuracy3 = accuracy_score(y_test, y_pred3)
accuracy = accuracy_score(y_test, y_pred)

print(f'Accuracy1: {accuracy1}')
print(f'Accuracy2: {accuracy2}')
print(f'Accuracy3: {accuracy3}')

print(f'Voting Accuracy: {accuracy}')

こちらも、個別の予測器よりも良い結果を得ることができました。

Accuracy1: 0.78
Accuracy2: 0.74
Accuracy3: 0.78
Voting Accuracy: 0.795

データセットによっては、単体の方がよい結果を出すこともありました。常にVotingの方が良い結果になるわけではないので、評価実験が必要です。

まとめ

scikit-learnのVotingClassifierについて解説しました。簡単にアンサンブルできるので、複数の予測器の結果を組み合わせるのに使ってみてはどうでしょうか。

特徴量エンジニアリングなどの手法については以下の記事を参考にしてください

機械学習のための前処理&特徴量エンジニアリングの手法【Python】
機械学習のための前処理&特徴量エンジニアリングの手法【Python】

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ABOUT ME
ある/Aru
ある/Aru
IT&機械学習エンジニア/ファイナンシャルプランナー(CFP®)
専門分野は並列処理・画像処理・機械学習・ディープラーニング。プログラミング言語はC, C++, Go, Pythonを中心として色々利用。現在は、Kaggle, 競プロなどをしながら悠々自適に活動中
記事URLをコピーしました