はじめに: シーケンスのニューラル ネットワーク
Le リカレント ニューラル ネットワーク (RNN) シーケンシャルデータを処理するように設計されています。 テキスト、時系列、オーディオ、アクション シーケンス。処理するフィードフォワード ネットワークとは異なります。 独立した入力、RNN は 1 つの入力を維持します 隠された (隠れた状態) として機能します。 これにより、ネットワークはシーケンス内の以前の情報のコンテキストを考慮できるようになります。
ただし、古典的な RNN には次のような問題があります。 勾配消失問題: の間 トレーニングでは、時間ステップ全体で勾配が急速に減衰するため、学習が不可能になります。 長期にわたる依存症。の LSTM (長短期記憶)および クレーン (Gated Recurrent Unit) は、洗練されたゲート メカニズムでこの問題を解決します。
何を学ぶか
- RNN がシーケンス全体で状態を維持する方法
- 勾配消失問題とそれが RNN を制限する理由
- LSTM: 入力ゲート、忘却ゲート、出力ゲートおよびセル状態
- CRANES: LSTM の軽量な代替品
- 双方向 RNN とシーケンス間モデル
- 実際の実装: テキスト生成と感情分析
RNN: アーキテクチャと隠れた状態
RNN はシーケンスを一度に 1 要素ずつ処理し、各ステップで独自の要素を更新します 隠れた状態。この状態ベクトルは、すべての状態の圧縮された概要をキャプチャします。 それまでに見られた情報。各タイム ステップの出力は、両方の入力に依存します。 以前の非表示状態からの現在の状態。
形式的には、各タイム ステップ t で、RNN は次を計算します。
- h_t = Tanh(W_hh * h_(t-1) + W_xh * x_t + b_h): 以前の状態と現在の入力を組み合わせた新しい非表示の状態
- y_t = W_hy * h_t + b_y: 現在のタイム ステップでの出力
import torch
import torch.nn as nn
# RNN semplice in PyTorch
class SimpleRNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super().__init__()
self.hidden_size = hidden_size
self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
# x shape: (batch, seq_len, input_size)
# h0 shape: (1, batch, hidden_size)
h0 = torch.zeros(1, x.size(0), self.hidden_size).to(x.device)
output, hidden = self.rnn(x, h0)
# Usa l'ultimo hidden state per classificazione
out = self.fc(hidden.squeeze(0))
return out
# Esempio: sequenza di 20 time step con 10 feature ciascuno
model = SimpleRNN(input_size=10, hidden_size=64, output_size=2)
x = torch.randn(8, 20, 10) # batch=8, seq=20, features=10
output = model(x)
print(f"Output: {output.shape}") # [8, 2]
勾配消失問題
Il 消失勾配 そして古典的な RNN のアキレス腱です。その間、 バックプロパゲーション スルー タイム (BPTT) では、勾配に行列が繰り返し乗算されます。 各タイムステップでの重み W_hh の値。この行列の固有値が 1 未満の場合、勾配は 指数関数的に減少します。 1 より大きい場合は爆発します。
実際には、これは古典的な RNN がオーバーシュートする依存関係を学習できないことを意味します。 私は 10~20のタイムステップ。文章の雰囲気を理解するためのキーワードが 最初と最後の出力では、勾配はその値に達する前にほぼゼロになります。 言葉。
LSTM が必要な理由
LSTM は、すべてを強制するのではなく、洗練された直感で消失勾配を解決します。 乗算を繰り返して情報を得るには、 セルの状態 別々の 情報の「高速道路」として機能します。ゲートは追加する情報を制御します。 セル状態を忘れたり、セル状態から読み取ったりして、数百年間グラジエントを変更せずに流すことができます。 タイムステップの。
LSTM:長期短期記憶
Le LSTM1997 年に Hochreiter と Schmidhuber によって導入され、消失を解決します。 4 つの主要なコンポーネントを含むグラデーション:
三つの門
- 忘れた門 (f_t): セル状態からどの情報を破棄するかを決定します。各次元の 0 (すべて忘れる) と 1 (すべて保持する) の間のシグモイド値
- 入力ゲート(i_t): セルの状態にどのような新しい情報を追加するかを決定します。シグモイド ゲート (どれだけ加算するか) と Tanh 候補ベクトル (何を加算するか) を結合します。
- 出力ゲート (o_t): セル状態のどの部分を出力/非表示状態として使用するかを決定します。 Tanh と Sigmoid を通じてセルの状態をフィルター処理する
セルの状態
Il セルの状態 そしてLSTMの心臓部です。タイムチェーンを流れていく 線形演算 (乗算と加算) のみを使用し、勾配を伝播させます。 簡単に。ゲートは、セル状態に出入りする情報の流れを制御します。
import torch
import torch.nn as nn
class LSTMClassifier(nn.Module):
"""LSTM per classificazione di sequenze"""
def __init__(self, vocab_size, embed_dim, hidden_size,
num_layers, num_classes, dropout=0.3):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(
input_size=embed_dim,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
dropout=dropout if num_layers > 1 else 0,
bidirectional=True
)
self.dropout = nn.Dropout(dropout)
# Bidirezionale: hidden_size * 2
self.fc = nn.Linear(hidden_size * 2, num_classes)
def forward(self, x):
embedded = self.dropout(self.embedding(x))
lstm_out, (hidden, cell) = self.lstm(embedded)
# Concatena hidden state forward e backward
hidden_cat = torch.cat((hidden[-2], hidden[-1]), dim=1)
output = self.fc(self.dropout(hidden_cat))
return output
# Sentiment analysis: vocab 10000, embedding 128, hidden 256
model = LSTMClassifier(
vocab_size=10000,
embed_dim=128,
hidden_size=256,
num_layers=2,
num_classes=2 # positivo/negativo
)
# Input: batch di 16 frasi, max 50 token
x = torch.randint(0, 10000, (16, 50))
output = model(x)
print(f"Output: {output.shape}") # [16, 2]
CRANE: より軽量な代替品
Le クレーン (Gated Recurrent Unit)、Cho らによって導入されました。 2014年、私もその一人です LSTM の簡易バージョン。忘却ゲートと入力ゲートを 1 つに結合します アップデートゲート セルの状態と非表示の状態をマージし、パラメータの数を減らします。 約25%増加します。
クレーンには 2 つのゲートがあります。
- リセットゲート(r_t): 新しい候補を計算するときに古い隠れ状態をどれだけ無視するか
- アップデートゲート (z_t): 古い非表示状態をどのくらい保持するか、新しい候補をどのくらい使用するか
実際には、GRU は多くのタスクで LSTM に匹敵するパフォーマンスを達成しますが、 劣悪なトレーニング。選択はタスクによって異なります。非常に長いシーケンスの場合、LSTM は次のような傾向があります。 より小さいデータセットの場合は、GRU の方が適している可能性があります。 過剰適合する傾向。
双方向 RNN とシーケンス間
双方向
Una 双方向RNN シーケンスを両方向(左から右)に処理します。 それを逆方向(右から左)に、2 つの隠れた状態を連結します。これにより、 各ポジションには過去と未来の両方のコンテキストがあり、次のようなタスクの基本となります。 単語の意味が文脈全体に依存する固有表現認識。
シーケンスツーシーケンス (Seq2Seq)
アーキテクチャ シーケンス 2 シーケンス RNN エンコーダを使用して入力シーケンスを圧縮します。 固定コンテキスト ベクトル、および出力シーケンスを生成する RNN デコーダー。これ トランスフォーマーが登場するまで、アーキテクチャは機械翻訳の基礎でした。
class TextGenerator(nn.Module):
"""Generatore di testo carattere per carattere"""
def __init__(self, vocab_size, embed_dim, hidden_size, num_layers):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_size, num_layers,
batch_first=True, dropout=0.2)
self.fc = nn.Linear(hidden_size, vocab_size)
def forward(self, x, hidden=None):
embedded = self.embedding(x)
output, hidden = self.lstm(embedded, hidden)
logits = self.fc(output)
return logits, hidden
def generate(self, start_token, max_len=100, temperature=0.8):
"""Genera testo auto-regressivamente"""
self.eval()
current = start_token.unsqueeze(0).unsqueeze(0)
hidden = None
generated = [start_token.item()]
with torch.no_grad():
for _ in range(max_len):
logits, hidden = self(current, hidden)
logits = logits[:, -1, :] / temperature
probs = torch.softmax(logits, dim=-1)
next_token = torch.multinomial(probs, 1)
generated.append(next_token.item())
current = next_token
return generated
注目の到来
Seq2Seq モデルの主な制限は次のとおりです。 ボトルネック: すべての情報 入力シーケンスの 1 つの固定ベクトルが圧縮されます。長いシーケンスの場合、これは ベクトルはすべての詳細をキャプチャできません。の仕組み 注意、 Bahdanau らによって導入されました。 2014 年には、デコーダが次のことを実行できるようにすることで、この問題を解決しました。 すべてのエンコーダ位置を直接「見て」ください。このアイデアは、 トランスフォーマー、それについては次の記事で説明します。
実用的なアプリケーション
RNN と LSTM は、さまざまな分野で応用されています。
- 感情分析: レビュー、ツイート、コメントの感情を分類します。双方向 LSTM は完全なコンテキストをキャプチャします
- 時系列予測: 株価、エネルギー消費量、システム指標の予測。 LSTM は季節パターンの捕捉に優れています
- テキストの生成: チャットボットから計算詩まで、文字ごとまたは単語ごとにテキストを生成します
- 機械翻訳: Seq2Seq + Attendance アーキテクチャによる機械翻訳 (Transformers の前身)
- 音声認識: オーディオからテキストへの変換。音響シーケンスが音素と単語のシーケンスにマッピングされます。
シリーズの次のステップ
- 次の記事では、 トランスフォーマー、ほとんどの NLP タスクで RNN を廃止したアーキテクチャ
- 自己注意、多頭注意、位置エンコーディングについて見ていきます。
- BERT と GPT がどのように自然言語処理に革命をもたらしたかを分析します。







