なぜLSTMは長期記憶を保てるのか — セル状態の計算を1ステップずつ電卓で追って腑に落とす

LSTMの構造図はネットのどこにでもあります。「セル状態というベルトコンベアがあって、忘却ゲート・入力ゲート・出力ゲートが情報を制御する」——図を見れば、なんとなく仕組みはわかった気になります。

でも、こういう疑問が残りませんか。

なぜ、あの計算式だと長期の記憶が保存できるのか? 図の「ベルトコンベア」は理解できた。でも、$C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t$ という式の、掛け算と足し算が、いったいどういうロジックで「遠い過去を覚えていられる」という性質に化けるのか。そこが演算レベルで腑に落ちない。

この記事は、まさにこの「演算レベルの腑落ち」だけを狙います。アーキテクチャの紹介は最小限にして、セル状態の数式を電卓レベルで1ステップずつ追いかけ、「足し算」「要素ごとの掛け算」「0〜1のゲート」という3つの素朴な演算が、どうやって長期記憶という性質を生み出すのかを、forward(順伝播)と backward(誤差逆伝播)の両方から手を動かして確かめます。

この理解は、LSTMだけの話ではありません。

  • ResNetのスキップ接続がなぜ深いネットワークを訓練可能にするのか(同じ「足し算で素通りレーンを作る」原理)
  • Transformerの残差接続・GRU・状態空間モデル(Mamba等)まで、現代の系列モデルが共通して使う「勾配を素通りさせる」設計思想

——これらが一本の線でつながって見えるようになります。

本記事の内容

  • バニラRNNが「同じ数を掛け続ける」せいでなぜ記憶を失うのか(演算レベル)
  • LSTMの中心式 $C_t = f_t C_{t-1} + i_t \tilde{C}_t$ を電卓で追う順伝播
  • 「足し算」を微分すると勾配が忘却ゲートの積 $\prod f_k$ になる逆伝播のからくり
  • 「要素ごとの積」「シグモイド」「tanh」がそれぞれ何のためにあるのか
  • PyTorchで実際にBPTTの勾配を測り、バニラRNNとの差を可視化する

前提知識

この記事は「なぜその計算が効くのか」に絞っています。LSTMの各ゲートの役割やアーキテクチャの全体像は、以下の記事で先に押さえておくと、本記事の演算追跡がスッと入ってきます。

「勾配」「誤差逆伝播」という言葉にピンとこない場合は、勾配降下法の基礎 も合わせてどうぞ。

まず結論を一言で

謎の答えを先に言ってしまいます。LSTMが長期記憶を保てる理由は、たった一つの設計に集約されます。

過去の記憶 $C_{t-1}$ を、非線形関数に通さず、足し算の片側にそのまま置いた。

下の図が、LSTMの心臓部です。

LSTMのセル状態というベルトコンベアと、忘却ゲート・入力ゲートのバルブを表した概念図

セル状態 $C$ という1本の「ベルトコンベア」が左から右へ流れています。その上で起きる演算は、たった2つだけです。

  1. 忘却ゲート $f_t$ を掛ける($\times$)— コンベアの中身を「何割残すか」決めるバルブ
  2. 新しい情報を足す($+$)— 入力ゲートで絞った候補を上乗せする

この図から読み取ってほしい最大のポイントは、コンベア本体(横の流れ)には tanh も ReLU も挟まっていないということです。掛けて、足す。これだけ。この「非線形でぐしゃっと潰さない」ことが、後で見るように勾配を遠くまで届ける決定的な理由になります。

なぜこれが効くのか。それを理解するには、まず「効かない方」——普通のRNNがなぜ記憶を失うのかを、演算レベルで見ておく必要があります。

バニラRNNはなぜ忘れるのか — 「同じ数を掛け続ける」問題

普通のRNN(バニラRNN)の隠れ状態の更新は、こう書けます。

$$ \begin{equation} h_t = \tanh(w\, h_{t-1} + u\, x_t + b) \end{equation} $$

過去の状態 $h_{t-1}$ に重み $w$ を掛け、入力を足し、その全体を $\tanh$ という非線形関数に通します。問題は、この「掛けて、非線形に通す」を毎ステップ繰り返すことです。

