Kaggleで学ぶ、モデルのブレンディングとスタッキング僕たちのKaggle挑戦記(2/2 ページ)

» 2021年12月02日 05時00分 公開
[一色政彦デジタルアドバンテージ]
前のページへ 1|2       

4日目(ランクアップせず):モデルスタッキング

 ブレンディングが理解できればスタッキングは理解できたも同然です。中間のLevelに複数のモデルを追加するだけだからです。順を追って見ていきましょう。

モデルスタッキングの構成について

 実装に入る前に、全体構成について示しておきます。

 ここでのスタッキングでは、「Level 0」と「Level 1」と「Level 2」の3層の構成になるように、以下の手順でモデルやデータセットを作成していきます。

  • Level 0層: ベースとなる、複数(今回は5つ)の機械学習モデルを作成
  • Level 0→1の間: ベースモデルによる予測結果から新たなデータセット(訓練/検証/テスト)を作成
  • Level 1層: 中間となる、複数(今回は3つ)のメタモデルを作成
  • Level 1→2の間: [Level 1]メタモデルによる予測結果から新たなデータセット(訓練/検証/テスト)を作成
  • Level 2層: 最終的な予測を行うための、1つのメタモデルを作成

 この構成と流れを図にすると、図7のようになります。

図7 3つのLevelを持つモデルスタッキングの構成図 図7 3つのLevelを持つモデルスタッキングの構成図

 それでは、Level 0層から実装していきましょう。

[Level 0]ベースとなる、複数の機械学習モデルを作る

 まずは、性能(=精度)が高くなりそうな機械学習の手法を用いて、ベースとなるモデルを複数作ります。筆者の場合は、先ほどのモデルブレンディングと同じ5つのベースモデルを使い回しました。

 1つのベースモデルの実装例は、前掲のリスト1に示したコードと全く同じになるため、説明は割愛します。

 ここまでで、Level 0層のベースモデルが準備できました。

[Level 0→1]予測結果から新たなデータセットを作る

 Level 1層のメタモデルを作る前に、そのモデルに入力するためのデータセットを作ります。このデータセットは、先ほど作成したベースモデルによる予測結果から作成します。

 この手順も、前掲のリスト2に示したコードと全く同じになるため、説明は割愛します。

[Level 1]中間となる、複数のメタモデルを作る

 次に、Level 1層に複数のメタモデルを作成します。筆者の場合は、以下の3つを作りました。

  • [Level 1]モデル1: XGBoost
  • [Level 1]モデル2: ランダムフォレスト
  • [Level 1]モデル3: 線形回帰

 いずれもこれまでの連載内容で作れるモデルです。

 機械学習モデルの構築はワンパターンなので、スタッキング[Level 1]メタモデルの実装であっても、前掲のリスト1とコード内容は大差ありません。違うのは、リスト1でXGBRegressorクラスを使っていた部分が、例えば下記のリスト5の太字部分ではscikit-learnのRandomForestRegressorというランダムフォレストのクラスを使用している点くらいです。

# [Level 1]メタモデル2: ランダムフォレスト
import numpy as np
import pandas as pd
from sklearn.preprocessing import OrdinalEncoder, StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.ensemble import RandomForestRegressor

# 事前にハイパーパラメーターのチューニングをしておく(参考:前掲のリスト3)
# params = study.best_params
params = {
  'n_estimators': 199,
  'min_samples_split': 20
  }

# 新しい「5分割済みの訓練&検証データ」と「テストデータ」のロード
# は、前掲のリスト2と同様のコードで実行済み。
# サンプルのSubmission用ファイルもロード
df_sample_submission = pd.read_csv('../input/30-days-of-ml/sample_submission.csv')

# 利用する特徴量の選択
useful_features = ['pred_1', 'pred_2', 'pred_3']

valid_scores = []  # 「検証データに対する評価スコア」を保存する変数
valid_predictions = {}  # 「検証データに対する予測結果」を保存する変数
test_predictions = []  # 「テストデータに対する予測結果」を保存する変数

for fold in range(5):
  X_train =  df_train[df_train.kfold != fold].reset_index(drop=True)
  X_valid = df_train[df_train.kfold == fold].reset_index(drop=True)
  X_test = df_test.copy()

  # 検証データのIDを保存しておく
  valid_ids = X_valid.id.values.tolist()

  y_train = X_train.target
  y_valid = X_valid.target

  X_train = X_train[useful_features]
  X_valid = X_valid[useful_features]
  X_test = X_test[useful_features]

  # ランダムフォレストモデルの訓練(fit)
  model = RandomForestRegressor(
    n_jobs=-1, # 全CPUを使う場合(scikit-learnはサポート範囲の広さを重視してGPUには非対応)
    criterion='mse',  # scikit-learn v1.0からは'squared_error'
    random_state=42,
    **params) # チューニング済みのハイパーパラメーターをセット
  model.fit(X_train, y_train)

  # 検証データをモデルに入力して予測する
  preds_valid = model.predict(X_valid)
  # 検証データのIDと、それに対する予測値をセットで、ループ外の変数に保存する
  valid_predictions.update(dict(zip(valid_ids, preds_valid)))
  # 「検証データに対する評価スコア」を取得してループ外の変数に保存し、スコアを出力
  score_valid = mean_squared_error(y_valid, preds_valid, squared=False)
  valid_scores.append(score_valid)
  print(fold, score_valid)
  # 出力例: 0 0.7249324634721162

  # 同様に、テストデータをモデルに入力して予測する
  preds_test = model.predict(X_test)
  # 予測結果をループ外の変数に保存
  test_predictions.append(preds_test)

