PyTorch torch.nn.LSTM 関数
torch.nn.LSTMPyTorch における長短期記憶ネットワークのモジュールです。
LSTM は特殊な再帰ニューラルネットワークであり、長期的な依存関係を学習でき、系列モデリングタスクに広く使用されています。
関数定義
torch.nn.LSTM(input_size, hidden_size, num_layers=1, bias=True, batch_first=True, dropout=0, bidirectional=False)
パラメータの説明:
input_size(int): 入力特徴量の次元。hidden_size(int): 隠れ状態の次元。num_layers(int): LSTM の層数。デフォルトは 1。bias(bool): バイアスを使用するかどうか。デフォルトは True。batch_first(bool): True の場合、入出力の形状は (batch, seq, feature) になります。デフォルトは True。dropout(float): 最後の層以外で使用される dropout。デフォルトは 0。bidirectional(bool): 双方向 LSTM を使用するかどうか。デフォルトは False。
入出力
入力:
input: 形状が (batch, seq_len, input_size) のテンソルh_0: 初期隠れ状態。形状は (num_layers * num_directions, batch, hidden_size)c_0: 初期セル状態。形状は (num_layers * num_directions, batch, hidden_size)
出力:
output: 最後の隠れ層の出力。形状は (batch, seq_len, num_directions * hidden_size)h_n: 全層の最後の隠れ状態c_n: 全層の最後のセル状態
使用例
例 1: 基本的な使い方
LSTM を作成して使用する:
例
import torch
import torch.nn as nn
# LSTM を作成:入力次元 256、隠れ次元 512、2 層
lstm = nn.LSTM(input_size=256, hidden_size=512, num_layers=2, batch_first=True)
# 入力を作成:batch=4、系列長=10、入力次元=256
input_tensor = torch.randn(4, 10, 256)
# 順伝播
output, (h_n, c_n) = lstm(input_tensor)
print("入力形状:", input_tensor.shape)
print("出力形状:", output.shape) # (4, 10, 512)
print("隠れ状態の形状:", h_n.shape) # (2, 4, 512)
print("セル状態の形状:", c_n.shape) # (2, 4, 512)
import torch.nn as nn
# LSTM を作成:入力次元 256、隠れ次元 512、2 層
lstm = nn.LSTM(input_size=256, hidden_size=512, num_layers=2, batch_first=True)
# 入力を作成:batch=4、系列長=10、入力次元=256
input_tensor = torch.randn(4, 10, 256)
# 順伝播
output, (h_n, c_n) = lstm(input_tensor)
print("入力形状:", input_tensor.shape)
print("出力形状:", output.shape) # (4, 10, 512)
print("隠れ状態の形状:", h_n.shape) # (2, 4, 512)
print("セル状態の形状:", c_n.shape) # (2, 4, 512)
例2: 双方向LSTM
双方向 LSTM を使用して双方向の文脈を捉える:
例
import torch
import torch.nn as nn
# 双方向 LSTM
bilstm = nn.LSTM(input_size=256, hidden_size=256, num_layers=2, batch_first=True, bidirectional=True)
input_tensor = torch.randn(4, 10, 256)
output, (h_n, c_n) = bilstm(input_tensor)
print("双方向 LSTM の出力形状:", output.shape) # (4, 10, 512) = 256*2
print("隠れ状態の形状:", h_n.shape) # (4, 4, 256) = 2層*2方向
print("最後の層の隠れ状態:", h_n[-2:, :, :].shape) # 順方向と逆方向
import torch.nn as nn
# 双方向 LSTM
bilstm = nn.LSTM(input_size=256, hidden_size=256, num_layers=2, batch_first=True, bidirectional=True)
input_tensor = torch.randn(4, 10, 256)
output, (h_n, c_n) = bilstm(input_tensor)
print("双方向 LSTM の出力形状:", output.shape) # (4, 10, 512) = 256*2
print("隠れ状態の形状:", h_n.shape) # (4, 4, 256) = 2層*2方向
print("最後の層の隠れ状態:", h_n[-2:, :, :].shape) # 順方向と逆方向
例 3: 隠れ状態の初期化
隠れ状態を手動で初期化する:
例
import torch
import torch.nn as nn
lstm = nn.LSTM(input_size=256, hidden_size=512, batch_first=True)
# 初期隠れ状態を手動で作成
batch_size = 4
num_layers = 2
hidden_size = 512
h_0 = torch.zeros(num_layers, batch_size, hidden_size)
c_0 = torch.zeros(num_layers, batch_size, hidden_size)
# 初期状態を渡す
input_tensor = torch.randn(4, 10, 256)
output, (h_n, c_n) = lstm(input_tensor, (h_0, c_0))
print("カスタム初期状態を使用して完了")
print("出力形状:", output.shape)
import torch.nn as nn
lstm = nn.LSTM(input_size=256, hidden_size=512, batch_first=True)
# 初期隠れ状態を手動で作成
batch_size = 4
num_layers = 2
hidden_size = 512
h_0 = torch.zeros(num_layers, batch_size, hidden_size)
c_0 = torch.zeros(num_layers, batch_size, hidden_size)
# 初期状態を渡す
input_tensor = torch.randn(4, 10, 256)
output, (h_n, c_n) = lstm(input_tensor, (h_0, c_0))
print("カスタム初期状態を使用して完了")
print("出力形状:", output.shape)
例 4: 完全な感情分類モデル
LSTM ベースのテキスト分類:
例
import torch
import torch.nn as nn
class LSTMClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes=2):
super(LSTMClassifier, self).__init__()
# 埋め込み層
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
# LSTM 層
self.lstm = nn.LSTM(
input_size=embed_dim,
hidden_size=hidden_dim,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.3
)
# 全結合分類層
self.fc = nn.Linear(hidden_dim * 2, num_classes)
def forward(self, x):
# x: (batch, seq_len)
embedded = self.embedding(x) # (batch, seq_len, embed_dim)
# LSTM 出力
output, (hidden, cell) = self.lstm(embedded)
# 双方向の最後の層の隠れ状態を連結
# hidden: (4, batch, hidden_dim) - 2層 * 2方向
hidden = torch.cat([hidden[-2], hidden[-1]], dim=1) # (batch, hidden_dim*2)
# 分類
logits = self.fc(hidden)
return logits
# モデルをインスタンス化
vocab_size = 10000
model = LSTMClassifier(vocab_size=vocab_size, embed_dim=128, hidden_dim=128, num_classes=2)
# テスト入力:batch=8、系列長=50
input_ids = torch.randint(1, vocab_size, (8, 50))
output = model(input_ids)
print("モデル構造:")
print(model)
print("n入力形状:", input_ids.shape)
print("出力形状:", output.shape) # (8, 2)
import torch.nn as nn
class LSTMClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes=2):
super(LSTMClassifier, self).__init__()
# 埋め込み層
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
# LSTM 層
self.lstm = nn.LSTM(
input_size=embed_dim,
hidden_size=hidden_dim,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.3
)
# 全結合分類層
self.fc = nn.Linear(hidden_dim * 2, num_classes)
def forward(self, x):
# x: (batch, seq_len)
embedded = self.embedding(x) # (batch, seq_len, embed_dim)
# LSTM 出力
output, (hidden, cell) = self.lstm(embedded)
# 双方向の最後の層の隠れ状態を連結
# hidden: (4, batch, hidden_dim) - 2層 * 2方向
hidden = torch.cat([hidden[-2], hidden[-1]], dim=1) # (batch, hidden_dim*2)
# 分類
logits = self.fc(hidden)
return logits
# モデルをインスタンス化
vocab_size = 10000
model = LSTMClassifier(vocab_size=vocab_size, embed_dim=128, hidden_dim=128, num_classes=2)
# テスト入力:batch=8、系列長=50
input_ids = torch.randint(1, vocab_size, (8, 50))
output = model(input_ids)
print("モデル構造:")
print(model)
print("n入力形状:", input_ids.shape)
print("出力形状:", output.shape) # (8, 2)
例 5: 多層スタック LSTM
深い LSTM ネットワーク:
例
import torch
import torch.nn as nn
# 4 層スタックの LSTM、dropout 付き
deep_lstm = nn.LSTM(
input_size=256,
hidden_size=512,
num_layers=4,
batch_first=True,
dropout=0.4 # 各層間の dropout
)
input_tensor = torch.randn(2, 20, 256)
output, (h_n, c_n) = deep_lstm(input_tensor)
print("4層 LSTM の出力形状:", output.shape)
print("隠れ状態の形状 (4層):", h_n.shape)
print("セル状態の形状 (4層):", c_n.shape)
import torch.nn as nn
# 4 層スタックの LSTM、dropout 付き
deep_lstm = nn.LSTM(
input_size=256,
hidden_size=512,
num_layers=4,
batch_first=True,
dropout=0.4 # 各層間の dropout
)
input_tensor = torch.randn(2, 20, 256)
output, (h_n, c_n) = deep_lstm(input_tensor)
print("4層 LSTM の出力形状:", output.shape)
print("隠れ状態の形状 (4層):", h_n.shape)
print("セル状態の形状 (4層):", c_n.shape)
LSTM ゲートの概念
LSTM は3つのゲートで情報の流れを制御します:
- 忘却ゲート: 前の時刻の情報をどれだけ保持するかを決定
- 入力ゲート: 新しい情報をどれだけ加えるかを決定
- 出力ゲート: どれだけの情報を出力するかを決定
よくある質問
Q1: batch_first=True とはどういう意味ですか?
入出力テンソルの最初の次元は batch_size です。False の場合、最初の次元は系列長になります。
Q2: 双方向 LSTM はいつ使いますか?
系列ラベリング、感情分析など、双方向の文脈を必要とするタスクに使用します。機械翻訳では一般的に encoder-decoder アーキテクチャが使われます。
Q3: 隠れ層のサイズはどう選びますか?
通常は 128〜512 で、タスクの複雑さとデータ量に応じて調整します。小さすぎると未学習、大きすぎると過学習になります。
使用シーン
nn.LSTM主な適用シーンは以下のとおりです:
- 自然言語処理: テキスト分類、固有表現認識
- 時系列予測: 株価予測、音声認識
- 系列から系列へのタスク: 機械翻訳、テキスト生成
ヒント:bidirectional=True を使用すると、出力次元は hidden_size * 2 になります。
その他の拡張