いま入力の影響を無視して、記憶がどう伝わるかだけを追いましょう。$h_t \approx \tanh(w\, h_{t-1})$ です。これを $T$ ステップ繰り返すと、過去の記憶への感度(勾配)は、ざっくり

$$ \frac{\partial h_T}{\partial h_0} \approx \prod_{t=1}^{T} w \cdot \tanh'(\cdot) = w^T \cdot \prod_{t=1}^{T}\tanh'(\cdot) $$

という形になります。ここで効いてくるのが「同じ数 $w$ を $T$ 回掛ける」という構造です。等比数列を思い出してください。1より小さい数を何回も掛ければ0に吸い込まれ、1より大きい数を掛ければ無限大に発散します。

バニラRNNの勾配が同じ数wをT回掛けることで指数的に消失または爆発する様子

このグラフ(対数軸)から、問題の本質が一目でわかります。$w=0.9$ という、1にかなり近い値でさえ、40ステップ遡ると勾配は $0.9^{40} \approx 0.015$ まで縮みます。$w=0.6$ なら絶望的です。逆に $w=1.3$ では爆発します。ちょうど $w=1$ の細い綱の上だけが安定ですが、そこを狙って学習し続けるのは至難の業です。

しかも追い打ちがあります。$\tanh’$ は最大でも1、ふだんは1より小さい値です。だから $w=1$ にできたとしても、$\tanh’$ の積がさらに勾配を削っていきます。「同じ数を掛け続ける」構造に、「毎回1未満の非線形微分が掛かる」構造が重なって、記憶は指数的に薄れていく——これがバニラRNNが長期依存を学べない、演算レベルの正体です。

では、LSTMはこの「掛け続ける」呪いをどう解いたのでしょうか。中心の式だけを取り出して、電卓で追ってみます。

LSTMの中心式だけを取り出す

LSTMには4つの式(3ゲート+候補)がありますが、長期記憶の謎を解くのに本当に必要なのは、セル状態の更新式ただ1本です。

$$ \begin{equation} C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t \end{equation} $$

記号の意味を最小限だけ確認します。

  • $C_{t-1}$:前のステップから運ばれてきた記憶(ベルトコンベアの中身)
  • $f_t \in (0,1)$:忘却ゲート。過去の記憶を何割残すか
  • $i_t \in (0,1)$:入力ゲート。新しい情報を何割書き込むか
  • $\tilde{C}_t \in (-1,1)$:候補。今回書き込もうとしている新情報の中身
  • $\odot$:要素ごとの積(アダマール積)

$f_t, i_t, \tilde{C}_t$ がどう計算されるかは、いったん脇に置きます。大事なのは、この式が「古い記憶を $f_t$ 倍して、新しい情報を足す」という、掛け算と足し算だけでできていることです。バニラRNNと違って、$C_{t-1}$ は $\tanh$ の中に入っていません。$C_{t-1}$ は式の外側に、足し算の片側として剥き出しで置かれています。

この一見地味な違いが、順伝播と逆伝播の両方で効いてきます。まず順伝播から、実際に数値を入れて追いましょう。

演算追跡①:順伝播を電卓で追う

いちばん単純な状況を考えます。ベクトルではなくスカラー1個のセルにして、「$t=0$ で記憶 $C=1.0$ を書き込み、その後は新しい入力が来ない($i_t=0$)」とします。忘却ゲートは $f=0.98$ で一定としましょう。

すると更新式は $C_t = 0.98 \times C_{t-1} + 0 = 0.98\, C_{t-1}$ です。電卓で追うと、

$$ C_0 = 1.0,\quad C_1 = 0.98,\quad C_2 = 0.9604,\quad \dots,\quad C_{60} = 0.98^{60} \approx 0.298 $$

60ステップ経っても、最初に書き込んだ記憶の約30%が残っています。比較のため、同じ係数0.98でもバニラ風に毎ステップ $\tanh$ を挟んだ $h_t = \tanh(0.98\, h_{t-1})$ も並べてみます。

import numpy as np

T = 60
f = 0.98

# LSTMのセル状態:掛けて足すだけ(今回は足す分が0)
C = np.zeros(T + 1)
C[0] = 1.0
for t in range(1, T + 1):
    C[t] = f * C[t - 1] + 0.0   # i_t * 候補 = 0(新規入力なし)

