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 教師付き学習による母平均モデルの推定
手持ちのデータと同じ母集団から新しくランダムサンプリングされ、\(X\)のみが観察できるサンプルについて\(Y\)の値を予測する。
- データ分割を用いたモデル選択、評価を行う
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を実装
5.2.0.1 パッケージ & データ
ここではpipelinesによるデータ整備は行わない (暫定的)
追加でlgr (表示するメッセージを操作), future (並列計算) パッケージを使用
5.2.0.2 推定タスクの定義
分割数、繰り返し計算回数は最小限に設定
- 実戦では増やす
5.2.0.3 使用するBuildIn Algorithmを定義
5.2.0.4 PreProcess
線形モデルについて、連続変数二乗項と交差項を導入
- Duflo のおすすめ
1= po("mutate")
Mutate
2$param_set$values$mutation = list(
MutateSize2 = ~ 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
)
3= po("scale")
Scale
4<- Mutate %>>%
OLS %>>%
Scale lrn("regr.lm") |>
as_learner()
$id <- "OLS" OLS
- 1
- \(X\) の加工
- 2
- 二乗項と交差項を作成
- 3
- 標準化(平均を引き、標準偏差で叙す)
- 4
- OLSと結合
5.2.0.5 チューニング付き推定方法の定義
Tree、ElasticNet (LASSO/Ridge) アルゴリズムについて、HyperParameterを交差検証により推定する
探索するHyperParameterの範囲を設定する必要がある
- mlr3tuningspacesパッケージが提供するおすすめ範囲を使用
<- lrn("regr.rpart") |>
Tree 1lts()
2<- AutoTuner$new(
Tree learner = Tree,
resampling = CV,
measure = R2,
terminator = Terminal,
tuner = Tuner
)
3$id <- "Tree"
Tree
<- lrn("regr.glmnet") |>
RegulizedLinear 4lts()
<- Mutate %>>%
RegulizedLinear %>>%
Scale |>
RegulizedLinear 5as_learner()
6<- AutoTuner$new(
RegulizedLinear learner = RegulizedLinear,
resampling = CV,
measure = R2,
terminator = Terminal,
tuner = Tuner
)
7$id <- "ElasticNet" RegulizedLinear
- 1
- TuningSpaceを指定したTreeを定義
- 2
- HyperParameter Tuningを指定
- 3
- Treeと名づける
- 4
- TuningSpaceを指定したElasticNetを定義
- 5
- 二乗項/交差項作成を付与
- 6
- HyperParameter Tuningを指定
- 7
- ElasticNetと名づける
5.2.0.6 SuperLearnerの定義
1<- list(
BaseLearner
OLS,
RandomForest,
Tree,
RegulizedLinear
)
2<- lrn(
SuperLearner "regr.lm",
id = "SuperLearner")
3<- pipeline_stacking(
Stacking
BaseLearner,
SuperLearner,use_features = FALSE) |>
as_learner()
4$id <- "Stacking" Stacking
- 1
- 個別のアルゴリズムの指定
- 2
- 集計用アルゴリズムの指定
- 3
- Stackingの定義
- 4
- Stackingと名づけ
5.2.0.7 交差推定による評価
1<- benchmark_grid(
Design 2tasks = Task,
3learners = list(
OLS,
SimpleOLS,
RegulizedLinear,
RandomForest,
Tree,
Stacking
),4resamplings = CV
)
5::get_logger("mlr3")$set_threshold("error")
lgr::get_logger("bbotk")$set_threshold("error")
lgr6::plan("multisession")
future
7<- benchmark(Design)
BenchMark
8$aggregate(R2) BenchMark
- 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
= pd.read_csv("ExampleData/Example.csv")
data
123) # Fix seed
np.random.seed(
= data['Price']
Y
= data.drop(
X 'Price',
= 1) axis
5.2.0.9 使用するアルゴリズム
= linear_model.LinearRegression() # OLS
OLS
= RandomForestRegressor(
RF = 500) # Random Forest n_estimators
5.2.0.10 交差推定によるテスト
= KFold(n_splits=5, shuffle = True) # サンプル5分割 Folds
- OLS のテスト
= Folds)) np.mean(cross_val_score(OLS, X, Y, cv
0.45701534421807366
- Random Forestのテスト
= Folds)) np.mean(cross_val_score(RF, X, Y, cv
0.5162822824693902