スタッキングの精度保証について考える

記事をご覧いただきありがとうございます！

感想やご指摘があればコﾒﾝﾄいただけると幸いです！

（この記事は英語の発音記号（特にアクセント）を意識してカタカナを書いてあります。例としては 
　アクセント　→ アｸｾﾝﾄ （ˈəksɛnt）
　コメント　→ コﾒﾝﾄ （ˈkɑmɛnt）
などです。）

# 0. 問題設定

教師あり学習を考えます. つまり以下のような設定です:
『$D=(x,y)^{n}\in{(\mathbb{R}^{d_x}\times\mathbb{R}^{d_y})} ^n\in\mathbb{D}$が与えられた際,
　$x$から$y$を予測する学習機を作りたい.』

近年では,様々な学習機(モﾃﾞﾙ)があり,
勾配ブｰｽﾃｨﾝｸﾞ木,深層学習,ﾊﾟラﾐﾀｰが小さめの統計モﾃﾞﾙなどがあります.

この記事ではそれらの詳細には触れませんが,
精度を上げるためのｽタｯｷﾝｸﾞという技術の精度保証について考察していきます.

# 1. ｽタｯｷﾝｸﾞ (ˈstækɪŋ)

ｽタｯｷﾝｸﾞとは,
複数のモﾃﾞﾙ(m個)の出力値を入力値として別のモﾃﾞﾙ (ミﾀ・モﾃﾞﾙ)で再度学習して予測する技術のことです.

イﾐｼﾞとしては以下の通りです:

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/729ffbd5-1f01-6a5e-3c56-50e0db8b6ca6.png  width="500"/>

(上記の水色の矢印は0である場合も多いと思います.ただ,人間社会の会議や意思決定では水色を入れて考えることが一般的な気がします.)

この手法はとても良く機能しますが,実装や理論を少し間違えるとデｲﾀ・リ-ｹｼﾞ(ˈdeɪtə ˈlikəʤ)が起きてしいまい,正しい精度保障ができなくなってしまいます.

そのため,この記事では,精度保証とデｲﾀ・リ-ｹｼﾞに注目してｽタｯｷﾝｸﾞを紹介します.

精度保証とは,現在$D$に含まれていないデｲﾀに対しても当てはまりをよくするということです.それを保証する量としてしばしば使われるのが,汎化誤差です.

# 2. 汎化誤差 (ˌʤɛnrəlɪˈzeɪʃən ˈɛrər)

汎化誤差とは,様々な定義の仕方がありますが,真のデｲﾀの分布に対して当てはまりの良さの数値として定義されます(分布のKL情報量から算出する方法やある損失関数に関する期待値に関して計算する方法など).

今回は,ある損失関数($L(y,y)$)の期待値として定義します.デｲﾀ$D$が与えられた際の学習機$f$の損失関数は以下で定義されます:

$$
G(f,D)=\mathbb{E}_{(x,y)}[L(f(x|D),y)].
$$

ここで注意したいのが,
- $D$に関する期待値は取らない(A)
- $(x,y)$の分布は未知(B)

ということです.

上記のことからk フォｳﾙﾄﾞ・ｸロｽ・ｳﾞｧﾘデｲｼｮﾝという指標を汎化誤差の代わりに用いることが多いです.

# 3. k フォｳﾙﾄﾞ・ｸロｽ・ｳﾞｧﾘデｲｼｮﾝ (krɔs - ˌvæləˈdeɪʃən)

k-ｸロｽ・ｳﾞｧﾘデｲｼｮﾝとはデｲﾀ$D$を$k$個に分割して汎化誤差を近似的に見積もる手法です.
分割の仕方($cv$)は様々ありますが,総じて以下のように定義されます:

```math
\begin{align}
CV(f,D,cv,k)=\frac{1}{k}\sum^{k}_{i=1}\frac{1}{|cv(D,i,{\rm valid})|}\sum_{(x,y)\in cv(D,i,{\rm valid})}L(f(x|cv(D,i,{\rm train})),y).
\end{align}
```

ここで,$cv:\mathbb{D}\times Int \times Str \rightarrow \mathbb{D}$として分割を与える関数です.イﾐｼﾞとしては以下の通りです:

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/d2240581-35fe-8f9a-bb10-f5f2e22e169d.png  width="500"/>

これが汎化誤差を近似した値と言える根拠は,validに対して(cvを考慮して)期待値を取ると汎化誤差に一致するためです(*):

```math
\begin{align}
\tilde{\mathbb{E}_{{\rm valid}}}[CV(f,D,cv,k)]=\frac{1}{k}\sum^{k}_{i=1}G(f,cv(D,i,train)).
\end{align}
```

(*:一部,学習機ではearly stoppingやtarget encodingなどの手法を用いる関係上,多少のvalidationのdata leakageを許容する考えもあり,現実社会では厳密に期待値を取っても一致しない状況が多いと考えられます.)

