誤差逆伝播 入門
「すべてのパラメータに関する損失の勾配を計算する」 —— パラメータが数百万個もあると、 これは不可能に聞こえる —— 手計算なら本当に不可能だ。誤差逆伝播(backpropagation)はそれを代わりにやってくれるアルゴリズムで、ネットワークを 1 回 逆向きに辿りながら、各接続で微積分 primer の連鎖律を適用していく。4 つのトピック: 逆伝播そのもの、なぜ重みをすべて 0 で初期化してはいけないか、深層ネットワークに付き まとう勾配消失 / 勾配爆発の問題、そして MLP —— Transformer の各ブロックに隠れている シンプルな深層ネットワーク。
誤差逆伝播
連鎖律をすべてのパラメータに 1 回で。
勾配降下 primer の締めは気持ちよかった:1 ステップは w ← w − η · ∇L だけ。だがあの primer は 「その勾配は計算できる」とこっそり仮定していた。パラメータが 1 つなら、 確かにできる —— 微積分 primer §1。だがパラメータが百万個、50 層に散らばっていると、 「手で勾配を計算する」のはもはや現実的な作業ではない。誤差逆伝播(backpropagation)はそれを それでも可能にするアルゴリズムだ。
誤差逆伝播には 2 つの性質があり、合わせて「深層学習が回る理由」のすべてだ:
- 自動である。順伝播を書けば、フレームワーク(PyTorch、JAX、 TensorFlow)がすべての勾配をタダで返してくれる。シンボリック代数も手計算も 要らない。
- コストはネットワーク規模に対して線形。「順伝播 1 回 + 逆伝播 1 回」 は概ね「順伝播 2 回」と同じコスト。パラメータ 100 万のネットでも、その 100 万個の 勾配は逆伝播 1 回で一気に出てくる —— 100 万回計算するわけではない。
鍵は、微積分 primer §3 の連鎖律を徹底的に当てはめること。計算を逆向きに辿る: 各ステップで、戻ってくる勾配は次のステップの勾配にその場所の局所微分を掛けたもの。 各パラメータの勾配は、そのパラメータから損失までの経路上の局所微分すべての積になる。
具体例:1 入力、1 隠れニューロン、1 出力の小さなネット。 入力 x = 2、目標 y = 5。 重みは w₁ = 1.5, b₁ = 0.5, w₂ = 0.8, b₂ = 0.1。損失は二乗誤差。
順伝播: z = w₁·x + b₁ = 1.5·2 + 0.5 = 3.5 a = ReLU(z) = ReLU(3.5) = 3.5 ŷ = w₂·a + b₂ = 0.8·3.5 + 0.1 = 2.9 L = (ŷ − y)² = (−2.1)² = 4.41 逆伝播(各行は「ひとつ局所微分を掛ける」だけ): ∂L/∂ŷ = 2 · (ŷ − y) = −4.20 ∂L/∂w₂ = ∂L/∂ŷ · a = −4.20 · 3.5 = −14.70 ∂L/∂a = ∂L/∂ŷ · w₂ = −4.20 · 0.8 = −3.36 ∂L/∂z = ∂L/∂a · ReLU'(z) = −3.36 · 1 = −3.36 ∂L/∂w₁ = ∂L/∂z · x = −3.36 · 2 = −6.72
リズムを見てほしい。逆伝播の各行は「1 行前の結果に局所微分を 1 つ掛けた」もの。∂L/∂w₁ = ∂L/∂z · ∂z/∂w₁ —— 微積分 primer の連鎖律そのまま、それ以上でも 以下でもない。各パラメータの勾配は、そのパラメータから損失までの経路上の局所微分の 積に過ぎない。
"逆"伝播の "逆" も重要だ:勾配は出力から入力に向けて計算され、その逆では ない。なぜか? ∂L/∂ŷ が分かれば、それを再利用して 1 つ前の層の勾配 (ここでは w₂, b₂, a)をすべて計算できる。次に ∂L/∂a が 分かれば、さらに 1 つ前の層のすべてを計算できる。各層は「上から受け継いだ勾配」に 自分の局所微分を掛けて、さらに前の層に渡す。総作業量は「グラフを 1 回逆向きに歩く」 だけだ。
実装の小ネタ。順伝播の間、フレームワークは計算グラフを記録する —— 各演算とその出力値。 逆伝播ではそのグラフを逆向きに辿り、内部組み込み演算(行列積、ReLU、sigmoid、softmax、 LayerNorm、attention —— どれにも手で書かれた勾配式がある)ごとに対応する局所微分を 掛けていく。ユーザーはここに触れない。順伝播だけ書く;残りは loss.backward() がやってくれる。
Transformer では:同じアルゴリズム、グラフがずっと大きいだけ。 700 億パラメータのモデルでも、700 億個の勾配は同じ逆伝播 1 回ですべて出てくる —— 出力を生んだのと同じ計算グラフを辿るだけだ。各アテンションヘッドの各重み、各 FFN、 各 LayerNorm —— 誤差逆伝播はそれらを一括で、順伝播 1 回分のコストとほぼ同じで 計算してくれる。逆伝播がなければ、Transformer の訓練は「遅い」問題ではなく、 「不可能な」問題だった。
重みの初期化
どの重みも小さなランダム値から始まる理由 —— 0 ではなく。
誤差逆伝播はオプティマイザに重みを「どう改善するか」を教える。 だが最初の更新の前に、重みには初期値が要る。 「全部 0 にする」は最も自然な第一案だ —— そしてそれは訓練が始まる前に訓練を殺す。 その理由と、代わりに何をするかを見よう。
100 個のニューロンを持つ層を想像する。全部の重みが 0 で初期化されている。 この層のどのニューロンも同じ入力を見て、同じレシピを当てるので、同じ出力を出す。 機能的にはすべて同じニューロン —— ただ 100 個コピーされただけ。 ゼロ初期化の「幅 100 の層」は「幅 1 の層」と幅が変わらない。
逆伝播でさらに悪化する:
- この層のニューロンが同じ出力を返すから、上層から降りてくる勾配も同じになる。
- 同じ入力 + 同じ勾配 → 同じ重み更新。
- 更新後も 100 個のニューロンの重みは完全に同一。この層は永遠に「1 個のニューロンが 100 個に化けた」状態のまま。訓練がこの対称を破れない —— 逆伝播は対称を保つだけだ。
これが対称性問題だ。同一層内のニューロンを同一にする初期化は、 どれも彼らを永遠に同期させてしまう —— 損失がどれだけ賢かろうと、 オプティマイザがどれだけ気を遣おうと、何エポック待とうと解けない。
対策:対称を破る。各重みを独立な小さなランダム値で初期化する (ガウスでも一様でもよい)。すると同じ層のニューロンは入力を違うように見るようになる:出力が違い、勾配が違い、訓練の中で違う役割に育つ。 「幅広の層」が本当に幅広になる。
ランダム初期化で対称は破れるが、ランダムのスケールは適当には選べない。 分散が小さすぎる(0 に近い)と信号が層ごとに減衰する —— 第 10 層では各活性が ほぼ 0 で、ネットは学べない。分散が大きすぎる(1 に近い)と信号が層ごとに増幅する —— 活性が飽和し、損失が NaN になる。信号が深さを越えて綺麗に伝わるのは狭い分散帯だけで、 標準のレシピはその帯に着地するように設計されている:
- Xavier(Glorot)初期化 —— sigmoid / tanh 活性化を仮定して、 層をまたいで活性の分散が概ね一定になるように重みのスケールを取る。 分散 ≈
1 / n_in。 - He 初期化 —— 同じ発想を ReLU に合わせて調整したもの。 ReLU は入力の半分を 0 にするので、補うために分散を倍にする。 分散 ≈
2 / n_in。 - バイアス —— 通常はそのまま 0 で開始。バイアスには対称性問題が ない(ニューロンを縛るのは重みだけ)し、勾配がすぐに有用な値に押し上げてくれる。
「小さい」という形容詞は重要だ。深 ReLU ネットで分散 1 の重みを使うと、 最初の順伝播の段階で出力に巨大な活性が出る。分散 0.001 で初期化すれば、 第 5 層を越えると活性は塵になっている。分散 ≈ 1/n_in が「ちょうど良い」帯で、 ±2 倍程度の遊びが許容される。
Transformer では:線形層(QKV 投影、アテンション出力、FFN 層)は 通常、分散 ≈ 1 / d_model のガウス分布で初期化する。 レシピによっては「出力投影」をさらに縮める(例えば 1 / √(2N)、 N は層数)。残差ストリームの分散がブロックを積むごとに膨らまないようにするためだ。 LayerNorm は恒等写像(gain = 1、bias = 0)で開始する。具体的な定数は変わるが、 原則は変わらない —— 対称を破り、分散を抑える。
勾配消失と勾配爆発
局所微分 50 個の積は、ほとんどの場合「ちょうど良い数」ではない。
誤差逆伝播は、入力側に近い層の ∂L/∂w を「その重みから損失までの経路上 の局所微分の積」として計算する。50 層のネットでは、その積は約 50 項からなる。 各項が 1 をわずかに下回ると、積は実質ゼロ。1 をわずかに上回ると、積は実質無限大。 どちらでも訓練は壊れる。
同じ掛け算が、2 通りの形で失敗する:
- 勾配消失 —— 多くの局所微分が小さい。積は深さに対して指数的に 縮む。入力側の層が受け取る勾配はほぼ 0、重みはほとんど更新されない; 技術的には学習可能でも、その層は凍結されたように振る舞う。
- 勾配爆発 —— 多くの局所微分が大きい。積は深さに対して指数的に 膨らむ。入力側の層が受け取る勾配は巨大、オプティマイザがどこかランダムな方向に 大ジャンプ、重みが発散して、数回の更新で損失が
NaNになる。
具体的に:0.5 の 50 乗 ≈ 8 × 10⁻¹⁶。1.5 の 50 乗 ≈ 6.4 × 10⁸。各層では穏当な係数が、深さで複利されると災害になる。
原因を、現場で出てくる順に並べると:
- 飽和する活性化関数。sigmoid の微分は最大でも
σ'(z) ≤ 0.25。20 層の sigmoid ネットは 0.25 以下を 20 個掛ける —— 勾配は数学的に最大でも 0.25²⁰ ≈ 10⁻¹²。tanh は若干マシ(最大 1.0) だが、両端で導関数が 0 に飽和する。ReLU は大きく改善する(導関数は 0 か 1、 「生きている」半分では一切縮まない)。これが ReLU が sigmoid / tanh を置き換えた 理由の一つ。 - 悪い初期化。§2 で触れた通り —— 重みの分散を 4 にすれば、 局所微分も同じくらい増幅され積が爆発する;分散 0.01 で初期化すれば消失する。 Xavier / He 初期化は、まさに「層あたりの乗数」が 1 近辺に落ちるように作られている。
- ただ深いだけ。活性化と初期化が妥当でも、100 層を素朴に積めば ドリフトする。1 近辺の数を 100 個掛けても、結局 1 から離れていく。
2025 年に深層ネットを訓練可能にしているパッチ群:
- より良い活性化関数 —— ReLU、GELU、SiLU。正半分が飽和しない。
- 適切な初期化 —— tanh には Xavier、ReLU には He、 Transformer には
1/d_model。 - 正規化層 —— BatchNorm、LayerNorm、RMSNorm。各層の後で活性の 中心とスケールをやり直し、積が無限にドリフトするのを防ぐ。
- 残差接続 ——
x + sublayer(x)。任意の層の勾配は 少なくとも次の層の勾配と同じ(「+ x」のせい)で、ゼロには縮めない。 深層ネットを実用可能にした決定的な工夫。 - 勾配クリッピング —— 爆発対策の安価なハック。勾配のノルムが ある閾値(例えば 1.0)を超えたら、そのまま縮めて戻す。NaN は防げる。 更新が多少偏ることもある。
Transformer では:5 つの対策が同時に投入されている。GELU 活性化、 深さで調整した慎重な初期化、各サブ層前の LayerNorm、各サブ層を包む残差接続、そして 通常 ‖g‖ ≤ 1 の勾配クリッピング。これらが揃って初めて 100 層の Transformer が訓練可能になる。どれか 1 つでも欠ければ、当時 12 層の GPT-1 ですら 苦戦していたはずだ。特に残差接続は「飾り」ではない —— 深さそのものを可能にしているのが これだ。
MLP(= Transformer の FFN)
ニューラルネット primer の「層」を数回積めば、深層ネット。
ニューラルネット primer の「ニューロンの層」を取り出して、活性化を挟みながら 2〜3 段 積み上げると、それが MLP(Multi-Layer Perceptron、多層パーセプトロン) だ。最も単純な深層ネットで、2014 年頃まで深層学習論文のほぼすべてが扱っていたもの、 そして今でもすべての Transformer ブロックの FFN サブ層がこれだ。 ニューラルネット primer の順伝播が分かれば、MLP も分かる —— 同じ演算を 3 回繰り返すだけ。
レシピを 1 行で:Linear → 活性化を繰り返し、最後の層は Linear のみ(生のロジットやスカラー出力が欲しいので、活性化はかけない)。
MLP(x): h₁ = ReLU( W₁ · x + b₁ ) ← 第 1 層 h₂ = ReLU( W₂ · h₁ + b₂ ) ← 第 2 層 ŷ = W₃ · h₂ + b₃ ← 第 3 層(活性化なし) return ŷ
定義はこれだけ。「より深い」MLP は単に中央に ReLU(W·_+b) の行を増やす だけ。深さ(層数)と幅(各 h_i のサイズ)はハイパーパラメータで、 それ以外は同じ演算の繰り返し。
MLP について意外と知られていない 2 つの事実:
- 原則として、1 つの隠れ層で十分。万能近似定理いわく:十分な数の ニューロンを持つ単一の隠れ層は、任意の連続関数を任意の精度で近似できる ——原則として。実際は「十分な数」が法外な数になり、訓練が現実的でなくなる。 だから積む —— 深さは幅より「安い」。
- 活性化なしの MLP は 1 つの線形層に等しい。5 つの線形層を非線形なしで 積み上げると、全体は
(W₅ · W₄ · W₃ · W₂ · W₁) · xという 1 つの線形写像に 縮退する。深さは何も生まない。非線形性こそが「深い」と「広い」を分けるものだ。
なぜ「feedforward」と呼ぶ? 情報が一方向にしか流れないからだ —— 左に入力、右に出力、 ループなし。(ループのあるネットは再帰型 —— RNN とその仲間。) 順伝播は左から右へ 1 回歩くだけ、逆伝播は右から左へ 1 回歩くだけ。 誤差逆伝播はこの構造を好む:サイクルがないので不動点反復もない、勾配順序の曖昧さもない。
"多層パーセプトロン" という名前は半分は歴史の重荷だ。「パーセプトロン」(perceptron)は 1958 年の Rosenblatt の単層線形分類器。「多層」という接頭辞が深さと非線形性を加え、 この primer がずっと描いてきたネットになった。「MLP」と「FFN」(Feed-Forward Network)は 同じアーキテクチャを指す —— 読む論文によって、どちらかの名前が使われる。
Transformer では:FFN サブ層は MLP そのもの、それ以上でも以下でもない。 標準形は2 層:d_model から 4 · d_model への「上方 投影」、GELU(または SiLU)活性化、そして d_model への「下方投影」。 各 Transformer ブロックがちょうど 1 つ持ち、アテンションサブ層の直後に置かれる。 GPT-3 規模のモデルでは FFN サブ層が全パラメータの約 3 分の 2 を占める —— アテンションは「ルーティング」、MLP は「実際の計算」の本丸。 要するに、1750 億パラメータの言語モデルは重みの大半をこれに使っている:96 個の "Linear → GELU → Linear" を、アテンションで貼り合わせ、両端に数億個分の埋め込みと 正規化パラメータを足したもの。ここまでで、全部の重みが何をしているかは分かった。 次は、それらをつなぐ「接着剤」を読みに行こう。