Coursera Machine Learningのまとめ(線形回帰編)

# はじめに
初学者向けの入門としてあまりにも有名なCourseraのMachine learning コースの勉強を始めたので、線形回帰についてまとめてみる。

[※Courseraの機械学習コース](https://www.coursera.org/learn/machine-learning)

# 線形回帰とは
ものすごくざっくりとした理解としては、ある変数と予測したい値に相関関係がある時に、変数から予測値を直線のグラフに当てはめて推測しようという試み。

例えばこんな感じ。
実データの各点から直線を予想して作ってやろうというイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633548/cd9a9b86-4265-a078-6247-15af47cec493.png)


$x$を説明変数や特徴量と呼び、$y$を目的変数と呼ぶ。

上記のグラフの例だと、

* $特徴量 = x = 家の広さ$

* $目的変数 = y = 家の価格$

となる。

この時、それぞれのxに対して$\theta$で重み付けをしてあげて、$y$を求める関数を$h_θ(x)$として定義すると、
$$h_\theta(x) = \theta_0 + \theta_1 x$$
という感じ。

実際のデータセットでは、特徴量xは複数あるのが普通。
なので、複数の特徴量と複数行のデータセットについて、1つの数式にまとめてしまいたい。

ここで、行列計算の都合上、$x_0$ = 1 として考える。($\theta$の数と特徴量xの数を合わせるイメージ)

特徴量の数をi、データの行数をjとすると、
$\theta$は要素数$i$のベクトル、$x$のデータ全体は$i \times j$の行列となり、以下の数式で表すことができる。

```math
\begin{align}
h_\theta(x) &= \theta_0 x_0 + \theta_1 x_1 + \theta_2 x_2 + ...+\theta_n x_n \\
          &= \sum_{i=0}^{n}\theta_i x_i = \theta^T x
\end{align}
```

重回帰が行列計算一発でできてとても便利！
計算も早そう。

##損失関数
さて次は、$x$の値から$y$を近似しようとした時に、できるだけ正解に近づくような$\theta$を決めてやりたい。
そこで、各データについて実際の$y$の値と予測した$y$の値の差を取って、その差が最も小さくなる$\theta$を求める。

具体的には、実測値と予測値の誤差を二乗したものを足し合わせた、二乗誤差と呼ばれる関数を損失関数として定義し、これを最小化する$\theta$たちを探す。

```math
J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x_i) - y_i)^2 = \frac{1}{2m}\sum_{i=1}^{m}(\theta^T x_i - y_i)^2
```

#最適化
損失関数を最小にする$\theta$を探すことを、最適化という。

具体的には、上記の損失関数の微分(勾配)を最小化する。
損失関数が凸関数である限り、勾配が0になるということは、その点において損失が最小になっていることになる。

主な最適化には、解析的に求める方法と、繰り返し損失を求めながら近似的に最適値を求める方法がある。

##最急降下法(近似的な方法)
以下のようなロジックでちょっとずつ勾配を下っていく。

###アルゴリズム
1. $θ^0$をランダムに初期化する。
2. $J(\theta)$の勾配に定数$\alpha$を掛けた値を、現状の#\theta$から引く。つまり、勾配の逆方向に二乗損失のグラフを下っていくイメージ。
3. $\theta$の更新量が一定以上小さくなるまで、2を繰り返す。

```math
\theta \leftarrow \theta - \alpha\frac{\partial}{\partial \theta} J(\theta) =\theta - \alpha\frac{1}{m}\sum_{i=1}^{m}(\theta^T x_i - y_i)x_i
```

$\theta$の更新量が十分に小さくなれば、最適解に限りなく近付いたと判断できる。

###αの値について
勾配の更新幅である$\alpha$は、最急降下法がうまく働くかどうかを決定付ける。
ちゃんと考えて設定しましょうね、ということ。

* $\alpha$が小さすぎる場合
  勾配の更新幅が小さくなりすぎて、いつまで経っても最適解にたどり着けない。

* $\alpha$が大きすぎる場合
  最適解を飛び越えて更新してしまい、損失が発散してしまう。

###特徴量スケーリング
特徴量間のスケールが違いすぎると、勾配がいびつな形になり、最急降下法の更新に時間がかかることがある。

そのため、各特徴量をスケーリングしておくことが望ましい。
これは最急降下法だけではなく他の機械学習でも重要になってくる。

標準化の計算式は以下の通り。
$x$は各データの元の値を、$\bar{x}$は平均値を、$s$は標準偏差を表す。
$$\frac{x - \bar{x}}{s}$$

計算の結果、データの平均は0、分散は1に変換される。
実際の計算はライブラリ使ってささっとやっちゃうけど、何をしてるのかは覚えておこう。

Andrew先生曰く、

```math
-3 \leqq x \leqq3 \\
-\frac{1}{3} \leqq x \leqq \frac{1}{3}
```

あたりに収まっていれば標準化は不要とのこと。
データサイエンティストたちは結構感覚的にこういう調整をしてるみたい。つよい。

