機械学習を1ヵ月で実践レベルにする #10 (正則化)

# 10日目
[Coursera でStanford が提供しているMachine Learning](https://www.coursera.org/learn/machine-learning/) ですが、今日も順調にWEEK 9 を終えました。

## 過去記事一覧
* [1日目 とっかかり編](http://qiita.com/junichiro/items/ee50af10df77d52cd432)
* [2日目 オンライン講座](http://qiita.com/junichiro/items/7a5b95d7122176e94fe0)
* [3日目 Octave チュートリアル](http://qiita.com/junichiro/items/33954f08411e33d33506)
* [4日目 機械学習の第一歩、線形回帰から](http://qiita.com/junichiro/items/d4dc67bdebb9fccb7ef5)
* [5日目 線形回帰をOctave で実装する](http://qiita.com/junichiro/items/1a4b87e99b471cf5bea1)
* [6日目 Octave によるVectorial implementation](http://qiita.com/junichiro/items/7972b1b6ad3d087fbde0)
* [7日目 ロジスティック回帰 (分類問題) その1](http://qiita.com/junichiro/items/8de94c84c35e9851d42a)
* [8日目 ロジスティック回帰 (分類問題) その2](http://qiita.com/junichiro/items/5d20a40a3a282af422a3)
* [9日目 オーバーフィッティング](http://qiita.com/junichiro/items/4d2c91128c9bd850f580)
* [10日目 正則化](http://qiita.com/junichiro/items/8b1867201663c5af38a4)
* [11日目 ニューラルネットワーク #1] (http://qiita.com/junichiro/items/7794cedf834a4f6ef52c)
* [12日目 ニューラルネットワーク #2] (http://qiita.com/junichiro/items/b522ea41c02f90d23aa5)
* [13日目 機械学習に必要な最急降下法の実装に必要な知識まとめ](http://qiita.com/junichiro/items/527b1f211ed814528ded)
* [14日目 機械学習で精度が出ない時にやることまとめ](http://qiita.com/junichiro/items/7e2842c7afba2407c49b)
* [最終日 機械学習をゼロから1ヵ月間勉強し続けた結果](http://qiita.com/junichiro/items/3457e33e502086a200f1)

# 正則化
昨日、オーバーフィッティングの問題の例を見ましたが、今日はオーバーフィッティングを是正する、正則化についての話です。

## 正則化についての僕の考え
僕は個人的に、この正則化ってやつは機械学習の肝のひとつだと思っています。例えば最急降下法は、式は難しくても内容としては「予測と実測の差を小さくする方法」というように直感的にわかりやすいです。しかし正則化はこれらに比べると直感的な理解が得にくいです。それにも関わらず、また、一見重要性も理解しにくい割に、実際にはとても重要であるからです。

あとのほうの講座でも正則化にはたびたび触れることになりますので、ここでしっかり理解しておかないと後がきつくなります。

## 考え方
もう一度、ジャストフィットした例と、オーバーフィッティングした例を見てみます。

![overFitting2.png](https://qiita-image-store.s3.amazonaws.com/0/121876/2a8730fa-0a73-dbf0-bc6b-cb6083f4c514.png)![overFitting3.png](https://qiita-image-store.s3.amazonaws.com/0/121876/3a3c013d-55df-6e7a-dd18-bb8d1efe2cf6.png)

右のグラフを左のようなグラフの形状に近づけるのが目的で、それこそが正則化です。
いま、左のグラフは、その形状から類推すると、おそらく2次くらいの関数なので次のような式で表すことができるかと思います。

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/ed5fedbc-574c-8a49-6003-40fcee5ac63d.png)

次に右のグラフですが、こちらは左に比べて複雑なのでおそらく高次の項があり、それは例えば4次くらいの関数であり、次のような式で表すことができます。

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/b9fb93a8-dcd1-ddbc-be75-b199b1cd2da1.png)

この2つの式を比べるとわかると思いますが、右(下)のグラフの式の高次の項の影響が少なくなれば、左(上)のグラフ(の式)に近づきます。これを踏まえた上で、もう一度、コスト関数を最小化することに立ち返ってみます。

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/2df75e57-d6d5-bcc5-91ea-6cc254bbc3f6.png)

技巧的ですが、ここに高次の項のペナルティを課してみます。

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/66071f8d-7140-4b89-f020-a2a6890281b7.png)

そうすると、最急降下法などで上記のコストを最小にするためのθを選ぼうとすると、必然的にθ3やθ4は0に近い小さい数字となります。その結果、右のグラフはより左のグラフに近づきます。いまのように掛ける数字を大きくすると、θ３やθ4は小さくなり、右のグラフに近づき、掛ける数字を小さくすると、右のオーバーフィットしたグラフになることがわかります。

これを一般化して正則化項を導入したコスト関数は以下のようになります。

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/a5f5d369-0646-8cfd-3d37-0c1a0de404fc.png)

追加された第2項が正則化のための項です。これで、λ を調整することで適合度を、オーバーフィッティングしないようにコントロールできるようになります。

* オーバーフィットしている場合 -> λ を大きくしてグラフを滑らかにする
* アンダーフィットしている場合 -> λ を小さくしてグラフをもう少し複雑にする

# 正則化項付きの最急降下法
コスト関数

![image](https://qiita-image-store.s3.amazonaws.com/0/121876/91b78454-e82e-7150-74d9-6cb9a196f645.png)
(正則化は切片項のθ0には適用しないため、ｊ = 1 からの和をとります)

最急降下法はやはり偏微分です。

Repeat {
![image](https://qiita-image-store.s3.amazonaws.com/0/121876/a6a13f30-2349-a8f5-d20a-7649c30f2ffe.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/121876/32030f19-e66f-b5da-d912-e5e63f9786be.png)
(j=1, 2, 3, ..., n)
}

# 正則化あり線形回帰のoctave 実装

*2018/03/07 に修正しました。*

コスト関数

```octave
hx = X * theta;
cost = hx - y;
theta = [0; theta(2:end, :)];
J = ((cost' * cost) + lambda * (theta' * theta)) / (2 * m);
```

最急降下法の偏微分項

```octave
grad = (X' * cost + lambda * theta) / m;
```

あとはこれを計算ライブラリに渡せばモデルを得られます。

*2018/03/07 の修正ここまで。*

## 正則化ありロジスティック回帰のoctave 実装

```octave
J = -1/m * sum(y .* log(sigmoid(X * theta)) + (1 - y) .* log(1 - sigmoid(X * theta))) + lambda / 2 /m * sum(theta(2:end,:).^2);
```

最急降下法の偏微分項

```octave
grad = 1/m * (X' * (sigmoid(X * theta) - y)) + lambda / m * [0 ; theta(2:size(theta), :)];;
```

以上。

最適なλやαを決定する話はまた機会があればします。