5  教師付き学習による母平均モデルの推定

5.1 問題設定

  • 母平均関数 \(E[Y|X]\) を近似する関数 \(f(X)\) の推定をする。具体的には、母集団上での二乗誤差最小化を目指す。

\[\min_{f(X)} E[(E[Y|X]-f(X))^2]\]

  • 上記の最適化問題の解を近似する関数 \(f(X)\) は、標準的な予測問題において極めて有益である。

  • 上記問題を具体的に解くアルゴリズムとして、ここでは OLS, ElasticNet, Random Forest、およびそれらのStacking (SuperLearner) を実装する。

5.1.1 予測問題

  • 事前に定義する損失関数の母平均 (Population Risk) を最小化するような、予測関数\(f(X)\)の推定を目指す。

    • 以下ではMean squared error(MSE)を損失関数として用いる。確率変数\(Y,X\)について予測問題は以下のように定義できる

\[\min_{f(X)}MSE = \int_{x}E[(Y-f(x))^2|X_i=x]\times g(x)dx\]

  • \(g(x)\)\(x\)の分布関数

    • 一般に以下の最適化問題の解と一致

\[\min_{f(X_i)} \int_{x}E[(E[Y|X]-f(x))^2|X_i=x]g(x)dx\]

  • 理想の予測モデルは、 \(f(X)=E[Y|X]\)

    • \(E[Y|X]\) を十分に近似する関数を推定できれば、最善に近い予測性能を期待できる

5.2 実装

  • 以下のPipelineを実装

flowchart TB
  A[データとパッケージの読み込み] --> B[予測タスクの定義/サンプル分割]
  B --> C1[BuildIn 推定アルゴリズムの定義]
  B --> C2[+ 前処理]
  B --> C3[+ パラメータTuning]
  C1 --> C4[Super Learnerの定義]
  C2 --> C4[Super Learnerの定義]
  C3 --> C4[Super Learnerの定義]
  C1 --> D[Trainデータのみを用いたベンチマーク]
  C2 --> D[Trainデータのみを用いたベンチマーク]
  C3 --> D[Trainデータのみを用いたベンチマーク]
  C4 --> D[Trainデータのみを用いたベンチマーク]
  D --> E[最善の予測モデルを用いた最終推計]
  E --> F[Testデータによる評価]

5.2.0.1 パッケージ & データ

  • ここではpipelinesによるデータ整備は行わない (暫定的)

  • 追加でlgr (表示するメッセージを操作), future (並列計算) パッケージを使用

library(tidyverse)
1library(mlr3verse)
2library(mlr3pipelines)

Raw <- read_csv("ExampleData/Example.csv")

set.seed(123)
1
教師付き学習のメタパッケージ
2
Stacking用

5.2.0.2 推定タスクの定義

  • 分割数、繰り返し計算回数は最小限に設定

    • 実戦では増やす
Task <- as_task_regr(
  Raw, 
  target = "Price",
1  id = "Price")

2R2 <-  msr("regr.rsq")

3CV <- rsmp("cv",folds = 2)

Terminal = trm(
  "evals",
4  n_evals = 20)

5Tuner <- tnr("random_search")
1
推定に用いるデータと結果変数を指定
2
R2を評価指標に使用
3
2分割交差検証を指定
4
20個のパラメタセットを検証
5
ランダムサーチで検証するパラメタセットを選ぶ

5.2.0.3 使用するBuildIn Algorithmを定義

1SimpleOLS <- lrn(
  "regr.lm",
  id = "SimpleOLS"
  )

2RandomForest <- lrn(
  "regr.ranger",
  id = "RandomForest"
  )
1
単純なOLS
2
RandomForest

5.2.0.4 PreProcess

  • 線形モデルについて、連続変数二乗項と交差項を導入

1Mutate = po("mutate")

2Mutate$param_set$values$mutation = list(
  Size2 = ~ Size*Size,
  TradeQ2 = ~ TradeQ*TradeQ,
  BuildYear2 = ~BuildYear*BuildYear,
  Distance2 = ~Distance*Distance,
  Size_TradeQ = ~Size*TradeQ,
  Size_BuildYear = ~Size*BuildYear,
  Size_Distance = ~ Size*Distance,
  TradeQ_BuildYear = ~TradeQ*BuildYear,
  TradeQ_Distance = ~TradeQ*Distance,
  BuildYear_Distance = ~BuildYear*Distance
  )