# バニラ風:同じ0.98でも tanh を挟む
h = np.zeros(T + 1)
h[0] = 1.0
for t in range(1, T + 1):
    h[t] = np.tanh(0.98 * h[t - 1])

print(f"LSTM  C[60] = {C[60]:.3f}")   # -> 0.298
print(f"バニラ h[60] = {h[60]:.3f}")   # -> ほぼ0に潰れる

このコードを動かすと LSTM C[60] = 0.298、対してバニラ風の $h[60]$ はほぼ0に潰れます。

同じ係数0.98でもtanhを挟むと記憶が一気に潰れることを示す折れ線グラフ

グラフから読み取れることは決定的です。同じ0.98という係数を使っても、tanh を挟むか挟まないかで運命が分かれます。LSTMのセル状態(シアン)は素直に $0.98^t$ の指数で緩やかに減るだけ。一方バニラ風(赤破線)は、$\tanh$ が値を毎回 $(-1,1)$ に押し込めるせいで、減衰が加速して急速に0へ吸い込まれます。$\tanh$ は0付近では入力をほぼそのまま通しますが、それでも「掛けて圧縮」を繰り返すと、わずかな目減りが指数的に積み重なるのです。

ここで「記憶がどれくらい持つか」を決めているのは、明らかに忘却ゲートの値 $f$ です。$f$ を変えると記憶の寿命がどう変わるか、もう少し定量的に見てみましょう。

忘却ゲートは「記憶の半減期」を決めるダイヤル

入力なしで $C_t = f^t C_0$ なので、記憶が半分になるステップ数(半減期)は、$f^n = 0.5$ を解いて

$$ n = \frac{\log 0.5}{\log f} $$

と求まります。放射性物質の半減期とまったく同じ計算です。いくつかの $f$ で計算してみます。

import numpy as np

for f in [0.5, 0.9, 0.99]:
    n = np.log(0.5) / np.log(f)
    print(f"f={f}: 半減期 ≈ {n:.1f} ステップ")
# f=0.5 : 半減期 ≈ 1.0 ステップ
# f=0.9 : 半減期 ≈ 6.6 ステップ
# f=0.99: 半減期 ≈ 69.0 ステップ

忘却ゲートの値ごとに記憶の減衰曲線と半減期が変わる様子

このグラフが、LSTMの「記憶力」の正体です。$f=0.5$ なら記憶は1ステップで半分になり、すぐ消えます。$f=0.9$ で半減期は約6.6ステップ。そして $f=0.99$ になると半減期は約69ステップにも伸びます。忘却ゲートはまさに記憶の寿命を決めるダイヤルで、$f$ を1に近づけるほど、記憶は遠い未来まで保たれます。

しかも決定的に重要なのは、この $f$ が固定値ではなく、入力に応じてステップごとに学習・調整されることです。バニラRNNの $w$ が全ステップで共通の固定パラメータだったのに対し、LSTMは「いま重要な情報が来たから $f\approx1$ にして長く覚えよう」「もう不要だから $f\approx0$ で捨てよう」を、状況に応じて切り替えられます。これが「同じ数を掛け続ける」呪いを解く第一の鍵です。

順伝播で記憶が残ることは見えました。でも、ニューラルネットの学習で本当に効くのは逆伝播(勾配)です。「記憶が残る」と「勾配が遠くまで届く」は別の話に見えます。ここからが本題、なぜ足し算が勾配を救うのかを追います。

演算追跡②:逆伝播 — なぜ「足し算」で勾配が生き残るのか

学習とは、最終的な誤差(損失)を各時刻の状態で微分し、その勾配を過去へ遡って伝えていく作業です。バニラRNNではこの「遡り」の途中で勾配が消えました。LSTMではどうなるか。中心式を $C_{t-1}$ で微分してみます。

$$ C_t = f_t \odot C_{t-1} + i_t \odot \tilde{C}_t $$

ここで微分の基本に立ち返ります。足し算は項ごとにバラして微分できます(和の微分は微分の和)。そして第2項 $i_t \odot \tilde{C}_t$ は、$C_{t-1}$ とは直接関係のない量です(厳密には $f_t, i_t, \tilde{C}_t$ は $h_{t-1}$ 経由で $C_{t-1}$ に間接依存しますが、それは小さな脇道で、主役ではありません)。だから主要項だけ取り出すと、

