はじめに
前回の記事に記載した最適化問題である
\min_{\Theta} \frac{1}{2m} \sum^{m}_{i=1}\|x^{(i)} \Theta - y^{(i)}\|^2 \\
の基本的な解き方を自分なりにまとめておく.
準備
色々計算しやすいように事前に最適化問題の式を整理しておく.
まず以下のような関数に切り出しておく.
\begin{align}
h_{\theta}({\it{\bf{x}}})&=\sum^n_{i=1} x_i \theta_i \\
J(\Theta)&=\frac{1}{2m} \sum^{m}_{i=1}\|h_{\theta}(x^{(i)})-y^{(i)}\|^2 \\
\end{align}
そうすると,最小値を求める$\min$式は
\min_{\Theta} J(\Theta) \\
となる.関数$J(\Theta)$を最小化させるため,関数$J(\Theta)$を目的関数と呼ぶこともある.
また,$h_{\theta}(x)$のことを,コスト関数や仮説(Hypothesis)などと呼ぶ.
勾配降下法
この最適化問題を解くのは勾配降下法/最急降下法と呼ばれる方法でパラメータ$\Theta$の最適値を求めていくのが一般的である.
以下の式が収束するまで,繰り返していく.
\theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j}J(\Theta)\quad(j = {0,...,n}) \\
ここで注意するべき点は$\theta_j$の値は「まとめて更新する」ということ.
例えば,$\Theta = (\theta_0, \theta_1)$と2つのパラメータを求めるとする.
このパラメータを上記の式で表現する場合,
\theta_0 := \theta_0 - \alpha \frac{\partial}{\partial \theta_0}J(\theta_0, \theta_1) \\
\theta_1 := \theta_1 - \alpha \frac{\partial}{\partial \theta_1}J(\theta_0, \theta_1) \\
としてはいけないということ.
$\theta_1$は,更新された$\theta_0$を使っているため,これは正しい勾配降下法の実装になっていない.
正しくは,
\begin{align}
temp0 &:= \theta_0 - \alpha \frac{\partial}{\partial \theta_0}J(\theta_0, \theta_1) \\
temp1 &:= \theta_1 - \alpha \frac{\partial}{\partial \theta_1}J(\theta_0, \theta_1) \\
\theta_0 &:= temp0 \\
\theta_1 &:= temp1 \\
\end{align}
と仮変数を使うことで,更新後の値はそれぞれ更新前の$\theta_0$と$\theta_1$から求めることができ,正しい勾配降下法の実装ができるようになる.
勾配降下法を感覚的に捉えるとすれば,丘の上から緩やかに坂を下っていくボールをイメージするとわかりやすい.ボールが転がりきって,それ以上動かなくなれば,その位置が最小値ということである.
しかし,「その時に坂が下っているほうに進む」ということを繰り返しているため,進んでいる方向が必ずしも大域的最小値(global minimum)であるとは限らない.つまり,局所的最小値(local minimum)にたどり着くこともある.これを念頭に置いておく必要がある.
勾配降下法で使用するαについて
勾配降下法で使用する$\alpha$は,パラメータを求めるための処理を制御するパラメータということで,超パラメータ(hyper-parameter)と呼ばれることもある.
この値は,繰り返し計算する際の更新度合いを定義するものである.
$\alpha$が大きすぎると更新しすぎて,最小値を行ったり来たりすることがある.(ボールの勢いがつきすぎる)
逆に$\alpha$が小さすぎると,あまり更新しないため,繰り返し回数が多くなる.(ボールがあまり転がらない)
これを解消するために,回を重ねるごとに$\alpha$を少しづつ小さくさせるという工夫を入れることもある.
おわりに
今回は,機械学習で利用するパラメータ$\Theta$を,勾配降下法を使って求める方法をまとめてみた.
勾配降下法は,局所的最小値を取ることもあるが,実装の容易さが特徴であり,感覚的にもわかりやすいということからよく使わているようだ.
行列を利用して複数のデータをまとめて計算することで実装が簡素になることが多い.
また言語によっては,その演算が組み込まれていて行列計算自体を考えなくてもいいこともある.(matlabなど)