3Scale = po("scale")

4OLS <- Mutate %>>%
  Scale %>>%
  lrn("regr.lm") |>
  as_learner()

OLS$id <- "OLS"
1
\(X\) の加工
2
二乗項と交差項を作成
3
標準化(平均を引き、標準偏差で叙す)
4
OLSと結合

5.2.0.5 チューニング付き推定方法の定義

  • Tree、ElasticNet (LASSO/Ridge) アルゴリズムについて、HyperParameterを交差検証により推定する

  • 探索するHyperParameterの範囲を設定する必要がある

Tree <- lrn("regr.rpart") |> 
1  lts()

2Tree <- AutoTuner$new(
  learner = Tree,
  resampling = CV,
  measure = R2,
  terminator = Terminal,
  tuner = Tuner
  )

3Tree$id <- "Tree"

RegulizedLinear <- lrn("regr.glmnet") |> 
4  lts()

RegulizedLinear <- Mutate %>>% 
  Scale %>>% 
  RegulizedLinear |> 
5  as_learner()

6RegulizedLinear <- AutoTuner$new(
  learner = RegulizedLinear,
  resampling = CV,
  measure = R2,
  terminator = Terminal,
  tuner = Tuner
  )

7RegulizedLinear$id <- "ElasticNet"
1
TuningSpaceを指定したTreeを定義
2
HyperParameter Tuningを指定
3
Treeと名づける
4
TuningSpaceを指定したElasticNetを定義
5
二乗項/交差項作成を付与
6
HyperParameter Tuningを指定
7
ElasticNetと名づける

5.2.0.6 SuperLearnerの定義

1BaseLearner <- list(
  OLS,
  RandomForest,
  Tree,
  RegulizedLinear
  )

2SuperLearner <- lrn(
  "regr.lm",
  id = "SuperLearner")

3Stacking <- pipeline_stacking(
  BaseLearner,
  SuperLearner,
  use_features = FALSE) |>
  as_learner()

4Stacking$id <- "Stacking"
1
個別のアルゴリズムの指定
2
集計用アルゴリズムの指定
3
Stackingの定義
4
Stackingと名づけ

5.2.0.7 交差推定による評価

1Design <- benchmark_grid(
2  tasks = Task,
3  learners = list(
    OLS,
    SimpleOLS,
    RegulizedLinear,
    RandomForest,
    Tree,
    Stacking
  ),
4  resamplings = CV
  )

5lgr::get_logger("mlr3")$set_threshold("error")
lgr::get_logger("bbotk")$set_threshold("error")
6future::plan("multisession")

7BenchMark <- benchmark(Design)

8BenchMark$aggregate(R2)
1
評価の枠組みを定義
2
評価対象のタスク (データと結果変数) を定義
3
評価対象のアルゴリズムを定義
4
評価方法 (交差検証) を定義
5
Errorメッセージのみ表示
6
並列処理を指定
7
評価を実行
8
R2を計算
   nr task_id   learner_id resampling_id iters  regr.rsq
1:  1   Price          OLS            cv     2 0.4806426
2:  2   Price    SimpleOLS            cv     2 0.4372492
3:  3   Price   ElasticNet            cv     2 0.4574927
4:  4   Price RandomForest            cv     2 0.5012793
5:  5   Price         Tree            cv     2 0.4668550
6:  6   Price     Stacking            cv     2 0.5078875
Hidden columns: resample_result
  • RandomForestとStackingはComparableな性能
  • OLSとRandom Forestで予測モデルを推定し、交差検証で比較する。

5.2.0.8 パッケージ & データ

from sklearn import linear_model
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
import pandas as pd
import numpy as np

data = pd.read_csv("ExampleData/Example.csv")

np.random.seed(123) # Fix seed

Y = data['Price']

X = data.drop(
  'Price',
  axis = 1)

5.2.0.9 使用するアルゴリズム

OLS = linear_model.LinearRegression() # OLS

RF = RandomForestRegressor(
  n_estimators = 500) # Random Forest

5.2.0.10 交差推定によるテスト

Folds = KFold(n_splits=5, shuffle = True) # サンプル5分割
  • OLS のテスト
np.mean(cross_val_score(OLS, X, Y, cv = Folds))
0.45701534421807366
  • Random Forestのテスト
np.mean(cross_val_score(RF, X, Y, cv = Folds))
0.5162822824693902