10 人が閲覧(直近 30 日) AI

LSTMとは?仕組み・数式とRNN・GRU・Transformerとの違い、PyTorch・Keras実装

LSTMとは?仕組み・数式とRNN・GRU・Transformerとの違い、PyTorch・Keras実装

LSTM(Long Short-Term Memory、長短期記憶)は、時系列や文章のように順序を持つデータを扱うRNN(再帰型ニューラルネットワーク)の一種です。RNNが苦手だった「何十ステップも前の情報を覚えておく」処理を、セルステートと呼ぶ記憶の通り道と、忘却・入力・出力の3つのゲートで実現します。この記事では仕組みと数式、パラメータ数、学習の進め方、RNN・GRUとの実測比較、Transformerとの使い分けを、原論文と公式ドキュメントに沿って解説します。

まとめ:LSTMの要点

  • 正体:1997年に Hochreiter と Schmidhuber が発表したRNNの改良型。今「LSTM」と呼ばれる形は、2000年に忘却ゲートが加わった構成です。
  • 仕組み:セルステートを足し算で更新し、3つのゲート(0〜1の開度)で書き込み・保持・読み出しを制御します。この足し算の経路が勾配消失を抑えます。
  • 実測での差:学習前のLSTMが30ステップ前まで届ける勾配は、PyTorchの既定の初期化ではGRUと同水準まで消え、忘却ゲートのバイアスを1にすると約1万倍に増えました(後述)。
  • 弱点:1本の系列の中では時刻を1つずつ順に計算するため、系列方向に並列化できません。バッチ方向の並列化はできますが、大規模な言語モデルではTransformerに主役を譲りました。
  • 今使う場面:データが少ない時系列予測や、メモリ一定で逐次処理したいストリーミング・組み込み用途。

LSTM(長短期記憶)の定義と勾配消失問題

LSTMの名称と「長短期記憶」の意味

RNNは前の時刻の隠れ状態を次の時刻へ渡すループ構造で系列を処理します。隠れ状態は理論上は過去の情報を持ち越せますが、学習では遠い時刻との関係を捉えにくく、実際に使えるのは直近の情報、つまり短期記憶に偏ります。LSTMはこの短期記憶(隠れ状態)とは別に、情報を長く運ぶ経路(セルステート)を設けました。「短期記憶を長く保つ」という意味の命名で、日本語では「長短期記憶」「長・短期記憶」と訳されます。

勾配消失問題:RNNが長期依存を学べない理由

RNNは、誤差を時間方向にさかのぼって伝える通時的誤差逆伝播(BPTT)で学習します。さかのぼるたびに同じ重み行列と活性化関数の微分が掛け算されるため、その大きさが1を下回ると勾配は指数的に小さくなり、数十ステップ前にはほぼ0になります。これが勾配消失で、逆に1を上回ると発散します(勾配爆発)。この現象は Hochreiter が1991年の卒業論文で分析し、1997年のLSTM論文の出発点になりました。LSTMはセルステートを、忘却ゲートとの掛け算に新しい情報の足し算を組み合わせて更新します。忘却ゲートが1に近い間は勾配がほぼ減衰せずに流れる経路(定誤差カルーセル)になり、勾配消失が緩和されます。原論文の要旨は、1000ステップを超える時間差でも学習できると述べています(Hochreiter & Schmidhuber, Neural Computation 9(8), 1997)。

LSTMの構造:セルステートと3つのゲート

忘却ゲート・入力ゲート・出力ゲートの役割

セルステートへの出し入れを、シグモイド関数で0〜1の開度を出す3つのゲートが制御します。0なら遮断、1なら全通しで、開度そのものを学習するのがLSTMの要点です。

  • 忘却ゲート f:前のセルステートをどれだけ残すか。文の主語が変わったら古い主語の情報を消す、といった働きをします。
  • 入力ゲート i:新しい候補 g をどれだけセルステートへ書き込むか。
  • 出力ゲート o:セルステートのどの成分を、この時刻の出力(隠れ状態 h)として外に出すか。