$$ \begin{equation} \frac{\partial C_t}{\partial C_{t-1}} \approx f_t \end{equation} $$

これだけです。微分したら忘却ゲートそのものが残る。バニラRNNでは微分するたびに $w \cdot \tanh’$ という「1未満になりがちな邪魔者」が出てきましたが、LSTMの素通りレーンには $f_t$ を掛ける以外の演算がありません。

加法更新を微分すると勾配が忘却ゲートだけになり素通りレーンができることを示す図

この図が、謎の核心です。$C_t = f_t C_{t-1} + (\text{$C_{t-1}$と無関係な項})$ という足し算の形のおかげで、微分すると第2項はきれいに消え、$\partial C_t / \partial C_{t-1} = f_t$ だけが残ります。勾配にとって、セル状態は「$f_t$ を掛けるだけで通り抜けられる素通りレーン」になっているのです。バニラRNN(下の赤いレーン)が毎回 $\tanh’$ と $w$ という関所を通されるのと、好対照です。

では $T$ ステップ遡るとどうなるか。連鎖律で掛け合わせるだけです。

$$ \begin{equation} \frac{\partial C_T}{\partial C_t} \approx \prod_{k=t+1}^{T} f_k \end{equation} $$

勾配は忘却ゲートの積だけで決まります。バニラRNNの $w^T \prod \tanh’$ と見比べてください。違いは「掛けているものが何か」です。

バニラRNN LSTM(セル状態)
1ステップ遡る微分 $w \cdot \tanh'(\cdot)$ $f_t$
$T$ステップ遡る勾配 $\displaystyle w^T \prod \tanh'(\cdot)$ $\displaystyle \prod_{k} f_k$
掛ける値の正体 全ステップ共通の固定 $w$ + 1未満の $\tanh’$ 入力に応じて学習される $f_k$
長期記憶したいとき $w$ も $\tanh’$ も制御しづらい $f_k \approx 1$ を学習すればよい

LSTMでも「積」であることは変わりません。$f_k$ がすべて0.5なら勾配はやはり消えます。違いは、その積の各因子をネットワークが入力に応じて自由に設定できる点です。長期に覚えたい信号に対しては $f_k \approx 1$ を学習し、$\prod f_k \approx 1$ にして勾配を遠くまで素通しできます。実際に数値で確かめましょう。

import numpy as np

rng = np.random.default_rng(0)
T = 50

# LSTM: 「覚える」と学習した状態 → 忘却ゲートは1付近
f = np.clip(0.97 + 0.02 * rng.standard_normal(T), 0.0, 1.0)
lstm_grad = np.cumprod(f[::-1])   # 末尾から遡る積

# バニラ: w=1.0 にできても tanh' < 1 が連鎖
a = rng.standard_normal(T)
tanhp = 1 - np.tanh(a) ** 2
van_grad = np.cumprod((1.0 * tanhp)[::-1])

print(f"50ステップ遡った勾配  LSTM : {lstm_grad[-1]:.3e}")
print(f"50ステップ遡った勾配  バニラ: {van_grad[-1]:.3e}")

セル状態の勾配は忘却ゲートの積だけで決まりfが1に近ければ遠くまで届くことを示すグラフ

このグラフ(対数軸)で、LSTM(シアン)の勾配は50ステップ遡ってもほとんど減りません。$f_k \approx 0.97$ の積なので、$0.97^{50} \approx 0.22$ 程度の緩やかな減衰で済みます。一方バニラ(赤)は、$w=1$ にできていてもなお $\tanh’<1$ の積で勾配が桁違いに削られていきます。「足し算で素通りレーンを作り、その通行料 $f_k$ をネットワーク自身に決めさせる」——これがLSTMの長期記憶の演算レベルの正体です。

ここまでで「足し算」の威力はわかりました。でも式にはもう一つ、見慣れない記号 $\odot$ がありました。なぜ普通の掛け算ではなく「要素ごとの積」なのか。これにも明確な理由があります。

なぜ「要素ごとの積」$\odot$ なのか — 独立した記憶レーン