# 5回分の「検証データによる評価スコア」を平均する
score_validation = np.mean(valid_scores)
print('score_validation:', score_validation)
# 出力例: score_validation: 0.7258260367801279

# 「検証データに対する予測結果」をCSVファイルに保存
valid_predictions = pd.DataFrame.from_dict(valid_predictions, orient='index').reset_index()
valid_predictions.columns = ['id', 'pred_2'# 列名を[id]と[pred_2]にする
valid_predictions.to_csv('valid_level1_preds2.csv', index=False)

# 5回分の「テストデータに対する予測結果」を平均し、それをCSVファイルに保存
X_sample_submission = df_sample_submission.copy()
X_sample_submission.target = np.mean(np.column_stack(test_predictions), axis=1)
X_sample_submission.columns = ['id', 'pred_2'# 列名を[id]と[pred_2]にする
X_sample_submission.to_csv('test_level1_preds2.csv', index=False)

リスト5 [Level 1]ランダムフォレストのモデルを作り、検証データとテストデータでの予測結果をCSVファイルに保存

 ランダムフォレストのハイパーパラメーターは事前にチューニングしておきました。なおXGBoostでは、ブースティング法の仕組み上、「決定木が先頭から順々に構築(build sequentially)されるので早期停止が適切」と前回説明しました。一方、(前々々回も名前だけ出したアンサンブル学習の)バギング法を用いたランダムフォレストは、「決定木が並列に構築(build parallel)されるのでチューニングが適切」です。よってリスト5でまずは、ハイパーパラメーターn_estimators(=構築する決定木の数)をOptunaで自動チューニングしておいたというわけです。

 リスト5では、併せてチューニングしたmin_samples_splitというパラメーターも使っています。ランダムフォレストには、その他、min_sample_leafmax_depthなどさまざまなパラメーターがあるので、必要に応じてそれぞれチューニングするとよいでしょう。

 本稿では、中間のレベルは[Level 1]の1つだけです。しかし中間のLevel層をもっと増やしていくことには、精度の向上は徐々に弱くなっていくものの多少の効果があるそうです(筆者は試しておらず、具体的なことは把握していません。参考:『Kaggleで勝つデータ分析の技術』)。

[Level 1→2]予測結果から新たなデータセットを作る

 Level 2層のメタモデルを作る前に、そのモデルに入力するためのデータセットを作ります。このデータセットは、先ほど作成した、Level 1層のメタモデルによる予測結果から作成します。

 先ほどの[Level 0→1]が、5つの「検証データに対する予測結果」と「テストデータに対する予測結果」からデータセットを作成したのに対し、今度は3つから作成します。それ以外は、前掲のリスト2と同じなので、説明は割愛します。

[Level 2]最終となる、1つのメタモデルを作る

 最後に、Level 2層のメタモデルを作成します。

 これも、リスト4のコードがほぼ使い回せます。使える特徴量が5個から3個に減るので、絞り込み用の変数の記述をuseful_features = ["pred_1", "pred_2", "pred_3"]のように書き換えるくらいしか違いはありません。

 以上が交差検証を用いたモデルスタッキングです。ブレンディングさえ理解しておけばスタッキングは同じ考え方で実装できることが分かったと思います。


 以上、今回の後編では、YouTube動画の5回目〜6回目で体験したことを説明しました。モデルのブレンディングやスタッキングもKaggleコンペでは外せないスキルだと思います。本稿がそのスキル習得のヒントになっているとうれしいです。

 さて本連載では、Kaggle主催の「“30 Days of ML”公式プログラム」をベースに、下記4本の記事を公開しました。

 後半の前中後編のベースとなっているYouTube動画を公開したAbhishek Thakur氏は(先ほども書籍名を出しましたが)、

を執筆されており、日本語版も販売されていますので、さらに学びたい方は手に取ってみてはいかがでしょうか。

 本連載の記事では、あっさりとした概要説明にとどまっているところが多々ありますが、Kaggleに取り組むための必須スキルのオーバービューにはなっているのではないかと思います。Kaggleなどのコンペにチャレンジする人のバイブル的な書籍である(先ほども書籍名を出しましたが)、

を初心者が読むと「ハードルが高い」と思われることも多いかと想像しますが、上記4本の記事を理解することで、かなりハードルが下がるのではないかと思います。ぜひ、上記4本を完全に理解するまで何度か読んでみてから、この書籍にチャレンジしてみてください。


一色

 『Kaggleで勝つデータ分析の技術』は持っていると、辞書的な使い方もできますし、Kaggleに取り組む際には手元に置いておくのがオススメです。



かわさき

 初心者が読むにはハードルが高くても読んでみないといけなさそうですね。というか、一色さんはほんとに初心者なのかしら(笑)。


 さて次回ですが、BERTやGPTといったところを試してはいるのですが、コンペに参加するほどの余裕がまだないので、コンペ参加の体験記事は数カ月後になりそうです。そこで、いったんTips的な情報を挟むことにして、ローカル環境のVisual Studio Codeを使ってKaggleコンペに参加した方法をまとめようかと思っています。お楽しみに。

「僕たちのKaggle挑戦記」のインデックス

僕たちのKaggle挑戦記

前のページへ 1|2       

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。