ゲートの入力はどれも「前時刻の隠れ状態 h と今の入力 x」です。4つの全結合(3ゲート+候補g)が並列に計算され、その結果でセルステートと隠れ状態が更新されます。

数式で見るLSTMの1ステップ

時刻 t の計算は次の6式です(σはシグモイド、⊙は要素ごとの積)。PyTorchの torch.nn.LSTM の公式ドキュメントも、バイアスを入力側と再帰側の2組に分けている点を除けば同じ式です。

f_t = σ(W_f x_t + U_f h_{t-1} + b_f)    # 忘却ゲート
i_t = σ(W_i x_t + U_i h_{t-1} + b_i)    # 入力ゲート
g_t = tanh(W_g x_t + U_g h_{t-1} + b_g) # セル候補(書き込む中身)
o_t = σ(W_o x_t + U_o h_{t-1} + b_o)    # 出力ゲート
c_t = f_t ⊙ c_{t-1} + i_t ⊙ g_t         # セルステートの更新
h_t = o_t ⊙ tanh(c_t)                   # 隠れ状態(この時刻の出力)

核心は c_t の式です。前のセルステートに忘却ゲートを掛けて取捨選択し、入力ゲートで絞った候補を足すだけの構造なので、忘却ゲートが1に近い間は勾配がほぼそのまま過去へ流れます。

パラメータ数の計算式と実測値

入力の次元を n、隠れ状態の次元を m とすると、4つの全結合それぞれが入力側 m×n、再帰側 m×m の重みとバイアスを持ちます。KerasのLSTMはバイアスが1組なので 4×(m×(n+m)+m)、PyTorchは入力側と再帰側にバイアスを別々に持つため 4×m×(n+m)+8m です。n=10、m=50で実際に数えた結果は次のとおりです(2026年10月、PyTorch 2.14.1とKeras 3.15.1で実測)。

層(入力10・隠れ50) PyTorch Keras 3
単純なRNN 3,100 3,050
GRU 9,300 9,300
LSTM 12,400 12,200

同じ隠れ次元なら、LSTMは単純なRNNの約4倍、GRUの約4/3倍のパラメータを持ちます。PyTorchとKerasで数が200ずれるのはバイアスの持ち方の違いです(KerasのGRUは既定の reset_after=True でバイアスを2組持つため、PyTorchと同数になります)。積層すると2層目の入力は1層目の隠れ次元になるため、Kerasで50→50の2層目は20,200になります。

LSTMの学習方法:BPTT・勾配クリッピング・ドロップアウト

BPTTと打ち切りBPTT

LSTMも学習の基本はRNNと同じBPTTです。系列を時間方向に展開した1本の深いネットワークとみなし、誤差を全時刻へ逆伝播します。長い系列をそのまま展開するとメモリが足りなくなるため、実務では系列を数十〜数百ステップの窓に区切って逆伝播する打ち切りBPTT(truncated BPTT)が使われます。窓より遠い依存は勾配では学べないので、窓の長さは「予測に効く過去の範囲」より長く取ります。

勾配クリッピングと忘却ゲートの初期化

勾配消失はLSTMで緩和されますが、勾配爆発は残ります。勾配のノルムが閾値を超えたら閾値まで縮める勾配クリッピングを併用するのが定番です(Pascanu et al., ICML 2013)。PyTorchの torch.nn.utils.clip_grad_norm_ は全パラメータをまとめたノルムで縮めます。Kerasで同じ動作にするのはオプティマイザの global_clipnorm 引数で、clipnorm は重みごとに個別に縮めます。

もう1つの定石が、忘却ゲートのバイアスを1で初期化することです。Jozefowicz らは、この設定でLSTMとGRUの性能差が縮まったと報告しています(ICML 2015)。Kerasの LSTM は unit_forget_bias=True が既定ですが、PyTorchの nn.LSTM にはこの設定が無いため、自分で書き込みます。PyTorchのバイアスは入力・忘却・セル候補・出力の順に並んでいるので、2番目の区間が忘却ゲートです。