実際のLSTMでは、セル状態 $C_t$ はスカラーではなくベクトル(例:128次元)です。そして忘却ゲート $f_t$ も同じ次元のベクトルで、両者は要素ごとの積 $\odot$ で掛け合わされます。行列の掛け算ではありません。

これが何を意味するか。要素ごとの積では、$C_t$ の第 $j$ 成分は $C_{t-1}$ の第 $j$ 成分にしか依存しません。

$$ C_t^{(j)} = f_t^{(j)} \cdot C_{t-1}^{(j)} + i_t^{(j)} \cdot \tilde{C}_t^{(j)} $$

つまり、各次元が完全に独立した記憶配線になっているのです。次元1の記憶が次元2に漏れたり混ざったりしません。

要素ごとの積によって各次元が独立した記憶配線になることを示す図

この独立性が、表現力の上で絶大です。図のように、あるセル(次元)は $f=0.99$ で長期記憶専用のレーンになり、別のセルは $f=0.30$ で短期の作業メモリ、また別のセルは $f=0.05$ で「来たらすぐリセット」のフラグ用に——と、1つのLSTMの中で、異なる時間スケールの記憶を次元ごとに同時に持てるわけです。

もしここが行列積だったら、勾配の伝播は $\prod \bm{W}$ という行列の積になり、その固有値がふたたび「同じ行列を掛け続ける」呪いを呼び込んでしまいます。要素ごとの積にすることで、各次元の勾配が $\prod_k f_k^{(j)}$ という独立したスカラーの積に分解され、次元ごとに勾配の通り道がクリーンに保たれるのです。

さて、残るは「ゲートの値 $f_t, i_t$ はどうやって計算されるのか」です。ここでシグモイドと tanh が登場します。この2つの関数の使い分けにも、ちゃんと演算上の理由があります。

なぜゲートはシグモイド、候補は tanh なのか

ゲート $f_t, i_t, o_t$ はシグモイド $\sigma$ で、候補 $\tilde{C}_t$ は $\tanh$ で計算されます。

$$ f_t = \sigma(\bm{W}_f [\bm{h}_{t-1}, \bm{x}_t] + \bm{b}_f), \qquad \tilde{C}_t = \tanh(\bm{W}_C [\bm{h}_{t-1}, \bm{x}_t] + \bm{b}_C) $$

この関数選びは恣意的ではありません。それぞれの出力範囲が、果たすべき役割と一致しているのです。

シグモイドは0から1のバルブ、tanhはマイナス1から1の中身という役割分担を示すグラフ

  • シグモイド $\sigma$ の出力は $(0,1)$。これは「何割通すか」というバルブの開度として完璧です。0なら全閉(完全に忘れる/書き込まない)、1なら全開(完全に保持/全部書き込む)。忘却ゲートを $C_{t-1}$ に掛けたとき、$(0,1)$ の値なら記憶を増幅せず、必ず減衰側に働くので、順伝播が発散しません。ゲートに $(0,1)$ を使うのは、安定性のためにも必然です。

  • tanh の出力は $(-1,1)$。候補 $\tilde{C}_t$ は「メモリに書き込む中身そのもの」なので、正にも負にもなれる必要があります。$(-1,1)$ に収めることで、書き込む値の大きさが暴れず、セル状態が一度に大きく振れるのを防ぎます。

バルブはシグモイドで0〜1、中身はtanhで±1」——この役割分担を押さえると、4本の式が「なぜその関数なのか」まで含めてスッキリ見えてきます。

理屈はそろいました。最後に、本物のネットワークでBPTTの勾配を実測し、「LSTMの勾配は本当に遠くまで届くのか」を自分の目で確かめましょう。

ネットワークで実測する:勾配は本当に遠くまで届くか

スカラーの思考実験ではなく、多次元のLSTMセルとバニラRNNセルを実装し、最終ステップで生じた損失の勾配が、各時刻の状態にどれだけの大きさで届くかを PyTorch の自動微分で測ります。これがいわゆる勾配消失の直接観測です。

考えるタスクは「長期依存」の典型です。系列の最初の値を、ずっと後のステップで思い出して答える——間に無関係なノイズが挟まるほど、記憶の保持が難しくなります。

系列の最初の値を9ステップ後に思い出す長期依存タスクの説明図

