# [ML](/zATBbu8iSA6QbCXeO9hCQA) RNN
## 1. RNN 的基本概念
- **定義:**
RNN 是一種專門設計來處理序列資料(Sequential Data)的神經網路。與傳統前饋神經網路不同,RNN 能夠利用「循環」的結構,使資訊在序列的各個時間步(Time Step)間傳遞,從而捕捉數據中的時間或順序依賴關係。
- **核心思想:**
每個時間步(Time Step)的隱藏狀態(Hidden State)不僅依賴於當前輸入(Input),還與前一個時間步的隱藏狀態相關。這使得 RNN 能夠對前面的資訊進行記憶與整合,從而對整個序列進行建模。
---
## 2. RNN 的結構與運作原理
### 2.1 基本結構
- **輸入層 (Input Layer):**
每個時間步接收一個輸入向量 $x_t$。
- **隱藏層 (Hidden Layer):**
隱藏狀態 $h_t$ 的更新公式通常為:
$$
h_t = f(W_{xh} x_t + W_{hh} h_{t-1} + b_h)
$$
其中:
- $W_{xh}$ 為輸入到隱藏層的權重矩陣。
- $W_{hh}$ 為隱藏狀態之間的循環權重矩陣。
- $b_h$ 為偏置。
- $f$ 為非線性激活函數(例如 tanh 或 ReLU)。
- **輸出層 (Output Layer):**
最後,根據需要可從隱藏狀態 $h_t$ 中生成輸出 $y_t$,通常表達式為:
$$
y_t = g(W_{hy} h_t + b_y)
$$
其中 $g$ 可能是 Softmax(用於分類)或其他適合任務的激活函數。
### 2.2 運作流程
1. **序列輸入:**
將一個序列 $\{x_1, x_2, \dots, x_T\}$ 依次送入 RNN,每個時間步計算對應的隱藏狀態 $h_t$。
2. **隱藏狀態更新:**
每個時間步的隱藏狀態 $h_t$ 都會結合當前輸入與上一時刻的隱藏狀態 $h_{t-1}$ 更新,從而累積並保存前面步驟的信息。
3. **最終輸出:**
根據應用場景,最終可以輸出整個序列的最終隱藏狀態(用於分類、序列標註等任務),或在每個時間步生成對應的輸出。
---
## 3. RNN 的訓練方法與挑戰
### 3.1 訓練方法
- **反向傳播 (Backpropagation):**
RNN 通常使用反向傳播算法來更新參數,但由於序列的連續性,需要展開(Unroll)整個序列進行梯度計算,這一過程稱為 **反向傳播通過時間 (Backpropagation Through Time, BPTT)**。
### 3.2 常見問題
- **梯度消失 (Vanishing Gradient):**
當序列較長時,隨著時間步的增加,梯度可能會逐漸衰減,使得網路難以捕捉長距離依賴。
- **梯度爆炸 (Exploding Gradient):**
反之,梯度可能變得非常大,導致參數更新過度,進而影響模型穩定性。
通常可以透過梯度裁剪(Gradient Clipping)來緩解此問題。
---
## 4. RNN 的變體
為了解決標準 RNN 在長序列處理中遇到的梯度消失與爆炸問題,學者們提出了多種改進版本:
- **LSTM (Long Short-Term Memory):**
LSTM 引入了記憶單元 (Memory Cell) 與多個門控機制(輸入門、遺忘門、輸出門),使得模型能夠更好地保存和遺忘信息,從而捕捉長距離依賴。
- **GRU (Gated Recurrent Unit):**
GRU 是另一種改進版本,結合了輸入門與遺忘門,結構較 LSTM 簡單,但在很多任務上能夠取得相似甚至更好的效果。
---
## Pytorch
```py=
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
# hyperparameters
input_size = 1 # 單個特徵
hidden_size = 32 # LSTM 隱藏層大小
num_layers = 1 # LSTM 層數
output_size = 1 # 單一輸出
seq_length = 10 # 序列長度
learning_rate = 0.01
num_epochs = 100
# **1️⃣ 定義 LSTM 模型**
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# 定義 LSTM 層
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
# 定義輸出層
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
# 初始化 LSTM 隱藏狀態和細胞狀態
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
# LSTM 前向傳播
out, _ = self.lstm(x, (h0, c0))
# 取最後時間步的輸出
out = self.fc(out[:, -1, :])
return out
# **2️⃣ 建立模型**
model = LSTMModel(input_size, hidden_size, num_layers, output_size)
criterion = nn.MSELoss() # 使用 MSE Loss
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# **3️⃣ 建立假數據 (sin 時間序列)**
def generate_data(seq_length, num_samples=100):
x_train = []
y_train = []
for _ in range(num_samples):
start = np.random.rand()
x_seq = np.sin(np.linspace(start, start + np.pi, seq_length)) # 生成 sin 序列
y_seq = np.sin(start + np.pi) # 目標值
x_train.append(x_seq)
y_train.append(y_seq)
return torch.tensor(x_train, dtype=torch.float32).unsqueeze(-1), torch.tensor(y_train, dtype=torch.float32).unsqueeze(-1)
x_train, y_train = generate_data(seq_length)
# **4️⃣ 訓練模型**
for epoch in range(num_epochs):
model.train()
optimizer.zero_grad()
outputs = model(x_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# **5️⃣ 測試模型**
model.eval()
x_test, y_test = generate_data(seq_length, num_samples=10)
y_pred = model(x_test).detach().numpy()
# **6️⃣ 視覺化結果**
plt.plot(y_test.numpy(), label="True Values")
plt.plot(y_pred, label="Predicted Values", linestyle="dashed")
plt.legend()
plt.show()
```
---
## 5. RNN 的應用場景
RNN 主要用於處理序列數據,其典型應用包括:
- **自然語言處理 (NLP):**
如語言模型、文本生成、機器翻譯、情感分析、序列標註(例如命名實體識別)。
- **語音識別 (Speech Recognition):**
對連續語音信號進行建模,識別語音中的文字信息。
- **時間序列預測 (Time Series Forecasting):**
如股價預測、氣象預測等,利用歷史數據預測未來趨勢。
- **視頻處理:**
在視頻數據中提取時間序列特徵,應用於行為識別或事件檢測。
---
## 6. 總結
- **RNN (Recurrent Neural Network)** 是一種專門用於處理序列數據的神經網路,其核心在於利用隱藏狀態在時間步之間傳遞信息,從而捕捉數據中的時序依賴。
- 儘管標準 RNN 存在梯度消失與梯度爆炸等問題,但透過改進變體如 LSTM 與 GRU,這些問題得到了較好的緩解。
- RNN 在 NLP、語音識別、時間序列預測等多個領域有著廣泛的應用。