import torch
import torch.nn as nn

lstm = nn.LSTM(input_size=10, hidden_size=50, batch_first=True)
h = lstm.hidden_size
with torch.no_grad():
    lstm.bias_ih_l0[h:2*h].fill_(1.0)   # 忘却ゲートの区間だけ1にする
    lstm.bias_hh_l0[h:2*h].fill_(0.0)   # バイアスは2組あるので片方は0

この例は1層・単方向です。num_layers を2以上にした場合や双方向の場合は、bias_ih_l1 や bias_ih_l0_reverse など層・方向ごとのバイアスにも同じ設定をします。

PyTorchとKerasのドロップアウト適用位置

過学習対策のドロップアウトは、2つのフレームワークで掛かる場所が違います。PyTorchの dropout 引数は「最後の層を除く各LSTM層の出力」に掛かるため、num_layers=1 では効かず、設定すると警告が出ます。1層なら出力の後に nn.Dropout を置きます。Kerasは入力側の dropout と再帰側の recurrent_dropout を分けて指定でき、recurrent_dropout を0より大きくすると後述のcuDNN高速実装が使えなくなります。

LSTMの歴史:1997年の原型と忘却ゲートの追加

前出の6式は最初から揃っていたわけではありません。1997年の原型LSTMには忘却ゲートがなく、入力ゲート・出力ゲートと定誤差カルーセルだけで構成されていました。セルステートを一度も忘れないため、区切りのない長いデータを流し続けると値が蓄積して破綻する弱点がありました。

これを解決したのが Felix Gers・Jürgen Schmidhuber・Fred Cummins の「Learning to Forget」(Neural Computation 12(10), 2000、1999年に会議発表)で、ここで忘却ゲートが導入されました。同じ頃、ゲートがセルステートを直接参照する「のぞき穴(peephole)接続」も提案されています。

どの改良が効いているのかは、Greff らが8種類の変種を音声認識・手書き文字認識・音楽モデリングの3課題で比較したLSTMの変種の大規模比較(IEEE TNNLS, 2017)が答えています。結論は「どの変種も標準のLSTMを有意に上回らない」「最も重要な部品は忘却ゲートと出力の活性化関数」でした。peephole接続は今のPyTorch・Kerasの標準LSTMには入っていません。

RNN・LSTM・GRUの違い

RNN・LSTM・GRUのゲートと状態の比較

GRU(Gated Recurrent Unit)は、Cho らが2014年に機械翻訳の論文(arXiv:1406.1078)で提案した簡略版です。忘却ゲートと入力ゲートを1つの更新ゲートにまとめ、セルステートを廃して隠れ状態1本にしました。

項目 RNN LSTM GRU
ゲート なし 忘却・入力・出力 リセット・更新
保持する状態 h h と c h
全結合の組数 1 4 3
長期依存の学習 苦手 得意 得意
提案 1980年代 1997年 2014年

「全結合の組数」が、重みの数と主要な行列演算の量のおおよその比になります(バイアスの持ち方やゲートの要素ごとの演算の分だけ、厳密な整数倍にはなりません)。単純なRNNを新規に採用する場面はほぼなく、実務の選択肢はLSTMかGRUです。

過去へ届く勾配の実測:RNN・GRU・LSTM

勾配消失を数字で確かめるため、学習前の各モデル(入力1次元・隠れ次元32)に長さTの乱数系列を入れ、最終時刻の出力から各時刻の入力へ流れる勾配の大きさを測りました。表は「先頭の時刻に届いた勾配÷末尾の時刻の勾配」で、1に近いほど遠い過去まで学習信号が届きます。入力は標準正規分布の乱数256系列、勾配は「最終時刻の出力の2乗和」を各時刻の入力で微分した値の絶対値の平均で、表の値は乱数シード5本の中央値です(PyTorch 2.14.1・CPU)。

