本文へスキップ
ひもとくAI

勾配消失と重みの初期化

レッスン 5/7

勾配消失:層を深くすると、前の層が学習しなくなる

第6章の誤差逆伝播では、変化の割合を 後ろの層から掛け算でつないで、各層の勾配を求めました。層が深くなると、この掛け算の回数が増えます。

シグモイド関数の傾きは、最大でも0.25

第5・6章のシグモイド関数 σ(z)\sigma(z) の傾き(変化の割合)は、σ(z)×(1−σ(z))\sigma(z) \times (1 - \sigma(z)) という式で求められることが知られています(式の導き方は、高校・大学で学ぶ微分を使います。ここでは結果だけを使います)。σ(z)\sigma(z) は0〜1の値なので、この傾きが最も大きくなるのは σ(z)=0.5\sigma(z) = 0.5(つまり z=0z = 0)のときで、0.5×0.5=0.250.5 \times 0.5 = 0.25 です。zz が0から離れると、傾きはもっと小さくなります。

誤差逆伝播では、層を1つさかのぼるたびに、この傾きを掛けます。1より小さい数を何回も掛けると、どんどん小さくなります。

0.258=0.0000152…0.25^8 = 0.0000152\ldots

8層さかのぼると、傾きの掛け算だけで、変化の割合は6万分の1以下になりえます。

実験:層ごとの勾配の大きさを測る

手書き数字のデータで、隠れ層を8層(各32個)重ねたネットワークを作り、学習を始める前の勾配の大きさを、層ごとに測りました(重みの初期値は、シグモイド関数向けの決め方(次のスライドのXavier法))。

層1層目(入力側)2層目3層目4層目5層目6層目7層目8層目最後の層(出力側)
勾配の大きさ0.00001190.00003490.0001220.0005930.002030.008260.03620.1470.603

出力側から入力側へさかのぼるほど、層を1つ進むたびに約3〜5分の1ずつ小さくなり、1層目の勾配は、最後の層の 約5万分の1 になりました。

勾配が小さいと、重みはほとんど動きません。入力に近い層ほど学習が進まなくなる この現象を 勾配消失 と呼びます。1990年代〜2000年代の初めに、深いニューラルネットワークの学習がうまくいかなかった大きな理由の一つです。

反対に、1より大きい数を何回も掛けると、勾配がどんどん大きくなり、重みが暴れて学習が壊れることもあります。これを 勾配爆発 と呼びます。

ReLUと、重みの初期値の決め方

ReLUの傾きは1

第6章のReLUは、「マイナスなら0、プラスならそのまま」でした。プラスのところの傾きは ちょうど1 です。1を何回掛けても1なので、シグモイド関数のように、層を重ねるたびに勾配が小さくなることはありません。ディープラーニングでReLUが広く使われるようになった大きな理由です。

それでも、初期値が小さすぎると学習しない

ReLUを使っても、学習を始める前の重み(初期値)が小さすぎると、各層の出力が層を重ねるたびに小さくなっていき、勾配も消えてしまいます。

同じ8層のネットワークで、ReLUを使い、初期値の決め方を変えて、勾配の大きさを測りました。

初期値の決め方1層目の勾配最後の層の勾配
ReLU + 小さすぎる初期値(ばらつき0.01)約0.000000000003約0.000000000003
ReLU + He法0.7630.454

小さすぎる初期値では、どの層の勾配も、ほぼ0になりました。これでは、学習がまったく進みません。

入力の数に合わせて、初期値のばらつきを決める

1つのニューロンは、前の層の nn 個の値に重みを掛けて足します。nn が大きいほど、足し合わせた結果のばらつきは大きくなります。そこで、前の層の数 nn に合わせて、初期値のばらつき(標準偏差)を決める と、層を重ねても出力の大きさがそろいます。

決め方初期値の標準偏差使う場面
Xavier法(Glorot法)1n\sqrt{\dfrac{1}{n}}シグモイド関数・tanh
He法(Kaiming法)2n\sqrt{\dfrac{2}{n}}ReLU

He法が2倍にしているのは、ReLUがマイナスの値(およそ半分)を0にしてしまうぶんを補うためです。He法を使うと、どの層の勾配も0.33〜0.76の範囲に収まり、1層目まで勾配が届きました。

実は、第7章のミニプロジェクトのCNNでも、フィルターの初期値を rng.normal(0, np.sqrt(2 / 9), ...) と、He法(n=9n = 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なので、勾配が消えにくい
  • 初期値のばらつきは、前の層の数 nn に合わせる。Xavier法は 1/n\sqrt{1/n}、ReLU向けのHe法は 2/n\sqrt{2/n}

演習

演習を読み込んでいます…