STEP 21:RNNの基礎

🔄 STEP 21: RNNの基礎

時系列データを扱う!リカレントニューラルネットワーク入門

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

  • RNNとは何か?CNNとの違い
  • 時系列データとシーケンスデータ
  • 隠れ状態(Hidden State)の概念
  • RNNの仕組みと計算
  • 勾配消失問題
  • KerasでのSimpleRNN実装

🔄 1. RNNとは何か?

1-1. RNNの定義

RNN(Recurrent Neural Network、リカレントニューラルネットワーク)は、時系列データやシーケンスデータを扱うためのニューラルネットワークです。

📖 文章を読む例え

「私は 今日 公園で サッカーを した」

この文を理解するには、単語の順番文脈が重要です。

CNN:各単語を独立して見る(文脈を無視)
RNN:前の単語を覚えながら次の単語を処理(文脈を理解)

→ RNNは「記憶」を持ちながら処理を進めます!

1-2. 時系列データの例

✅ RNNが得意なタスク
  • 自然言語処理:文章生成、翻訳、感情分析
  • 株価予測:過去の価格から将来を予測
  • 音声認識:音声波形からテキストに変換
  • 音楽生成:メロディの自動作曲
  • 動画分析:フレームの連続から行動認識

1-3. CNNとRNNの違い

📊 CNN vs RNN

CNN(畳み込みニューラルネットワーク):
・空間的なパターンを認識
・入力:画像(縦×横×チャンネル)
・「どこに何があるか」が重要

RNN(リカレントニューラルネットワーク):
・時間的なパターンを認識
・入力:シーケンス(時間×特徴量)
・「どの順番で起きたか」が重要

⚙️ 2. RNNの仕組み

2-1. 隠れ状態(Hidden State)

RNNの核心は隠れ状態(Hidden State)です。
これは「過去の情報を記憶」するための変数で、各タイムステップで更新されます。

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

【RNNの構造】 ■ 通常のニューラルネットワーク(順伝播のみ) 入力 → [隠れ層] → 出力 各入力は独立に処理される ■ RNN(再帰的な接続あり) h₀ h₁ h₂ h₃ ↓ ↓ ↓ ↓ ┌─────────┐┌─────────┐┌─────────┐┌─────────┐ x₀ →│ RNN │→│ RNN │→│ RNN │→│ RNN │→ 出力 │ Cell │ │ Cell │ │ Cell │ │ Cell │ └─────────┘└─────────┘└─────────┘└─────────┘ ↑ ↑ ↑ ↑ x₀ x₁ x₂ x₃ (入力1) (入力2) (入力3) (入力4) h = 隠れ状態(Hidden State) x = 入力 隠れ状態が次のタイムステップに渡される → 過去の情報が「記憶」として保持される

2-2. RNNの計算式

📐 RNNの計算式

h_t = tanh(W_h × h_{t-1} + W_x × x_t + b)

h_t:現在の隠れ状態
h_{t-1}:前のタイムステップの隠れ状態
x_t:現在の入力
W_h:隠れ状態に対する重み
W_x:入力に対する重み
b:バイアス
tanh:活性化関数

2-3. 具体例で理解

【「こんにちは」を処理する例】 入力シーケンス:「こ」「ん」「に」「ち」「は」 タイムステップ1: 入力:「こ」 隠れ状態:h₁ = tanh(W_x × 「こ」 + 0) →「こ」の情報を記憶 タイムステップ2: 入力:「ん」 隠れ状態:h₂ = tanh(W_h × h₁ + W_x × 「ん」) →「こ」の記憶 +「ん」の情報 タイムステップ3: 入力:「に」 隠れ状態:h₃ = tanh(W_h × h₂ + W_x × 「に」) →「こん」の記憶 +「に」の情報 … 最終的に h₅ には「こんにちは」全体の情報が圧縮されている!

😰 3. 勾配消失問題

3-1. 問題の概要

RNNの大きな問題は勾配消失問題(Vanishing Gradient Problem)です。

⚠️ 勾配消失問題とは?