この図のように、$t=0$ の情報を最後まで運べるかが勝負です。では、ランダム初期化したLSTMとバニラRNNに長さ40の系列を流し、最終ステップの出力から逆伝播して、各時刻の状態が受け取る勾配ノルムを測ります。

import numpy as np
import torch

torch.manual_seed(0)
T, B, H = 40, 16, 16
x = torch.randn(T, B, 1)

# --- バニラRNN ---
Wx = torch.randn(1, H) * 0.5
Wh = torch.randn(H, H) * (1.0 / np.sqrt(H))
bh = torch.zeros(H)
for p in (Wx, Wh, bh):
    p.requires_grad_(True)

hs, h = [], torch.zeros(B, H)
for t in range(T):
    h = torch.tanh(x[t] @ Wx + h @ Wh + bh)
    h.retain_grad()
    hs.append(h)
hs[-1].pow(2).sum().backward()           # 最終ステップから逆伝播
van = np.array([hs[t].grad.norm().item() for t in range(T)])
# --- LSTM(忘却バイアス +1.0 で記憶寄りに初期化)---
torch.manual_seed(1)
def W():
    w = torch.randn(1 + H, H) * (1.0 / np.sqrt(1 + H))
    return w.requires_grad_(True)
Wf, Wi, Wc, Wo = W(), W(), W(), W()

h, C, Cs = torch.zeros(B, H), torch.zeros(B, H), []
for t in range(T):
    z = torch.cat([x[t], h], dim=1)
    f = torch.sigmoid(z @ Wf + 1.0)      # 忘却ゲート(バイアス +1)
    i = torch.sigmoid(z @ Wi)
    g = torch.tanh(z @ Wc)
    o = torch.sigmoid(z @ Wo)
    C = f * C + i * g                    # ★ 掛けて足す素通りレーン
    C.retain_grad()
    h = o * torch.tanh(C)
    Cs.append(C)
h.pow(2).sum().backward()
lstm = np.array([Cs[t].grad.norm().item() for t in range(T)])

# 最終ステップを1として正規化(遡るほど何倍減るか)
print(f"バニラ 初期/最終 勾配比: {van[0]/van[-1]:.3e}")   # -> 約 3.0e-03
print(f"LSTM   初期/最終 勾配比: {lstm[0]/lstm[-1]:.3e}")  # -> 約 2.3e-02

実行すると、最終ステップを基準にして40ステップ遡ったときの勾配は、バニラRNNが約 $3.0\times10^{-3}$(約330分の1に減衰)なのに対し、LSTMは約 $2.3\times10^{-2}$(約44分の1)。同じ40ステップ遡っても、LSTMの方が初期時刻に約8倍大きい勾配を届けています

BPTTの勾配がバニラRNNでは初期に向けて急減し、LSTMではほぼ平坦に届く比較グラフ

グラフ(対数軸)で形を見ると、違いはさらに明確です。LSTM(シアン)はほぼ一直線で、初期時刻まで緩やかにしか減りません。$\prod f_k$ という素通りレーンが効いている証拠です。一方バニラRNN(赤)は途中から急激に落ち込み、序盤(左側)では勾配がほとんど消えています。「最初の方の入力をどう使えば損失が下がるか」という情報が、バニラRNNにはほとんど届いていない——だから長期依存を学習できないのです。

このLSTMの勾配の届き方は、初期化次第でさらに伸ばせます。最後に、実務で必ず使われる小技の意味を、同じ測定で確かめます。

忘却ゲートのバイアス初期化が効く理由

上のコードで、忘却ゲートに + 1.0 というバイアスを足していたのに気づいたでしょうか。$\sigma(0)=0.5$ ですが、$\sigma(1)\approx0.73$、$\sigma(2)\approx0.88$ です。つまり忘却ゲートのバイアスを正の値で初期化すると、学習の最初から $f_t$ が1寄りになり、デフォルトで「よく覚える」状態からスタートできます。バイアスを負にすると逆に忘れっぽくなります。

忘却ゲートのバイアス初期化で勾配の届く距離が変わることを示すグラフ

