« 読了:Choi, Cha, & Tappert (2010) 二値類似性指標はたくさんあるので、その類似性を調べてみた | メイン | 読了:Trajman & Luiz (2008) 二つの診断基準の敏感度と特異度をMcNemar検定で比較する »
2018年5月 2日 (水)
大きなことから小さなことまで、悩みの種は尽きないが、そのなかには勉強不足に起因するとしかいいようがない問題もある。もっとも、勉強すりゃいいんだから、ある面では気楽である。
予測モデルの性能評価というのもそうした問題のひとつである。というわけで、数か月前に仕事を中断してメモをつくった。
以下はHastie, Tibshirani, Friedman「統計的学習の基礎」第7章「モデルの選択と評価」からのメモ。英語版なら無料なのに高価な訳書を買っちゃったので、せいぜい頑張ってモトをとらねばならぬ。
まずは損失関数loss functionの定義から。
目標変数を$Y$, 入力ベクトルを$X$、予測モデルを$\hat{f}(X)$、訓練データを$T$とする。訓練データにおける損失関数としては、$Y$が量的ないし間隔の場合は、
二乗誤差 $L(Y, \hat{f}(X)) = (Y - \hat{f}(X))^2$
絶対値誤差 $L(Y, \hat{f}(X)) = |Y-\hat{f}(X)|$
が用いられることが多い。$Y$が質的な場合は、水準数を$K$とし、モデルを$p_k(X) = Pr(Y=k|X)$、予測を$\hat{Y}(X) = argmax_k \hat{p}_k(X)$として、
0/1損失 $L(Y, \hat{Y}(X)) = I(Y = \hat{Y}(X))$
逸脱度 $L(G, \hat{p}(X)) = -2 \sum_k^K I(Y=k) \log \hat{p}_k(X)$
が使われることが多い。確率密度に関する損失関数としては
対数尤度 $L(Y, \theta(X)) = -2 \log Pr_{\theta(X)}(Y)$
が用いられる。
標本における損失の平均
$\bar{err} = (1/N) \sum_i^N L(y_i, \hat{F}(x_i))$
を訓練誤差training errorという。
いっぽうテスト誤差test error(=汎化誤差 generalization error)は
$Err_T = E[L(Y, \hat{f}(X)) | T]$
として定義される。その期待値、すなわち訓練データのランダム性を含むすべてのランダム性についての平均
$Err = E[L(Y, \hat{f}(X))]$
を期待テスト誤差 (期待予測誤差) という。ほんとにやりたいことは、手元の$T$についての$Err_T$の推定なんだけど、実際には$Err$を推定するわけである。
モデルに対する期待テスト誤差は、モデルが含んでいるパラメータ$\alpha$まで含めて $Err = E[L(Y, \hat{f}_\alpha(X))]$
と書くべきところだが、以下では略記する。
さて、(期待)テスト誤差を最小にするモデルを選ぶにはどうしたらよいか(モデル選択)。また、最終的なモデルの(期待)テスト誤差を推定するにはどうしたらよいか(モデル評価)。というのがここからのテーマである。
もしもデータが十分にあるならば、データを訓練集合、確認集合、テスト集合に分割するのがよい。確認集合はモデル選択に使い、テスト集合は最終的な(期待)テスト誤差の推定だけに使う。理想のサイズは一概にいえないが、たとえば50:25:25という感じ。
もっとも、データはふつう十分ではないので、なにかと大変なのである。
ここでちょっと脇道にそれて、バイアス-分散分解について。
$Y=f(X)+e, E(e)=0, Var(e)=\sigma_e^2$と仮定しよう。$f(X)$は回帰だとして、2乗誤差損失を採用しよう。入力点$X=x_0$における$f(X)$の期待テスト誤差は
$Err(x_0)$
$= E[(Y-\hat{f}(x_0))^2|X=x_0]$
$= [E\hat{f}(x_0)-f(x_o)]^2 + E[\hat{f}(x_0)-E\hat{f}(x_0)]^2 + \sigma_e^2$
と分解できる。第1項がバイアスの二乗、第2項が分散を表す。
もっともこれは二乗誤差損失の場合の話。バイアス-分散トレードオフの挙動は、損失をどう定義するかで変わってくる。
テスト誤差をもう一度きちんと定義しよう。
データの同時分布から生成された新しいテストデータ点$(X^0 ,Y^0)$におけるモデル$\hat{f}$のテスト誤差を
$Err_T = E_{X^0, Y^0}[L(Y^0, \hat{f}(X^0)) | T]$
とする。期待テスト誤差は、これを訓練集合$T$について平均した値
$Err = E_T E_{X^0, Y^0}[L(Y^0, \hat{f}(X^0)) | T]$
である。
ご存知のように、訓練誤差
$\bar{err} = (1/N) \sum_i^N L(y_i, \hat{F}(x_i))$
はテスト誤差の推定値としては楽観的である。
いま、訓練入力点$x_1, \ldots, x_N$に対して新しい応答変数$Y^0$が与えられたとしよう。
$Err_{in} = (1/N) E_{Y^0}[L(Y^0, \hat{f}(X^0)) | T]$
を訓練標本内誤差in-sample errorと呼ぶことにする。これ自体に関心はないんだけど(だってテスト入力点は訓練入力点とは異なるから)、話の都合上これを考えるわけである。
$\bar{err}$は$Err_{in}$に対してもなお楽観的である。そこで最善度optimismを
$op \equiv Err_{in} - \bar{err}$
と定義する。で、訓練集合上での予測変数のほうは固定して、出力変数にたいして期待値をとり[←ここの発想がややこしい...]
$\omega \equiv E_y(op)$
と定義する。
すると、幅広い損失関数について一般に
$\omega = (2/N) \sum_i^N Cov(\hat{y}_i, y_i)$
が成り立つ。つまり、$y_i$が予測値に強く効いているとき、$\bar{err}$はより楽観的なわけだ。
さて、話を戻して... (期待)テスト誤差をどうやって推定するか。路線がふたつある。
ひとつの路線は、どうにかして最善度$\omega$を推定するというもの。それを訓練誤差$\bar{err}$に乗せてやれば、すくなくとも訓練標本内誤差$Err_{in}$は推定できるわけで、モデル間の相対的な比較はできるわけである。
では、$\omega$を具体的にどうやって推定するか。
単純なケースとして、$\hat{y}_i$が$d$次元の線形フィッティングで得られている場合を考えよう。$Y=f(X)+e$において$\sum_i^N Cov(\hat{y}_i, y_i) = d \sigma_e^2$だから、
$\omega = 2 \cdot (d/N)\sigma_e^2$
ここから得られるのが$C_p$統計量
$C_p = \bar{err} + 2 \cdot (d/N) \sigma_e^2$
である。
これをもっと一般的にしたのがAICで...[ここから、AIC, 有効パラメータ数、BIC, MDL, VC次元の話が続くんだけど、ちょっと時間がないのでパス]
もうひとつの路線は、$Err$そのものを直接に推定しようというものである。
この路線としては、まずは交差確認(CV)が挙げられる。
推定対象について誤解しないように。leave-one-out(LOO)とかだとついつい$Err_{T}$を推定しているような気がしちゃうけど、あくまで$Err$を推定してるんだからね。
K-fold CVの$K$をどう決めるか。$K=N$の場合(つまりLOOの場合)、$N$個の訓練集合は互いに似ているから、気が付かないけど分散が大きくなる。いっぽう$K$が小さいと、訓練曲線によっては$Err$を過大評価するかもしれない。折衷案として5とか10とかを推奨する。
CVでは「1SE」ルールが用いられることが多い。これは、最良モデルの誤差とSEを求め、最良モデルより1SE以内のモデルのなかでもっとも簡素なモデルを選ぶというルール。
[ここで一般化CVの話。パス]
予測変数がたくさんある分類問題で、(1)予測変数を相関とかで絞り込み、(2)それらで分類器を組み、(3)CVでパラメータを推定して最終モデルにする、というやりかたをとる場合がある。これはよくある間違い。最初の選別が教師無しである場合を例外として、とにかく最初から標本を抜くのがポイント。(1)標本をKグループにわけ、(2)各群について、それを抜いた全群で予測変数簿を絞り込み分類器を組み立て、その群でテストする、というのが正しいやりかた。
分類誤差を最小にするような1変数を選ぶという場面を考える(こういうのをstumpという)。「すべての訓練集合に対してあてはめを行うと、データをとてもよく分ける予測変数をひとつみつけることになる。よってCVでは誤差を正確に推定できない」...これも間違い。CVの繰り返しのたびにモデルを完全に再学習しないといけないということを忘れている。
もうひとつはブートストラップ法。訓練集合から同じサイズの標本集合を復元抽出で取り出す。これをB回繰り返す。B個の標本のそれぞれから任意の量を求める。B個の値の分布を調べる。
予測誤差の推定という文脈ですぐに思いつくのが、各ブートストラップ標本にモデルをあてはめて、予測値$\hat{f}^{*b}(x_i)$を得て、
$\hat{Err}_{boot} = (1/B)(1/N)\sum_b^B \sum_i^N L(y_i, \hat{f}^{*b}(x_i))$
を得るというのがひとつのアプローチ。しかしこれは$Err$の良い推定値ではない。訓練集合とテスト集合が分かれていないから。
そうではなくて、個々の観察値について、それを含まないブートストラップ標本だけを使って予測値を得る、というのが正しい。観測値$i$を含まないブートストラップ標本の集合を$C^{-i}$, そのサイズを$|C^{-i}|$として
$\hat{Err}^{(1)} = (1/N) \sum_i (1/|C^{-i}|)\sum_{b \in C^{-1}} L(y_i, \hat{f}^{*b}(x_i))$
とするわけである。これがLOOブートストラップ誤差である。
ところが、CVの場合と同じく、訓練集合が小さくなったことに寄るバイアスが生じる。
バイアスの大きさはどのくらいか。ある観測値$i$があるブートストラップ標本$b$に含まれる確率は$1-(1-(1/N))^N$。およそ0.632である。つまり、それぞれのブートストラップ標本における「異なり観測値」の数は、平均しておよそ$0.632N$。これはCVでいえば$K=2$の場合に相当する。だから、訓練曲線の傾きが$N/2$のあたりでまだ大きいようであれば、LOOブートストラップ標本による推定は過大になる。
バイアスを修正するにはどうすればよいか。ふたつのアイデアがある。
その1,0.632推定量。
$\hat{Err}^{(0.632)} = 0.368 \bar{err} + 0.632 \hat{Err}^{(1)}$
となる[この導出は面倒らしい]。この推定量は過学習のことを全然考えていない。
その2,0.632+推定量。まず、$y_i$と$x_{i'}$の全ての組み合わせを通じて
$\hat{\gamma} = (1/N^2) \sum_i \sum_{i'} L(y_i, \hat{f}(x_{i'}))$
を求め、
$\hat{R} = (\hat{Err}^{(1)} - \bar{err}) / (\hat{\gamma} - \bar{err})$
を求める。これを相対過学習率と呼ぶ。で、
$\hat{\omega} = 0.632 / (1-0.368 \hat{R})$
$\hat{Err}^{(0.632+)} = (1-\hat{\omega}) \bar{err} + \hat{\omega} \hat{Err}^{(1)}$
を求める。なぜなら...[ちゃんと丁寧に説明されているのだが、ここで力尽き、頭が停止した。いずれまた気力のあるときに...]
最後に、CVで得た期待テスト誤差$Err$の推定は、我々が本当に知りたい対象であるテスト誤差$Err_T$の推定になっているか、という問題。
実験してみるとわかるんだけど[...中略...]、意外にうまくいかない。訓練集合$T$に対するテスト誤差の推定は、同じ訓練集合からのデータだけではわからない。
嗚呼... いろいろ勉強不足を痛感する次第である。LOOブートストラップってそういう意味だったのか。
いや、勉強不足なのはまだよい。本当の問題は、このトシになって勉強してても無駄なんじゃないかという絶望感がひたひたと押し寄せてくる、という点である。辛いなあ。
雑記:データ解析 - 覚え書き:教師あり学習モデルの評価方法