Lassoの技法のひとつである安定性選択とランダム化された安定性選択があるが、これらの方法は結果がスパースになるという問題がある。
要は、選ばれる変数が少なく、とてもスリムにモデルになってしまうという問題である。
- Kissel, N., & Mentch, L. (2024). Forward stability and model path selection. Statistics and Computing, 34(2), 82. https://doi.org/10.1007/s11222-024-10395-8
Forward Stability
Forward Stabilityの計算手順は以下の通りである。まず、データセットを複数のサブセットに分割し、各サブセットに対してモデルをフィッティングし、変数選択を行う。その後、各変数の選択頻度を計算し、一定の閾値を超えた変数を最終モデルに含める。このメカニズムは、サブセット抽出を繰り返すことで安定した変数選択を実現する。良い点は選択の安定性を高め、高次元データに対しても効果的である点だ。一方、悪い点は計算コストが高く、適切な閾値の設定が難しい場合があることである。
Model Path Selection
Model Path Selectionの計算手順は、初期モデルを選択し、一段階ずつ変数を追加し、各ステップで最適な変数を選択する。追加した変数によって構築されたモデルパスを保存し、指定されたモデルサイズに達するまでこれを繰り返す。このメカニズムは前進選択法に基づき、逐次的にモデルを構築し、モデルパスを生成するものである。良い点は構造的に類似した複数のモデルを生成し、モデル選択の不確実性を可視化できる点と、直感的なグラフ表示が可能な点である。一方、悪い点は計算コストが非常に高く、過剰適合のリスクがあることである。
パッケージのインストール
devtools::install_github(repo='nkissel/MPS', subdir='ModelPath')
データの読み込み
library(haven) library(tidyr) auto_data <- haven::read_dta("http://www.stata-press.com/data/r9/auto.dta") auto_data <- subset(auto_data, select = -make) # makeを削除 auto_data <- auto_data %>% drop_na() # 全カラムに対してNAがない行を抽出 auto_data$foreign <- as.integer(auto_data$foreign) auto_data <- as.data.frame(auto_data)
Forward Stability
library(ModelPath) mps_fs <- full.select.gen(myframe = auto_data, resp.name = 'price', depth = 3, r = 100, model = 'lm', condense = FALSE) print(mps_fs) build.tree(mps_fs) # グラフのプロット
結果。
[,1] [1,] "displacement" [2,] "mpg" [,1] [,2] [,3] [1,] "displacement" "foreign" "weight" [2,] "displacement" "foreign" "mpg" [3,] "mpg" "displacement" "foreign"
Model Path Selection (MPS)
mps_mps <- full.select.gen(myframe = auto_data, resp.name = 'price', depth = 3, r = 100, model = 'lm', condense = TRUE) print(mps_mps) build.tree(mps_mps) # グラフのプロット
結果。
[,1] [1,] "displacement" [2,] "mpg" [,1] [,2] [,3] [1,] "displacement" "foreign" "weight" [2,] "displacement" "foreign" "mpg"
反復回数(r)
rの数字はリサンプリングを100回実行することを意味する。リサンプリングは、安定性の評価、変数選択の一貫性、計算の頑健性に影響する。
depth
モデルの階層数を指定する。階層数を増やすと変数間の相互作用や依存関係についてより多くの情報が得られるが、計算コストが増加したり、モデルの複雑性の増加したりする。したがって、 安定性と解釈性のトレードオフを考慮して、適切な階層数を選択する必要がある。下記でdepth = 4のForward Stabilityを実行する。
library(ModelPath) mps_fs_f4 <- full.select.gen(myframe = auto_data, resp.name = 'price', depth = 4, r = 100, model = 'lm', condense = FALSE) print(mps_fs_f4) build.tree(mps_fs_f4) # グラフのプロット
[,1] [1,] "displacement" [2,] "mpg" [,1] [,2] [,3] [,4] [1,] "displacement" "foreign" "weight" "length" [2,] "displacement" "foreign" "mpg" "weight" [3,] "mpg" "displacement" "foreign" "weight" [4,] "mpg" "foreign" "weight" "length" [5,] "mpg" "foreign" "weight" "displacement" [6,] "mpg" "foreign" "weight" "gear_ratio" [7,] "mpg" "foreign" "weight" "turn" [8,] "mpg" "foreign" "displacement" "weight"
depthが増えると変数の関係性はわかりやすくなっているが、"gear_ratio"と"turn"が増えている。 どちらのモデルを望むかは分析者の選択に拠る。