3秒でわかる
出力の誤差を後ろから前へたどって各重みの修正量を求める計算手順。大きなニューラルネットの学習を現実的な時間で回すために使います。
30秒図解
もう少し詳しく
どういうものか
逆伝播は、ニューラルネットワークの学習で、出力の誤差を最後の層から入力側へ順にさかのぼりながら、各重みをどれだけ動かせば誤差が減るかを求める計算です。合成関数の微分の連鎖律をそのまま計算手順にしたもので、前の層で使った途中結果を再利用するため、重みが何百万個あっても一度の走査で全部の修正量が出ます。
学習の 1 回分は、入力から出力へ計算する順伝播、誤差の計算、逆伝播による勾配の算出、求めた勾配で重みを更新する、という 4 段階の繰り返しです。
なぜ必要か
重みを 1 個ずつずらして誤差の変化を測る方法でも勾配は求まりますが、重みの数だけネットワーク全体を計算し直すことになります。100 万個の重みなら 100 万回です。逆伝播なら、順伝播 1 回分と同じ程度の手間で全部の勾配が求まります。この差があるからこそ、大規模なモデルの学習が現実の時間で終わります。
具体例
PyTorch では、順伝播の過程が自動で記録され、backward を呼ぶと各パラメータに勾配が入ります。
import torch
x = torch.tensor([1.0, 2.0])
w = torch.tensor([0.5, -0.3], requires_grad=True)
y_true = torch.tensor(1.0)
y = (x * w).sum() # 順伝播
loss = (y - y_true) ** 2 # 誤差
loss.backward() # 逆伝播
print(w.grad) # 各重みの修正の向きと大きさつまずきやすいところ
勾配が累積される点は、手書きの学習ループで必ず引っかかります。backward を呼ぶたびに grad へ足し込まれるため、更新のたびに zero_grad で消さないと、前回までの勾配が混ざった値で重みが動きます。学習が発散する原因の定番です。
層を深くしたときに、入力側へ届くころには勾配がほとんど 0 になる勾配消失も起こります。掛け算を重ねる過程で値が小さくなり続けるためで、活性化関数の選択や、層を飛び越える接続で緩和します。
推論だけを行う場面で勾配の記録を止めないと、無駄なメモリを使い続けます。
覚え方
順伝播が「答えを出す向き」、逆伝播が「責任を配る向き」です。最終的な誤差を、どの重みがどれだけ引き起こしたかという割合で後ろから分配していく、と捉えると流れが追えます。
計算グラフを思い浮かべると、逆伝播はそのグラフを逆向きに 1 度たどるだけの作業です。掛け算の枝では相手の値が、足し算の枝ではそのままの値が上流へ渡っていく、という単純な規則の繰り返しにすぎません。