STEP 22:LSTM(Long Short-Term Memory)

🧠 STEP 22: LSTM(Long Short-Term Memory)

長期記憶と短期記憶を使い分ける!勾配消失問題を解決

📋 このステップで学ぶこと

  • LSTMとは何か?なぜ必要か?
  • セルステート(Cell State)の概念
  • 3つのゲート(忘却・入力・出力)
  • LSTMの計算フロー
  • Kerasでの実装方法
  • 時系列予測の実践

🧠 1. LSTMとは何か?

1-1. LSTMの登場背景

LSTM(Long Short-Term Memory)は、1997年にHochreiterとSchmidhuberによって提案された、勾配消失問題を解決するためのRNNアーキテクチャです。

📚 図書館の例え

SimpleRNN:メモ帳だけで作業
→ 新しい情報を書くと古い情報が消えてしまう

LSTM:メモ帳 + 長期保存用のファイル
→ 重要な情報はファイルに保存
→ 不要な情報はファイルから削除
→ 必要に応じてファイルから取り出して使用

これにより、長期的な依存関係を学習できる!

1-2. SimpleRNNとの比較

📊 SimpleRNN vs LSTM

SimpleRNN:
・隠れ状態(h)のみで情報を保持
・長いシーケンスで勾配消失
・短期的な依存関係のみ学習可能

LSTM:
・隠れ状態(h)+ セルステート(c)
・ゲート機構で情報の流れを制御
・長期的な依存関係も学習可能

⚙️ 2. LSTMの構造

2-1. セルステート(Cell State)

セルステートは、LSTMの「長期記憶」を担う経路です。
情報が変更されにくい「高速道路」のように、勾配がそのまま流れます。

以下の図は横スクロールできます。

【LSTMのセルステート】 c_{t-1} ──────────────────────────────────→ c_t ↑ ↑ [忘却] [追加] │ │ ┌───────┴──────────┴───────┐ │ │ │ LSTM セル │ │ │ └───────┬──────────┬───────┘ ↑ ↓ h_{t-1} ──────┘ └──────→ h_t ↑ x_t c = セルステート(長期記憶):情報が変更されにくい経路 h = 隠れ状態(短期記憶):現在の出力を決める

2-2. 3つのゲート

LSTMは3つのゲートで情報の流れを制御します。

ゲート 役割 出力範囲
忘却ゲート(Forget Gate) 古い情報をどれだけ「忘れる」か 0〜1(0=完全に忘れる、1=完全に保持)
入力ゲート(Input Gate) 新しい情報をどれだけ「記憶」するか 0〜1(0=無視、1=完全に記憶)
出力ゲート(Output Gate) セルステートからどれだけ「出力」するか 0〜1(0=出力しない、1=全て出力)

2-3. 各ゲートの働き

【LSTMゲートの働き(文章処理の例)】 入力文:「昨日、東京で美味しいラーメンを食べた。今日は」 ■ 忘却ゲート(Forget Gate) 「今日は」が入力されたとき… →「昨日」は関係なくなるかも → 忘れる(f ≈ 0) →「ラーメン」はまだ関係あるかも → 保持(f ≈ 1) ■ 入力ゲート(Input Gate) 「今日は」という新しい情報を… → 重要なので記憶する(i ≈ 1) ■ 出力ゲート(Output Gate) 次の単語を予測するために… →「ラーメン」の情報を出力(o ≈ 1) → 結果:「お腹がいっぱい」を予測

📐 3. LSTMの計算式

📐 LSTMの計算ステップ

1. 忘却ゲート:
f_t = σ(W_f × [h_{t-1}, x_t] + b_f)

2. 入力ゲート:
i_t = σ(W_i × [h_{t-1}, x_t] + b_i)
c̃_t = tanh(W_c × [h_{t-1}, x_t] + b_c)

3. セルステート更新:
c_t = f_t × c_{t-1} + i_t × c̃_t

4. 出力ゲート:
o_t = σ(W_o × [h_{t-1}, x_t] + b_o)
h_t = o_t × tanh(c_t)

σ = シグモイド関数(0〜1の値を出力)