###確率的勾配降下法
これは別でちょっとだけ勉強した内容。

最急降下法では、全てのデータの勾配を計算して、$\theta$の更新量を計算している。
確率的勾配降下法は、ランダムに1つだけデータをピックアップして勾配を計算して、$\theta$の更新に用いる。

一回当たりの計算量が小さくなり、処理が早くなる。
一方で、、最短距離で最適解にはたどり着けず、計算回数は増える。

ちなみに、1つだけではなくいくつかのデータをピックアップして勾配を計算する方法を、ミニバッチというらしい。
この辺りの用語はこの先勉強したいディープラーニングの概要でも見かけたので、ちゃんと理解しておきたい。

##解析的に解く方法
二乗誤差関数は凸関数で微分可能なので、解析的に最適解を求めることができる。
すなわち、

```math
\frac{\partial}{\partial \theta} J(\theta) = 0
```

を解けば良い。
結果だけ書くと、以下のようになるらしい。

```math
\theta = (X^TX)^{-1} X^T y
```

計算で一発で解けるので便利だが、特徴量やデータ量が増えると、当然計算コストが大きくなる。
これまたAndrew先生曰く、特徴量の数が1000個くらいなら解析的に解くけど、10000個とか超えてくるなら最急降下法を使った方が良いとのこと。

#多項式回帰
ここまでは、与えられた特徴量にそれぞれパラメータを掛け合わせた単純な式、直線やいわゆる超平面で回帰していた。
$$y=\theta_0 + \theta_1 x_1 +\theta_2 x_2 +… \theta_i x_i$$

でも、実際のデータって直線や平面では表せないグネグネとした分布になっていることが多い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633548/6764519d-4207-6ab4-66a2-bb4c4598d1f4.png)

なので、直線ではなく曲線で回帰してやろうというのが多項式回帰の考え方。
具体的には、特徴量のn次多項式を使ってモデル化する。
例えば特徴量が$x_1$だけだとするとこんな感じ。

$$y=\theta_0 +\theta_1 x_1 + \theta_1 x_1^2 +\theta_2 x_1^2 …+\theta_n x_1^n$$

これで、グネグネと分布したデータにもフィットする回帰曲線を引くことができる。
多項式ではない線形回帰と同じく二乗誤差の勾配を計算して最適化することになる。

$sin$から作ったデータ点をざっくり4次多項式で回帰してみたらこんな感じになった。
何となくフィットしているように見える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633548/d4cc2821-9c48-6fea-3eeb-6e572c827cbb.png)

実際には、曲線が訓練データにフィットしすぎて未知のデータをうまく予測できなくなることがある。
これは過学習と呼ばれ、正則化等の方法で抑制することができるらしい。

#正則化による過学習の抑制
訓練データセットにフィットしすぎると、未知のデータをさっぱり予測できないという事態に陥ることがあり、過学習と呼ばれている。

これを抑制するための方法がいくつかあるが、ここでは正則化を学んだ。
厳密にはこれはL2正則化と言うらしい。

具体的には、損失関数に$\theta$の二乗の和に正則化パラメータ$\lambda$を掛けたものを加えてやる。
$\theta$の二乗の和は、すなわち$\theta^T\theta$と表せる。

```math
J(\theta) = \frac{1}{2m} \big[(\sum_{i=1}^{m}(\theta^T x_i - y_i)^2 + \lambda\sum_{j=1}^{n}\theta_j^2 \big] = \frac{1}{2m} \big[(\sum_{i=1}^{m}(\theta^T x_i - y_i)^2 + \lambda\theta^T\theta \big]
```

つまり、パラメータ$\theta$の値が訓練データにフィットしようとして大きくなりすぎると、損失もあわせて大きくなってくる。
この正則化項を含んだ損失関数を最適化することで、モデルの複雑さを抑えつつ学習していく。

最適化の方法は同じく最急降下法で、$J(\theta)$を各$\theta$で偏微分した勾配を小さくする方向に、$\theta$を繰り返し更新していく。
ただし、$\theta_0$については、正則化項を入れないで更新する。

```math
\begin{align}
&\theta_0 \leftarrow \theta_0 - \alpha\frac{1}{m}\sum_{i=1}^{m}(\theta^T x_i - y_i)x_{i0}\\
&\theta_j \leftarrow \theta_j - \alpha\Big[\big(\frac{1}{m}\sum_{i=1}^{m}(\theta^T x_i - y_i)x_{j0}\big) + \frac{\lambda}{m}\theta_j \Big]\\
&j = 1,2,3...,n
\end{align}
```

#まとめと感想
考え方はすごくシンプルで、データを関数で近似して予測しようという試み。
単純な$y=ax+b$での直線への近似から始まり、たくさんの特徴量を使ったり、更に多項式にして曲線で近似したりと、汎用性が高いと感じた。

一番基本的な内容だけど、解釈しやすい内容なので汎用性も高そうだし、機械学習の成り立ちや仕組みを知る第一歩でもある。