ここで注意したいのが,
汎化誤差の際にも言及した(A)の$f(x|D)$の$D$に対して期待値を取らないことにあります.

逆に言えば,$f$の条件付きパラメータ（f(・|×××)のxxxの部分）に期待値を取るデｲﾀを含めてはならないということです.

これに注意してｽタｯｷﾝｸﾞを考えます.

# 4. ｽタｯｷﾝｸﾞにおけるcvを考える 

ｽタｯｷﾝｸﾞにおけるcvでは以下の二つのケースを私は考えました:

- それぞれのモﾃﾞﾙでcvをして実装をした後,最後にそれらをｽタｯｷﾝｸﾞをする(I).
- ｽタｯｷﾝｸﾞまでをcvをする(II).

イﾐｼﾞとしては以下の通りです（以下のtrainやvalidはその部分データに対応する出力値が入っていると考えてます）:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/60668895-90bf-ab48-a5ce-caa085753ac2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/e3bd4315-03c7-5ba7-c6db-e5dbb0dce3d7.png)

さて,どちらが数学的にｽタｯｷﾝｸﾞの精度保証を行うことができるでしょうか.

まず,IIが正しいことは直ちにわかります.
というのも,new validに対して期待値を取ろうとしてもその情報が学習機の学習に用いられていないためです.

しかし,Iは正しくありません.

というのも,Iにおけるnew validに対して期待を取ろうとすると,ｽタｯｷﾝｸﾞ前のcv(2,3,4)でそれらのvalidのデｲﾀを元に学習を行なっているからです.つまり,期待値を取ろうとすると,うまく計算できないことがわかります.

よって,ｽタｯｷﾝｸﾞの実装で精度を保証するにはIIの方法を用いる必要があります.

## 4.1. 実際は...?

しかし,実用上はどうでしょうか.

直感的には,Iでも上手くいく気もしますが,私には良くわかりません...(今度実装して公開できそうなら別途記事にいたします)
 
森脇 大輔ら,『Kaggleで勝つデータ分析の技術』,技術評論社(2019)([amazon link](https://www.amazon.co.jp/dp/4297108437))のp362を読む限りでは手法IIに似た手法では『学習データについては「目的変数を知っている」予測値になってしまい、テストデータについては「目的変数を知らない」予測値になっているので、学習データとテストデータで意味が違う特徴量となってしま』うため,精度は出ないと紹介されており,p364では,手法Iの実装がされているように思えました.

そのため,先ほど私が指摘した点については,無視できると考えられるのだと思います.というのも,data leakageをある程度許容する手法は様々あり(early stoppingなど)今回の話はそれに含まれてくる話で,精度のためには仕方のないことのように思えるからです.

この辺りの実装や経験値,および私の考えに誤りに考えられそうな部分があれば,コﾒﾝﾄお願いいたします🙇‍♂️


# 5. 新規デｲﾀへの実装を考える

## IIの場合
今までの工程でk*(m+1)個の小さなモﾃﾞﾙができました.

そのためミﾀ・モﾃﾞﾙを含めたk個の枠組み(1つあたりm+1のモデルを使用)をとり,
最終的に平均を取ることが一般的であると考えられます:

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/1a075da1-3022-e136-5e37-3a7ae84f90d7.png width="500"/>

## I の場合
今までの工程で(m+1) x (k)個のモﾃﾞﾙができました.

実用的には,それぞれモﾃﾞﾙの平均(k個)を取ってから,
m次元の1つの特徴量を作成し,
k個のミﾀ・モﾃﾞﾙを回して平均を取ることが考えられます:


<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/c9da3d79-88ff-f996-020f-1a075ad79cfe.png width="500"/>


# ˈkɑləm 1 : 別の視点の精度保証

ある$x$に対して,モﾃﾞﾙ1~mまで全てが全くベクトル的にも正反対の結論をしていたら,あまり決定的な結論を採択したくないかもしれません([イラストや](https://www.irasutoya.com/2013/02/blog-post_9122.html)から花の画像を引用):

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/6074059f-fe34-b5fe-4224-7fd04fd30c58.png  width="300"/>

上記の例では,
そもそもモﾃﾞﾙ一つ一つが明らかに学習不足であると考えられますが,ひとひとつの精度が良いと想定されている場合は非常に難しい課題である可能性があります.

Kaggleなどでは精度を競うためこちらは気にしなくて良いかもしれませんが,学習機を社会実装するとなると,一つの反例が命取りになる場合もあるため,この辺りには,注意していきたいと個人的には感じています.

# 最後に

記事をご覧いただきありがとうございます！

感想やご指摘があればコﾒﾝﾄいただけると幸いです！

LGTMやｽトｯｸも ﾓﾁベｲｼｮﾝにつながるため,よろしければお願いいたします🙇‍♂️

# 参考文献

門脇 大輔, 阪田 隆司, 保坂 桂佑, 平松 雄司『Kaggleで勝つデータ分析の技術』,技術評論社(2019)([amazon link](https://www.amazon.co.jp/dp/4297108437))