モデル T=10 T=30 T=100
RNN 1.9e-3 3.6e-8 5.5e-24
GRU 3.0e-3 3.6e-7 1.2e-20
LSTM(PyTorch既定) 5.7e-3 4.1e-7 1.1e-20
LSTM(忘却バイアス1) 1.5e-1 5.1e-3 1.9e-7
LSTM(忘却バイアス3) 1.45 1.35 2.0e-1

PyTorchは重みもバイアスも ±1/√(隠れ次元) の一様分布で初期化するため、学習前の忘却ゲートの開度は平均して約0.5です。毎ステップ半分ずつ忘れる状態なので、学習前のLSTMはRNNやGRUと同じく、系列が長くなるほど桁違いに勾配を失います。忘却ゲートのバイアスを1にするとT=30で約1万倍、3にするとT=100でも末尾の2割の勾配が先頭まで届きました。つまりLSTMの長期記憶は構造だけで自動的に得られるものではなく、忘却ゲートが1に近い値を取ったときに働きます。Kerasが unit_forget_bias=True を既定にしているのはこのためで、PyTorchで長い依存を学ばせるなら、前出の「勾配クリッピングと忘却ゲートの初期化」の方法でバイアスを上げておきます。

なお、先頭の値を当てさせる課題を同じ3モデルで1,500ステップ学習させた小実験(Adam・学習率0.01、テスト誤差0.1未満を成功とした)では、T=30以上でどのモデルも安定して解けず、シード3本で成功したのはGRUの1本だけでした。短い学習で「LSTMとGRUのどちらが上か」を決めると初期値の運に左右されるため、両方を同じ条件で複数回学習し、検証誤差と推論時間で選びます。

PythonでのLSTM実装:PyTorchとKeras 3

PyTorch(nn.LSTM)での実装と出力の形

nn.LSTM は全時刻の出力と、最終時刻の隠れ状態 h_n・セルステート c_n を返します。batch_first=True で入力を(バッチ, 時刻, 特徴量)の順にそろえ、最終時刻の出力を全結合層へ渡すのが回帰・分類の基本形です。

import torch
import torch.nn as nn

class LSTMRegressor(nn.Module):
    def __init__(self, n_features=10, hidden=50, layers=2):
        super().__init__()
        self.lstm = nn.LSTM(n_features, hidden, num_layers=layers,
                            batch_first=True, dropout=0.2)
        self.fc = nn.Linear(hidden, 1)

    def forward(self, x):                 # x: (batch, 時刻, 特徴量)
        out, (h_n, c_n) = self.lstm(x)
        return self.fc(out[:, -1])        # 最終時刻の出力だけを使う

model = LSTMRegressor()
x = torch.randn(4, 30, 10)
out, (h_n, c_n) = model.lstm(x)
print(out.shape, h_n.shape, c_n.shape)

実行すると torch.Size([4, 30, 50]) torch.Size([2, 4, 50]) torch.Size([2, 4, 50]) と表示されます。h_n と c_n の先頭次元は「方向数×層数」で、bidirectional=True にすると出力の最後の次元が2倍(この例なら100)になります。

Keras 3(TensorFlow)での実装とcuDNNの条件

Keras 3では入力の形を keras.Input で宣言します。従来の書き方の LSTM(50, input_shape=(30, 10)) も動きますが、Keras 3.15.1では「Sequentialモデルでは最初の層にInput(shape)を置くこと」という警告が出ます。LSTMを積むときは、下の層に return_sequences=True を付けて全時刻の出力を渡します。

import keras
from keras import layers

model = keras.Sequential([
    keras.Input(shape=(30, 10)),               # (時刻, 特徴量)
    layers.LSTM(50, return_sequences=True),    # 全時刻を次の層へ
    layers.LSTM(50),                           # 最終時刻だけを出力
    layers.Dense(1),
])
model.compile(optimizer=keras.optimizers.Adam(global_clipnorm=1.0), loss="mse")
model.summary()

