勾配消失:層を深くすると、前の層が学習しなくなる
第6章の誤差逆伝播では、変化の割合を 後ろの層から掛け算でつないで、各層の勾配を求めました。層が深くなると、この掛け算の回数が増えます。
シグモイド関数の傾きは、最大でも0.25
第5・6章のシグモイド関数 σ(z) の傾き(変化の割合)は、σ(z)×(1−σ(z)) という式で求められることが知られています(式の導き方は、高校・大学で学ぶ微分を使います。ここでは結果だけを使います)。σ(z) は0〜1の値なので、この傾きが最も大きくなるのは σ(z)=0.5(つまり z=0)のときで、0.5×0.5=0.25 です。z が0から離れると、傾きはもっと小さくなります。
誤差逆伝播では、層を1つさかのぼるたびに、この傾きを掛けます。1より小さい数を何回も掛けると、どんどん小さくなります。
0.258=0.0000152…
8層さかのぼると、傾きの掛け算だけで、変化の割合は6万分の1以下になりえます。
実験:層ごとの勾配の大きさを測る
手書き数字のデータで、隠れ層を8層(各32個)重ねたネットワークを作り、学習を始める前の勾配の大きさを、層ごとに測りました(重みの初期値は、シグモイド関数向けの決め方(次のスライドのXavier法))。
出力側から入力側へさかのぼるほど、層を1つ進むたびに約3〜5分の1ずつ小さくなり、1層目の勾配は、最後の層の 約5万分の1 になりました。
勾配が小さいと、重みはほとんど動きません。入力に近い層ほど学習が進まなくなる この現象を 勾配消失 と呼びます。1990年代〜2000年代の初めに、深いニューラルネットワークの学習がうまくいかなかった大きな理由の一つです。
反対に、1より大きい数を何回も掛けると、勾配がどんどん大きくなり、重みが暴れて学習が壊れることもあります。これを 勾配爆発 と呼びます。
ReLUと、重みの初期値の決め方
ReLUの傾きは1
第6章のReLUは、「マイナスなら0、プラスならそのまま」でした。プラスのところの傾きは ちょうど1 です。1を何回掛けても1なので、シグモイド関数のように、層を重ねるたびに勾配が小さくなることはありません。ディープラーニングでReLUが広く使われるようになった大きな理由です。
それでも、初期値が小さすぎると学習しない
ReLUを使っても、学習を始める前の重み(初期値)が小さすぎると、各層の出力が層を重ねるたびに小さくなっていき、勾配も消えてしまいます。
同じ8層のネットワークで、ReLUを使い、初期値の決め方を変えて、勾配の大きさを測りました。
小さすぎる初期値では、どの層の勾配も、ほぼ0になりました。これでは、学習がまったく進みません。
入力の数に合わせて、初期値のばらつきを決める
1つのニューロンは、前の層の n 個の値に重みを掛けて足します。n が大きいほど、足し合わせた結果のばらつきは大きくなります。そこで、前の層の数 n に合わせて、初期値のばらつき(標準偏差)を決める と、層を重ねても出力の大きさがそろいます。
He法が2倍にしているのは、ReLUがマイナスの値(およそ半分)を0にしてしまうぶんを補うためです。He法を使うと、どの層の勾配も0.33〜0.76の範囲に収まり、1層目まで勾配が届きました。
実は、第7章のミニプロジェクトのCNNでも、フィルターの初期値を rng.normal(0, np.sqrt(2 / 9), ...) と、He法(n=9、3×3のフィルター)で決めていました。
Pythonで初期値を決める、よくある誤解と振り返り
He法の初期値は、rng.normal で作れます。平均と標準偏差を決めると、平均の近くに多く、平均から離れるほど少なくなるように散らばる、でたらめな数を作る関数です(このような散らばり方を 正規分布 と呼びます。テストの点数や身長の分布が、この形に近くなることが知られています)。
import numpy as np
rng = np.random.default_rng(0)
n_in, n_out = 64, 32 # 前の層の数、この層のニューロンの数
W = rng.normal(0, np.sqrt(2 / n_in), (n_in, n_out)) # He法
b = np.zeros(n_out) # バイアスは0から始めてよい
print(W.std()) # → 約0.177(= √(2/64))
rng.normal(平均, 標準偏差, 形) は、平均のまわりに、標準偏差くらいのばらつきで散らばる数を作ります(第3章の標準偏差)
- 重みを全部同じ値(例えば全部0)で始めると、どのニューロンも同じ計算をし、同じように学習してしまいます。でたらめな数で始めるのは、ニューロンごとに違う役割を持たせるためです
- PyTorchの
nn.Linear や nn.Conv2d は、はじめから同じ考え方の初期値を使っています
よくある誤解
- 「層を深くするほど、必ず賢くなる」: 勾配消失のように、深くすると学習そのものが難しくなる問題があります。ReLU・初期値の工夫・次のレッスンのBatch Normalizationなどを組み合わせて、はじめて深いネットワークを学習できます
- 「初期値は、でたらめなら何でもよい」: ばらつきが小さすぎると勾配が消え、大きすぎると爆発します。前の層の数に合わせて決めます
- 「重みは0から始めればよい」: 全部0だと、どのニューロンも同じになり、区別がつかないまま学習が進みます
振り返り
- 勾配消失: 誤差逆伝播で1より小さい傾きを何回も掛けるため、入力に近い層ほど勾配が小さくなり、学習が進まない。シグモイド関数の傾きは最大0.25
- ReLUの傾きは1なので、勾配が消えにくい
- 初期値のばらつきは、前の層の数 n に合わせる。Xavier法は 1/n、ReLU向けのHe法は 2/n