# [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、語音識別、時間序列預測等多個領域有著廣泛的應用。