📌 計算の流れを日本語で
  1. 忘却:古いセルステートのどの部分を忘れるか決定
  2. 記憶候補:新しく記憶する情報の候補を作成
  3. 選択:候補のどの部分を実際に記憶するか決定
  4. 更新:セルステートを更新(忘却+追加)
  5. 出力:更新されたセルステートから出力を生成

💻 4. Kerasでの実装

4-1. LSTMレイヤーの基本

from tensorflow.keras.layers import LSTM # LSTMレイヤー LSTM( units=64, # 隠れ状態の次元数 return_sequences=False, # 最後の出力のみ(分類タスク) return_state=False, # 状態を返すかどうか dropout=0.0, # 入力に対するドロップアウト recurrent_dropout=0.0 # 再帰接続に対するドロップアウト )

4-2. 時系列予測モデル

import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.callbacks import EarlyStopping # ===== ダミーデータ作成(sin波予測) ===== def create_dataset(n_samples=1000, seq_length=50): X, y = [], [] for _ in range(n_samples): start = np.random.rand() * 2 * np.pi seq = np.sin(np.linspace(start, start + 4*np.pi, seq_length + 1)) X.append(seq[:-1].reshape(-1, 1)) y.append(seq[-1]) return np.array(X), np.array(y) X_train, y_train = create_dataset(2000) X_test, y_test = create_dataset(400) print(f”X_train shape: {X_train.shape}”) # (2000, 50, 1) # ===== LSTMモデル ===== model = Sequential([ LSTM(64, return_sequences=True, input_shape=(50, 1)), Dropout(0.2), LSTM(32, return_sequences=False), Dropout(0.2), Dense(16, activation=’relu’), Dense(1) ]) model.compile(optimizer=’adam’, loss=’mse’) model.summary()
実行結果:
X_train shape: (2000, 50, 1)

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm (LSTM)                 (None, 50, 64)            16896     
 dropout (Dropout)           (None, 50, 64)            0         
 lstm_1 (LSTM)               (None, 32)                12416     
 dropout_1 (Dropout)         (None, 32)                0         
 dense (Dense)               (None, 16)                528       
 dense_1 (Dense)             (None, 1)                 17        
=================================================================
Total params: 29,857

4-3. 学習と評価

# 学習 early_stop = EarlyStopping(monitor=’val_loss’, patience=10, restore_best_weights=True) history = model.fit( X_train, y_train, epochs=50, batch_size=32, validation_split=0.2, callbacks=[early_stop], verbose=1 ) # 評価 test_loss = model.evaluate(X_test, y_test) print(f”\nテスト損失(MSE): {test_loss:.6f}”) # 予測 predictions = model.predict(X_test[:5]) print(“\n予測結果:”) for i in range(5): print(f” 実際: {y_test[i]:.4f}, 予測: {predictions[i][0]:.4f}”)
実行結果:
Epoch 1/50 - loss: 0.2345 - val_loss: 0.1234
...
Epoch 25/50 - loss: 0.0012 - val_loss: 0.0015

テスト損失(MSE): 0.001234

予測結果:
  実際: 0.8415, 予測: 0.8389
  実際: -0.5403, 予測: -0.5456
  実際: 0.9893, 予測: 0.9867
  ...

→ SimpleRNNより高精度!

🎯 5. 実践:感情分析

“”” IMDBレビューの感情分析(ポジティブ/ネガティブ) “”” from tensorflow.keras.datasets import imdb from tensorflow.keras.preprocessing.sequence import pad_sequences from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout # ===== データ準備 ===== max_features = 10000 # 語彙数 maxlen = 200 # シーケンス長 (X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=max_features) # パディング(長さを揃える) X_train = pad_sequences(X_train, maxlen=maxlen) X_test = pad_sequences(X_test, maxlen=maxlen) print(f”X_train shape: {X_train.shape}”) # (25000, 200) # ===== LSTMモデル ===== model = Sequential([ Embedding(max_features, 128, input_length=maxlen), # 単語埋め込み LSTM(64, dropout=0.2, recurrent_dropout=0.2), Dense(1, activation=’sigmoid’) # 2値分類 ]) model.compile( optimizer=’adam’, loss=’binary_crossentropy’, metrics=[‘accuracy’] ) # ===== 学習 ===== history = model.fit( X_train, y_train, epochs=5, batch_size=64, validation_split=0.2 ) # ===== 評価 ===== test_loss, test_acc = model.evaluate(X_test, y_test) print(f”\nテスト精度: {test_acc:.4f}”)
実行結果:
X_train shape: (25000, 200)

