この記事は個人的なお勉強用のメモです。
このお勉強の位置
深層学習 Day 2
Section 1 勾配消失問題 ← これ
Section 2 学習率最適化手法
Section 3 過学習
Section 4 畳み込みニューラルネットワークの概念
Section 5 最新のCNN
講義
勾配消失問題
定義
誤差逆伝播法が下位層(入力層の側)に進んでいくにつれて、
勾配がどんどん緩やかになっていく。
そのため、勾配降下法による更新では下位層のパラメータはほとんど変わらず、
訓練は最適値に収束しなくなる。
原因
例えばシグモイド関数の勾配の最大値は確認テストに記したように 0.25 である。
ある個所の重みの勾配を求めるときは連鎖率で微分値を掛け算するが、
シグモイド関数の勾配値(最大0.25)を掛けると、重みの勾配が小さくなってしまう。
中間層が複数のシグモイド関数で構成されていると、
それらのシグモイド関数を通るたびに重みの勾配が小さくなる。
解決法
- 活性化関数の選択
- 重みの初期値設定
- バッチ正規化
【解決法1】活性化関数の選択
シグモイド関数を使うと勾配消失問題が起こる。
代わりに、ReLU関数を使う。
ReLU関数の微分係数(勾配)は、1または0となる。
1(入力値 > 0)
0(入力値 <= 0)
【解決法2】重みの初期値設定 - 「Xavierの初期値」
「Xavier(ザビエル)の初期値」という手法で初期値を設定する。
重みの初期値=重みの要素を、前の層のノード数の平方根で除算した値
サンプルコード
network['W1'] = np.random.randn(input_layer_size , hidden_layer_size) / np.sqrt(input_layer_size)
network['W2'] = np.random.randn(hidden_layer_size , output_layer_size) / np.sqrt(hidden_layer_size)
np.random.randn:標準正規分布に従う値を返す。
Xavierの初期値と組み合わせる活性化関数
- ReLU関数
- シグモイド関数
- 双曲線正接関数(tanh関数)
※ 赤本の 6.2.3 項 に「Xavierの初期値は活性化関数が線形であることが前提」と書いてある。
そうであれば、ReLU関数は Xavierの初期値とは組み合わせて使わないことになる。
しかし講師の話によると、ReLU+Xavierの組み合わせでいい効果が得られる場合があるとのこと。
【解決法2】重みの初期値設定 - 「Heの初期値」
ReLU関数を使う場合は、「Heの初期値」という手法で初期値を設定する。
重みの初期値=重みの要素を、前の層のノード数の平方根で除算した値に対し、
$\sqrt{2}$ を掛けた値
network['W1'] = np.random.randn(input_layer_size , hidden_layer_size) / np.sqrt(input_layer_size) * np.sqrt(2)
network['W2'] = np.random.randn(hidden_layer_size , output_layer_size) / np.sqrt(hidden_layer_size) * np.sqrt(2)
【解決法3】バッチ正規化
ミニバッチ単位で入力値のデータの偏りを抑制する手法。
活性化関数に値を渡す前後にバッチ正規化の層を加える。
活性化関数の前の場合、バッチ正規化層の入力は $u$
活性化関数の後の場合、バッチ正規化層の入力は $z$
効果
- 計算の高速化
正規化によってデータのばらつきが抑制されて、計算がコンパクトで済むため。 - 勾配消失が起きづらくなる。
数学的記述
\begin{align}
\mu_t &= \frac{1}{N_t}\sum_{i=1}^{N_t}x_{ni} (ミニバッチの平均値)\\
\sigma_t^2&=\frac{1}{N_t}\sum_{i=1}^{N_t}(x_{ni}-\mu_t)^2 (ミニバッチの分散)\\
\hat{x}_{ni}&=\frac{x_{ni}-\mu_t}{\sqrt{\sigma^2+\theta}} (正規化つまり平均値を0かつ分散を1にする)\\
y_{ni}&=\gamma x_{ni} + \beta
\end{align}
$\gamma$:スケーリングパラメータ
$\beta$:シフトパラメータ
※講義動画では $\sigma_t^2$ が標準偏差という説明をしているが、正しくは分散だと思う。
実装演習
シグモイド関数、初期値の加工なし
勾配消失問題が発生していて、学習が進んでいない。
ReLU関数、初期値の加工なし
シグモイド関数に比べると、ReLU関数では学習が進んでいる。
シグモイド関数、Xavierの初期値
シグモイド関数であるにもかかわらず、Xavierの初期値で初期値を変更するだけで
勾配消失問題が発生せずに、学習が進むようになった。
ReLU関数、Heの初期値
早い段階から学習が進んでいる。
Heの初期値の効果は非常に高い。
シグモイド関数、Heの初期値
Xavierの初期値と比較して、大きな違いは見受けられない。
ReLU関数、Xavierの初期値
Heの初期値と比較して、大きな違いは見受けられない。
動作結果のまとめ
- シグモイド関数の場合、XavierまたはHeの初期値の設定をしないと学習が進まない。
設定をすれば学習するようになる(どちらを選んでも効果は同じくらい)。 - ReLU関数の場合、XavierまたはHeの初期値の設定をしなくてもそこそこ学習する。
設定をすればさらに学習の効果が高くなる(どちらを選んでも効果は同じくらい)。
今回の動作結果は上記のとおりだが、条件によって動作結果が変わってくるので
いろいろと試してみるのがいいとのこと。
確認テスト
シグモイド関数の微分係数の最大値
シグモイド関数の導関数は $\sigma (1-\sigma)$ であるため、微分係数は $\sigma = 0.5$ のときに最大になる。
このときの微分係数は $\sigma (1-\sigma) = 0.5 \times (1-0.5) = 0.25$
参考までに、そのときの z の値は
\begin{align}
\frac{1}{1+e^{-z}}&=0.5
\\
1+e^{-z}&=2\\
e^{-z}&=1\\
\log e^{-z}=\log 1\\
-z \log e &= 0\\
\therefore z &= 0
\end{align}
重みの初期値を0にした場合に起こる問題
重みの初期値を0にすると重みの勾配が0となり、誤差逆伝播法によって他のどんな値をかけても
重みの勾配は0になってしまって、重みが更新されない問題が起こる。
↑ 的外れな解答
模範解答1
全ての値が同じ値で伝わるため、パラメータのチューニングが行われなくなる。
模範解答2
すべての重みの値が均一に更新されるため
多数の重みを持つ意味がなくなる。
バッチ正規化の効果
赤本 6.3.1 項より。
- 学習を早く進行させられる。
- 初期値にそれほど依存しない。
- 過学習を抑制する。
模範解答
- 計算の高速化
- 勾配消失が起きづらくなる。
修了テスト~練習問題~
問題59(バッチ正規化)
(あ)には正規化(平均1分散1にする)の式が入るので、正解はこれ。
\frac{x_i-\mu_{B}}{\sqrt{\sigma_B^2+\epsilon}}
平均値を引いて、標準偏差で割る。