シーケンスが長くなると、初めの方の入力に対する勾配が指数関数的に小さくなり、
学習がうまく進まなくなる問題です。

結果として、長期的な依存関係を学習できなくなります。

【勾配消失のイメージ】 「昨日 私は 東京で 美味しい ラーメンを 食べた ので 今日は お腹が いっぱいだ」 ↑ ↑ 「昨日」 「いっぱいだ」 「いっぱいだ」を予測するには「昨日…ラーメンを食べた」を覚えておく必要がある しかし、シーケンスが長いと… 勾配の大きさ: タイムステップ10 → 1.0 (学習できる) タイムステップ5 → 0.1 (学習しにくい) タイムステップ1 → 0.001 (ほぼ学習できない!) → 最初の方の情報が「忘れられて」しまう

3-2. 解決策

📌 勾配消失問題の解決策
  • LSTM:Long Short-Term Memory(次のステップで学習)
  • GRU:Gated Recurrent Unit(STEP 23で学習)
  • 勾配クリッピング:勾配の大きさを制限
  • 残差接続:ショートカット経路を追加

💻 4. KerasでのSimpleRNN実装

4-1. 入力データの形状

💡 RNNの入力形状

RNNの入力は3次元です:

(サンプル数, タイムステップ数, 特徴量数)

例:1000個の文章、各30単語、各単語は100次元ベクトル
→ (1000, 30, 100)

4-2. SimpleRNNの基本

from tensorflow.keras.layers import SimpleRNN # SimpleRNNレイヤー SimpleRNN( units=64, # 隠れ状態の次元数 return_sequences=False, # 最後の出力だけ返す return_state=False, # 隠れ状態を返すかどうか activation=’tanh’ # 活性化関数 )
📝 return_sequencesの違い

return_sequences=False:最後のタイムステップの出力のみ返す
→ 分類タスクなど、最終的な1つの出力が欲しい場合

return_sequences=True:全タイムステップの出力を返す
→ RNNを積み重ねる場合、系列ラベリングなど

4-3. シンプルな時系列予測

import numpy as np from tensorflow.keras.models import Sequential from tensorflow.keras.layers import SimpleRNN, Dense # ===== ダミーデータ作成 ===== # 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(1000) X_test, y_test = create_dataset(200) print(f”X_train shape: {X_train.shape}”) # (1000, 50, 1) print(f”y_train shape: {y_train.shape}”) # (1000,) # ===== モデル構築 ===== model = Sequential([ SimpleRNN(32, input_shape=(50, 1)), # 入力:50タイムステップ、1特徴量 Dense(1) # 出力:1つの値を予測 ]) model.compile(optimizer=’adam’, loss=’mse’) model.summary()
実行結果:
X_train shape: (1000, 50, 1)
y_train shape: (1000,)

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 simple_rnn (SimpleRNN)      (None, 32)                1088      
 dense (Dense)               (None, 1)                 33        
=================================================================
Total params: 1,121

4-4. 学習と評価

# 学習 history = model.fit( X_train, y_train, epochs=20, batch_size=32, validation_split=0.2, verbose=1 ) # 評価 test_loss = model.evaluate(X_test, y_test) print(f”\nテスト損失(MSE): {test_loss:.4f}”) # 予測 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/20 - loss: 0.4523 - val_loss: 0.3012
...
Epoch 20/20 - loss: 0.0089 - val_loss: 0.0078

テスト損失(MSE): 0.0082

予測結果:
  実際: 0.8415, 予測: 0.8234
  実際: -0.5403, 予測: -0.5612
  実際: 0.9893, 予測: 0.9756
  ...

🎯 5. RNNの応用パターン