Epoch 1/5 - accuracy: 0.7823 - val_accuracy: 0.8456
Epoch 5/5 - accuracy: 0.9234 - val_accuracy: 0.8678

テスト精度: 0.8612

→ 映画レビューの感情を86%の精度で分類!

📝 STEP 22 のまとめ

✅ このステップで学んだこと
  • LSTM:勾配消失問題を解決したRNNアーキテクチャ
  • セルステート:長期記憶を保持する経路
  • 忘却ゲート:古い情報をどれだけ忘れるか
  • 入力ゲート:新しい情報をどれだけ記憶するか
  • 出力ゲート:セルステートからどれだけ出力するか
  • return_sequences:Trueで全タイムステップの出力を返す
💡 覚えておくべきコード
# LSTMの基本パターン model = Sequential([ LSTM(64, return_sequences=True, input_shape=(timesteps, features)), Dropout(0.2), LSTM(32), Dense(num_classes, activation=’softmax’) ])
🚀 次のステップへ

LSTMを理解したので、次のSTEP 23ではGRU(Gated Recurrent Unit)を学びます。

LSTMをシンプルにした構造で、同等の性能を少ないパラメータで実現します!

📝 練習問題

問題1 やさしい

LSTMの目的

LSTMが解決しようとしている問題は何ですか?

  • A. 過学習問題
  • B. 勾配消失問題
  • C. データ不足問題
  • D. 計算速度問題
正解:B

LSTMは、SimpleRNNで発生する勾配消失問題を解決するために設計されました。セルステートとゲート機構により、長期的な依存関係を学習できます。

問題2 やさしい

LSTMのゲート数

LSTMには何種類のゲートがありますか?

  • A. 1種類
  • B. 2種類
  • C. 3種類
  • D. 4種類
正解:C

LSTMには忘却ゲート、入力ゲート、出力ゲートの3種類のゲートがあります。

問題3 ふつう

忘却ゲートの役割

忘却ゲートの出力が0に近い場合、何が起きますか?

  • A. 新しい情報を完全に記憶する
  • B. 古い情報を完全に忘れる
  • C. 出力を完全に抑制する
  • D. 学習を停止する
正解:B

忘却ゲートの出力(0〜1)は、前のセルステートをどれだけ保持するかを決めます。0に近いと「ほぼ忘れる」、1に近いと「ほぼ保持する」となります。

問題4 ふつう

LSTMの積み重ね

2層のLSTMを積み重ねる場合、最初のLSTM層で必要な設定は?

  • A. return_sequences=False
  • B. return_sequences=True
  • C. return_state=True
  • D. units=1
正解:B

LSTM層を積み重ねる場合、最初の層はreturn_sequences=Trueにして、全タイムステップの出力を次の層に渡す必要があります。最後の層だけFalse(またはデフォルト)にします。

問題5 むずかしい

セルステートの更新

セルステートの更新式 c_t = f_t × c_{t-1} + i_t × c̃_t について、正しい説明を選んでください。

  • A. f_tは新しい情報の重要度を表す
  • B. i_tは古い情報をどれだけ忘れるかを表す
  • C. c̃_tは記憶の候補となる新しい情報
  • D. c_{t-1}は出力ゲートの値
正解:C

c̃_t(候補セル)はtanhで生成される新しい記憶の候補です。f_tは忘却ゲート、i_tは入力ゲート、c_{t-1}は前のセルステートです。

問題6 むずかしい

パラメータ数の計算

LSTM(64, input_shape=(100, 32))のパラメータ数として、最も近いものは?(バイアスを含む)

  • A. 約2,000
  • B. 約8,000
  • C. 約25,000
  • D. 約100,000
正解:C
LSTMのパラメータ数の計算: 4 × [(入力次元 × units) + (units × units) + units] = 4 × [(32 × 64) + (64 × 64) + 64] = 4 × [2048 + 4096 + 64] = 4 × 6208 = 24,832 ※ 4倍なのは、4つの重み行列(忘却・入力・セル候補・出力)があるため
📝

学習メモ

ディープラーニング基礎 - Step 22

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE