アンサンブル学習:たくさんのモデルで多数決をとる
1人より、みんなで決めた方が当たることがある
クイズ番組で、1人の答えより、会場の多くの人の多数決の方がよく当たる、という話を聞いたことがあるかもしれません。機械学習でも、たくさんのモデルの予測を組み合わせると、1つのモデルより正確になることがよくあります。これを アンサンブル学習 と呼びます。
計算してみる:正解率0.7のモデルを集めて、多数決をとる
正解率0.7のモデルがいくつかあり、それぞれのモデルの間違いが、互いに関係なく(独立に)起こる とします。多数決が正解になる確率は、第10章の二項分布で計算できます(半分より多くのモデルが正解すれば、多数決は正解)。
各モデルが0.7なら、数を増やすほど多数決の正解率は1に近づきます。一方、各モデルが0.45(当て推量の0.5より悪い)だと、数を増やすほど多数決は 悪く なります。多数決で強くなるには、次の2つが必要です。
- 1つ1つのモデルが、当て推量よりは当たる
- モデルどうしの間違い方が、ばらばら(同じところで同じように間違えるなら、何個集めても1個と同じ)
実際のモデルは、同じデータで学習すると同じような間違い方をしやすいので、表のようにはうまくいきません。そこで、わざとモデルごとに違いを作る 工夫をします。
バギング:データを少しずつ変えて、たくさん学習させる
訓練データから、重複を許して データをでたらめに選び、元と同じ数の「少し違う訓練データ」をたくさん作ります(1つのデータが2回選ばれたり、1回も選ばれなかったりする)。この選び方を ブートストラップ と呼びます。それぞれの訓練データでモデルを1つずつ学習させ、予測は多数決(回帰なら平均)で決めます。この方法を バギング と呼びます。
ランダムフォレスト:決定木のバギング + 特徴量もでたらめに
ランダムフォレスト は、決定木(第5章)をバギングで集めたものです。さらに、木が分かれ道の質問を選ぶときに、すべての特徴量ではなく、でたらめに選んだ一部の特徴量の中から 選びます。こうすると、木どうしがさらに違った形になり、間違い方がばらばらになります。
決定木は、訓練データの小さな違いで形が大きく変わる(バリアンスが大きい、第8章)モデルです。この「不安定さ」が、アンサンブルでは、ばらばらな間違い方として役に立ちます。
実験:ランダムフォレストと、ブースティング
弱い木を集めると、強い森になる
手書き数字のデータ(テストデータ3割)で、決定木1本とランダムフォレストを比べました。
森の中の木は、ブートストラップで選んだデータと、でたらめに選んだ特徴量だけで作られるので、1本ずつではふつうの決定木(0.857)より 弱く、平均0.743しかありません。それでも、100本の多数決では0.978になりました。1本ずつの強さより、「間違い方がばらばら」であることが効いているのです。
データの分け方を5通りに変えても、決定木1本は0.839〜0.859、ランダムフォレストは0.957〜0.978で、いつも森の方が大きく上回りました。
ブースティング:前のモデルの間違いを、次のモデルが直す
バギングは、たくさんのモデルを それぞれ独立に 作りました。ブースティング は、モデルを 1つずつ順番に 作り、新しいモデルに「それまでのモデルが間違えたところ」を重点的に学習させます。
- AdaBoost: 間違えたデータの重みを大きくして、次のモデルがそのデータを重視するようにする
- 勾配ブースティング: それまでのモデルの予測と正解との「ずれ」(損失の勾配)を、次の木が予測するように学習させ、少しずつ足していく。第4章の勾配降下法を、「木を1本ずつ足す」形で行っているとも言える
- ランダムフォレスト
- 勾配ブースティング
- 決定木1本(0.857)
木の数(横軸、1〜100本)と、手書き数字のテストデータの正解率(縦軸)。ランダムフォレストは、1本で0.741、10本で0.943、100本で0.978と、木を増やすほど上がる。勾配ブースティングは、1本で0.778、10本で0.874、50本で0.941、100本で0.950と、ゆっくり上がる。どちらも10本前後で、決定木1本(0.857、水平な線)を上回る
ランダムフォレストは、木を増やしても過学習しにくく(300本で0.980)、増やすほど安定します。勾配ブースティングは、順番に間違いを直していくので、木を増やすほど訓練データに合わせていきます。このデータでは100本で0.950でしたが、ほかのハイパーパラメータ(1本の木の深さ、1本ずつ足す量を決める学習率など)の調整で、大きく変わります。
勾配ブースティングは、表の形のデータ(売り上げ、顧客の情報など)で特に強く、データ分析のコンテストで上位を占めることが多い手法です。高速に学習できるように工夫したライブラリ(XGBoost、LightGBM など)が広く使われています。
Pythonでアンサンブルを使う、よくある誤解と振り返り
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
forest = RandomForestClassifier(n_estimators=100, random_state=0) # 木の数100本
forest.fit(X_train, y_train)
print(forest.score(X_test, y_test)) # 手書き数字 → 0.978
boost = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=0)
boost.fit(X_train, y_train)
print(boost.score(X_test, y_test)) # 手書き数字 → 0.950
n_estimators は木の数です。ランダムフォレストは、多いほど安定します(時間はかかります)
- ブートストラップや特徴量の選び方に乱数を使うので、第9章のとおり
random_state を決めておきます
- 決定木を使うので、標準化は必要ありません(「いくつ以上か」で分けるだけなので、値の大きさの違いに左右されない)
- ランダムフォレストの
feature_importances_ で、どの特徴量が分かれ道によく使われたか(不純度をどれだけ減らしたか)が分かります。第9章の並べ替えによる重要度と同じく、似た特徴量があると重要度が分かれることに注意します
よくある誤解
- 「モデルをたくさん集めれば、必ず強くなる」: 当て推量より悪いモデルを集めると、多数決はかえって悪くなります(0.45のモデル101個で0.156)。また、同じ間違い方をするモデルをいくら集めても、よくなりません
- 「ランダムフォレストの木は、1本ずつでも強い」: 1本ずつの正解率は平均0.743で、ふつうの決定木(0.857)より弱いのです。強さは、多数決から生まれます
- 「バギングとブースティングは同じ」: バギングはモデルを独立に作って、主にばらつき(バリアンス)を減らします。ブースティングは順番に作って前の間違いを直し、主に大まかすぎる誤り(バイアス)を減らします
振り返り
- アンサンブル学習は、複数のモデルの予測を多数決(回帰なら平均)でまとめる。1つ1つが当て推量より当たり、間違い方がばらばらなほど効く
- バギングは、ブートストラップで作った少し違う訓練データで、モデルを独立に学習させる。ランダムフォレストは、決定木のバギングに、特徴量のでたらめな選択を加えたもの
- ブースティングは、前のモデルの間違いを次のモデルが直すように、順番にモデルを足していく(AdaBoost、勾配ブースティング)