【RNNの主な応用パターン】 ■ Many-to-One(多対一) 入力:シーケンス → 出力:1つの値 例:文章 → 感情(ポジティブ/ネガティブ) [入力1] [入力2] [入力3] [入力4] ↓ ↓ ↓ ↓ [RNN] → [RNN] → [RNN] → [RNN] ↓ [出力] ■ One-to-Many(一対多) 入力:1つの値 → 出力:シーケンス 例:画像 → キャプション(文章) [入力] ↓ [RNN] → [RNN] → [RNN] → [RNN] ↓ ↓ ↓ ↓ [出力1] [出力2] [出力3] [出力4] ■ Many-to-Many(多対多) 入力:シーケンス → 出力:シーケンス 例:英語 → 日本語(翻訳) [入力1] [入力2] [入力3] ↓ ↓ ↓ [RNN] → [RNN] → [RNN] → [RNN] → [RNN] ↓ ↓ [出力1] [出力2]

📝 STEP 21 のまとめ

✅ このステップで学んだこと
  • RNN:時系列・シーケンスデータを扱うニューラルネットワーク
  • 隠れ状態:過去の情報を「記憶」する変数
  • 計算式:h_t = tanh(W_h × h_{t-1} + W_x × x_t + b)
  • 入力形状:(サンプル数, タイムステップ数, 特徴量数)
  • 勾配消失問題:長いシーケンスで学習が困難になる問題
  • 解決策:LSTM、GRUなど(次のステップで学習)
💡 覚えておくべきコード
# SimpleRNNの基本 from tensorflow.keras.layers import SimpleRNN, Dense model = Sequential([ SimpleRNN(64, input_shape=(timesteps, features)), Dense(num_classes, activation=’softmax’) ]) # 入力形状:(サンプル数, タイムステップ数, 特徴量数)
🚀 次のステップへ

RNNの基礎を理解したので、次のSTEP 22ではLSTM(Long Short-Term Memory)を学びます。

勾配消失問題を解決し、長期的な依存関係を学習できる強力なアーキテクチャです!

📝 練習問題

問題1 やさしい

RNNの特徴

RNNの特徴として、正しいものを選んでください。

  • A. 画像認識に特化している
  • B. 過去の情報を記憶できる
  • C. 畳み込み演算を使う
  • D. 入力の順序は関係ない
正解:B

RNNは隠れ状態(Hidden State)を通じて過去の情報を記憶し、シーケンスの前後関係を考慮した処理ができます。

問題2 やさしい

RNNの入力形状

100個の文章、各50単語、各単語は200次元のベクトルで表現されている場合、RNNへの入力形状は?

  • A. (100, 200)
  • B. (50, 200)
  • C. (100, 50, 200)
  • D. (100, 200, 50)
正解:C

RNNの入力形状は(サンプル数, タイムステップ数, 特徴量数)です。この場合、(100, 50, 200)となります。

問題3 ふつう

勾配消失問題

RNNの勾配消失問題について、正しい説明を選んでください。

  • A. シーケンスが長いと最新の入力の学習が困難になる
  • B. シーケンスが長いと最初の入力の学習が困難になる
  • C. 隠れ状態のサイズが小さいと発生する
  • D. バッチサイズが大きいと発生する
正解:B

勾配消失問題は、シーケンスが長くなると、最初の方のタイムステップに対する勾配が指数関数的に小さくなり、学習が困難になる問題です。

問題4 ふつう

return_sequencesパラメータ

SimpleRNN(64, return_sequences=True)の出力形状について、入力が(32, 20, 10)の場合、出力形状は?

  • A. (32, 64)
  • B. (32, 20, 64)
  • C. (32, 10, 64)
  • D. (32, 20, 10)
正解:B

return_sequences=Trueの場合、全タイムステップの出力が返されます。入力(32, 20, 10)に対して、各タイムステップで64次元の出力を返すので、出力は(32, 20, 64)となります。

問題5 むずかしい

RNNの応用

感情分析(文章から感情を分類)タスクに最も適したRNNのパターンはどれですか?

  • A. One-to-One
  • B. One-to-Many
  • C. Many-to-One
  • D. Many-to-Many
正解:C

感情分析は、シーケンス(文章の単語列)を入力として、1つの分類結果(感情ラベル)を出力するMany-to-Oneパターンです。

📝

学習メモ

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

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