TensorFlowバックエンドでGPUを使うとき、Kerasは条件を満たせば高速なcuDNN実装に自動で切り替えます。Keras公式ドキュメントが挙げる条件は、activation がtanh、recurrent_activation がsigmoid、recurrent_dropout が0、unroll がFalse、use_bias がTrue、マスクを使うなら有効なデータの後ろだけを埋める右パディング(strictly right-padded)、の6つ(加えて最外のコンテキストがeager実行)です。学習が遅いときは、まず recurrent_dropout を設定していないかを確認します。Kerasの位置づけや版の事情はKeras 3とTensorFlowの関係で整理しています。

積層・双方向・CNN-LSTMの構成

層を重ねる積層LSTM(stacked LSTM)は、PyTorchなら num_layers、Kerasなら return_sequences=True の層を並べて作ります。まず2層程度で試し、深く積む場合は後述のGNMTのように層の間へ残差接続を入れる構成が使われます。文全体を見てから判断する固有表現抽出や文分類では、前後両方向から読む双方向LSTM(PyTorchは bidirectional=True、Kerasは layers.Bidirectional(layers.LSTM(...)))が効きます。時系列の将来予測で使う場合は、入力窓を予測時点より前の観測値だけで作ります。予測時点以降の値が入力に混ざると、本番では手に入らない情報で学習することになります。画像や波形にはCNNで局所的な特徴を抜き出してからLSTMへ渡すCNN-LSTMが使われ、動画の行動認識やセンサー波形の分類が代表例です。ニューラルネットワーク全般の部品と学習の流れはニューラルネットワークの仕組みとPyTorch実装で扱っています。

LSTMの応用事例

LSTMが本格的に製品へ入ったのは2010年代半ばです。代表例がGoogleのニューラル機械翻訳(GNMT)で、2016年の論文はエンコーダ8層・デコーダ8層のLSTMにアテンションと残差接続を組み合わせ、単文を人手で並べて比べる評価で、従来のフレーズベース方式より翻訳誤りを平均60%減らしたと報告しています(Wu et al., arXiv:1609.08144)。音声認識や手書き文字認識にも、同じ時期にLSTMが広く使われています。

今も現役なのが時系列です。需要・売上・電力・センサー値のように、過去の値の並びから次を予測する用途ではLSTMやGRUが選択肢に入ります。ただし季節性が強く系列が短い場合はARIMAなど統計モデルの方が安定することも多く、手法の使い分けは時系列分析の手法(ARIMAからPython実装まで)や需要予測アルゴリズムの選び方と実装手順で比較しています。自社の販売・在庫データで予測モデルを作る場合は、AI予測分析・需要予測の開発支援もご相談いただけます。

LSTMの欠点とTransformerとの違い

LSTMの欠点:系列方向の並列化の制約

LSTMは時刻 t の計算に t−1 の結果が必要なので、1本の系列の中では時刻方向に並列化できません。複数の系列をまとめて処理するバッチ方向の並列化はできますが、GPUが得意な大きな行列演算にまとめにくく、長い系列ほど学習時間が伸びます。また過去の情報はすべて固定長のセルステートに押し込まれるため、数千トークン前の特定の単語を正確に参照するのは苦手です。パラメータが同じ隠れ次元のRNNの4倍ある点も、小規模データでは過学習の原因になります。

Transformerとの比較:計算量と使い分け

2017年のTransformer論文(Vaswani et al., Attention Is All You Need)は、再帰を使わず自己注意だけで系列を処理する構成です。同論文のTable 1は層の種類ごとの計算量を次のように比べています(n=系列長、d=表現の次元)。

層の種類 1層の計算量 逐次演算の数 最長の経路長
自己注意(Transformer) O(n²·d) O(1) O(1)
再帰(RNN・LSTM) O(n·d²) O(n) O(n)