このグラフは、忘却バイアスを $+1$(緑)にした場合と $-2$(アンバー)にした場合の勾配の届き方を比べたものです。$b_f=+1$ では勾配が初期時刻まで素直に届くのに対し、$b_f=-2$ では序盤で勾配が大きく落ち込みます。$f_t$ が小さいと $\prod f_k$ が小さくなり、素通りレーンが詰まるからです。

これが、多くのLSTM実装で忘却ゲートのバイアスを1〜2程度に初期化するのがデファクトになっている理由です(Jozefowicz らが2015年に効果を報告)。学習の初期に勾配を遠くまで流しておけば、ネットワークは「どの記憶を長く保つべきか」を学ぶスタート地点に立てます。逆に最初から $f\approx0.5$ だと、$0.5^{40}$ で勾配が消え、長期依存の学習がそもそも始まりません。

ところで、ずっと「ネットワークが $f_t\approx1$ を学習する」と言ってきましたが、ゲートはどうやって「ここは覚えるべき」と気づくのでしょうか。最後にその循環を確認します。

ゲートは「覚えるべき」をどう学ぶのか

仕組みは美しい循環になっています。

  1. ある長期依存(最初の入力が最後の答えを決める)を含むデータで学習する
  2. その依存を使えれば損失が下がるので、最終ステップの損失は「序盤の $C_t$ をもっと保持してほしい」という勾配を生む
  3. その勾配は、素通りレーン $\prod f_k$ を通って序盤まで届く(バニラRNNではここで消える)
  4. 届いた勾配が、忘却ゲートの重み $\bm{W}_f$ を「その状況では $f_t$ を大きくする」方向に更新する
  5. 結果、ネットワークは「この種の情報が来たら長く覚える」というルールを獲得する

ポイントは、「勾配が遠くまで届く」こと自体が、「遠くの依存を学習できる」ことの前提になっている点です。バニラRNNは3でつまずくので、たとえ長期依存がデータにあっても、それを掴むための勾配が届かず、永遠に学べません。LSTMは加法更新で勾配の高速道路を確保したから、「何を長く覚えるべきか」をデータから学ぶことができる——これが、アーキテクチャ図だけでは見えない、演算レベルの本当の答えです。

まとめ

「なぜLSTMは長期記憶を保てるのか」という謎を、計算式のロジックまで分解してきました。答えは、つきつめると以下に集約されます。

  • 加法更新:$C_t = f_t C_{t-1} + i_t \tilde{C}_t$ は、過去の記憶を非線形に通さず足し算の片側に置く。微分すると第2項が消えて $\partial C_t/\partial C_{t-1}=f_t$ だけが残り、勾配の「素通りレーン」ができる。
  • 忘却ゲートの積:$T$ステップ遡る勾配は $\prod f_k$。バニラRNNの $w^T\prod\tanh’$ と違い、各因子をネットワークが入力に応じて決められるので、$f_k\approx1$ を学習すれば勾配を遠くまで届けられる。
  • 要素ごとの積:各次元が独立した記憶レーンになり、長期・短期・即リセットを1つのモデルで同時に持てる。行列積の固有値問題を回避する。
  • シグモイドとtanh:バルブは $(0,1)$、書き込む中身は $(-1,1)$ という出力範囲が、役割と安定性の両方に合っている。
  • 忘却バイアス初期化:$b_f$ を正にして $f$ を1寄りで始めれば、学習初期から勾配の高速道路が開通する。

この「足し算で恒等的な素通りレーンを作る」という発想は、LSTM固有のものではありません。ResNetの $\bm{x}+F(\bm{x})$、Transformerの残差接続、GRUの更新ゲート、状態空間モデルの線形再帰——現代の深いモデルはどれも、形を変えて同じ原理を使っています。「勾配を非線形に潰さず素通りさせる経路を確保する」。これが深層学習で長い依存・深い層を扱うための、共通の鍵なのです。

次のステップとして、以下の記事もおすすめです。

画像なし
LSTMの理論と仕組みを徹底解説 — ゲート機構から勾配の流れまで
LSTMの3つのゲートとセル状態の役割、勾配が安定する理由を数式とアーキテクチャから網羅的に解説します。
画像なし
GRUの理論と実装 — LSTMとの違いとゲート統合の仕組みを解説
LSTMの忘却・入力ゲートを更新ゲートに統合したGRUの仕組みを、LSTMとの対比で解説します。