逐次演算がO(1)なので全時刻を一度に学習でき、離れた2点が1ステップでつながるため長距離の依存も直接参照できます。これが大規模言語モデルがTransformerへ移った理由です。一方で、全トークン同士の自己注意は計算量が系列長の2乗で増えます。文章を1トークンずつ生成する推論でKVキャッシュを使う場合は、過去のトークン分のキャッシュが系列長に比例して増えます。LSTMは1ステップの計算も保持する状態のサイズも系列長によらず一定です。

判断の目安は次のとおりです。テキスト生成・翻訳・要約など言語タスクは、事前学習済みのTransformerが第一候補です。長い系列を一定のメモリで高速に推論したいといった制約があるときに、xLSTMのような再帰型の言語モデルが比較対象に入ります。学習データが限られる時系列予測や異常検知、マイコンやエッジ端末でセンサー値を1点ずつ処理する用途はLSTM・GRUが向きます。Transformer自体の仕組みはTransformerの自己注意の仕組みで解説しています。

2024年のxLSTM:LSTMの再設計

2024年には、LSTM原案者の Hochreiter を含むチームがxLSTMを発表しました(Beck et al., arXiv:2405.04517、NeurIPS 2024採択)。ゲートを指数関数にして正規化・安定化を加え、スカラーのメモリに新しいメモリ混合を入れた sLSTM と、行列のメモリを持ち完全に並列化できる mLSTM の2種類のセルを組み合わせます。LSTM最大の欠点だった並列学習の壁を mLSTM で崩し、TransformerやState Space Modelと性能・スケーリングで張り合えると報告しています。2025年3月には70億パラメータの言語モデル xLSTM 7B も公開され、著者らは系列長に対して計算量が線形に増え、メモリ使用量が一定である点を推論の速さの根拠に挙げています(arXiv:2503.13427)。

よくある質問

LSTMはいつ、誰が開発しましたか?

Sepp Hochreiter と Jürgen Schmidhuber が1997年に Neural Computation 誌で発表しました。今の標準形に含まれる忘却ゲートは、2000年に Felix Gers らが追加したものです。

LSTMとRNNの違いを一言でいうと何ですか?

LSTMもRNNの一種です。単純なRNNは隠れ状態1本で過去を持ち越すため、学習で遠い時刻との関係を捉えにくくなります。LSTMはゲートで制御するセルステートを別に持ち、勾配が過去へ届きやすい分、長い依存を学習しやすくなります。

LSTMとGRUはどちらを使うべきですか?

どちらが常に上ということはありません。GRUの方が約4分の3と軽いので、両方を同じ条件で学習し、検証誤差で決めます。

LSTMのドロップアウトはどこに掛ければよいですか?

PyTorchの dropout 引数は2層以上の層間にだけ掛かります。Kerasは入力側と再帰側を分けて指定できますが、GPUでは recurrent_dropout を0に保つとcuDNN高速実装が使えます。

LSTMはもう古い技術ですか?

言語モデルの主役はTransformerに移りましたが、少量データの時系列予測や逐次処理の組み込み用途では現役です。2024年には並列学習できるxLSTMも登場しています。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.27 テックブログ Brotli 脆弱性:CVE-2026-111497の影響確認とNode.js・Python・.NETの更新手順
  2. 2025.02.27 コラム トラッキングビーコン(Webビーコン)とは?仕組み・用途・確認と対策を徹底解説
  3. 2026.10.27 テックブログ Joshin(ジョーシン)不正アクセス:最大600万件の対象とサブスク初期パスワードの対処
  4. 2026.10.28 テックブログ リンツ不正アクセス:314万件の対象確認とパスワード強制リセット後の対処
  5. 2026.10.23 テックブログ Renta!はいつ再開?不正アクセスでメールアドレス等が流出したおそれ・再開時のパスワード再設定と運営側の対応

RELATED POSTS 関連記事

目次