在人工智能的領域中,神經網絡是推動技術發展的核心力量。今天,讓我們深入探討循環神經網絡(RNN)
一、神經網絡基礎
(1)什么是神經網絡
神經網絡,又稱人工神經網絡,其設計靈感源于人類大腦的運作模式。它由眾多被稱為“節點”的處理單元構成,這些節點之間相互傳遞數據,恰似大腦中的神經元傳遞電脈沖。
在機器學習領域,神經網絡扮演著關鍵角色。尤其是在深度學習中,它能夠從無標簽數據中提取有價值的信息,實現諸如識別照片中未知物品等復雜任務。
(2)神經網絡的學習過程
神經網絡的學習過程是一個迭代的過程,主要包括前向傳播、損失函數計算和反向傳播三個關鍵步驟。
在前向傳播階段,數據從輸入層開始,依次經過隱藏層的處理,最終到達輸出層。在這個過程中,每個神經元都會根據輸入數據和自身的權重、偏差進行計算。權重決定了輸入數據的相對重要性,而偏差則影響著神經元的激活程度。最初,我們會為權重和偏差賦予非零的隨機值,這就是網絡的參數初始化過程。
計算完成后,輸出層的結果即為前向傳播的最終輸出,我們將其與真實值(ground-truth value)進行對比,通過損失函數(loss function)來衡量模型的性能。損失函數計算預測值與真實值之間的誤差,常見的損失函數包括均方誤差(Mean Squared Error,MSE)、平均絕對誤差(Mean Absolute Error,MAE)、二元交叉熵(Binary Cross-entropy)、多類交叉熵(Multi-class Cross-entropy)等,它們分別適用于不同類型的任務,如回歸問題或分類問題。
如果前向傳播得到的預測值與真實值相差較大,說明我們需要調整網絡的參數以降低損失函數的值。這就引出了反向傳播過程,在這個階段,我們會計算損失函數關于模型參數的梯度,并利用優化算法(如梯度下降 等)來更新參數。
二、循環神經網絡
(1)RNN的定義與應用場景
循環神經網絡(RNN)是一種專門設計用于處理順序數據的神經網絡架構。與傳統的前饋神經網絡不同。
RNN 能夠通過內部狀態來記憶之前輸入的信息,從而更好地處理序列數據。在處理時間序列數據、語言建模或視頻序列等任務時,RNN 表現出了獨特的優勢,因為這些任務中輸入數據的順序至關重要。
(2)順序數據的概念
順序數據是指具有特定順序且順序會影響數據含義的信息。
“The quick brown fox jumps over the lazy dog.”
每個單詞都是數據的一部分,單詞的順序決定了句子的語義。如果將單詞順序打亂,句子就會變得毫無意義。
其他常見的順序數據還包括時間序列數據(如股票價格、溫度讀數、網站流量等)和語音信號等。
(3)RNN與前饋神經網絡的對比
- 前饋神經網絡:數據在網絡中僅沿一個方向流動,從輸入層到輸出層,不存在反饋回路。這種架構適用于模式識別等任務,但在處理順序數據時存在局限性,因為它無法利用之前的輸入信息。
- 循環神經網絡:通過網絡中的反饋回路,信號可以在前后時間步之間傳遞,使得網絡能夠記住之前的輸入,從而更好地處理順序數據。
(4)為什么使用RNN
傳統的人工神經網絡(ANN)在處理順序數據(如文本)時面臨挑戰,因為它們要求輸入數據具有固定的大小。在 ANN 中,每個輸入被獨立處理,無法捕捉元素之間的順序和關系。
三、RNN的架構
3.1 RNN的時間展開
RNN的關鍵在于其內部狀態或記憶,它能夠跟蹤已處理的數據,可以將 RNN 視為多個前饋神經網絡在時間上的鏈式執行,每個時間步都有一個相同的網絡結構在處理輸入數據。
- 輸入層:在每個時間步,輸入層接收一個輸入數據,并將其傳遞給隱藏層。與前饋網絡不同,RNN 的輸入是逐個時間步進行處理的,這使得網絡能夠適應動態變化的數據序列
- 隱藏狀態:隱藏層在 RNN 中起著核心作用,它不僅處理當前輸入,還會保留之前輸入的信息。隱藏狀態 h t h_t ht? 在時間步 t t t是根據當前輸入 X t X_t Xt?和前一個隱藏狀態 h t ? 1 h_{t - 1} ht?1? 計算得出的,計算公式如下:
h t = t a n h ( W ? [ h t ? 1 , X t ] + b h ) h_t = tanh(W*[h_{t-1},X_t] + b_h) ht?=tanh(W?[ht?1?,Xt?]+bh?)
- t a n h tanh tanh: 是非線性激活函數
- W W W:隱藏層的權重矩陣
- b h b_h bh?: 隱藏層的偏差向量
- 輸出序列:
RNN 的輸出方式非常靈活,可以在每個時間步都產生輸出(多對多),也可以在序列結束時產生一個單一輸出(多對一),甚至可以從單個輸入生成一個序列輸出(一對多)。例如,對于多對多的 RNN,時間步 t t t的輸出 O t O_t Ot? 可以通過以下公式計算:
O t = V ? h t + b o O_t = V*h_t+b_o Ot?=V?ht?+bo?
- V V V: 輸出層的權重矩陣
- b o b_o bo?:輸出層的偏差向
3.2 RNN的關鍵操作
3.2.1 前向傳播
在 RNN 的前向傳播過程中,對于每個時間步 t t t,網絡會結合當前輸入 X t X_t Xt? 和前一個隱藏狀態 h t ? 1 h_{t - 1} ht?1? 來計算新的隱藏狀態 h t h_t ht?和輸出 O t O_t Ot?。這個過程中會使用一些非線性激活函數(如 s i g m o i d sigmoid sigmoid 或 t a n h tanh tanh)來引入非線性變換.
def forward(self, inputs):h = np.zeros((1, self.hidden_size))self.last_inputs = inputsself.last_hs = {0: h}for i, x in enumerate(inputs):x = x.reshape(1, -1)h = np.tanh(np.dot(x, self.weights_ih) + np.dot(h, self.weights_hh) + self.bias_h)self.last_hs[i + 1] = hy = np.dot(h, self.weights_ho) + self.bias_oself.last_outputs = yreturn y
3.2.2 反向傳播時間(BPTT)
與傳統的反向傳播不同,BPTT 會在時間上展開整個數據序列,并在每個時間步計算梯度,然后利用這些梯度來調整權重,以降低總體損失。
假設我們有一個長度為 T T T 的時間序列數據,在每個時間步 t t t 都有一個簡單的損失函數 L t L_t Lt?(如回歸任務中的均方誤差),那么總損失 L t o t a l L_{total} Ltotal? 是每個時間步損失的總和:
L t o t a l = Σ t = 1 T L t L_{total}=\Sigma_{t=1}^{T}L_t Ltotal?=Σt=1T?Lt?
為了更新權重,我們需要計算 L t o t a l L_{total} Ltotal? 關于權重的梯度。對于權重矩陣 U U U(輸入到隱藏層)、 W W W(隱藏層到隱藏層)和 V V V(隱藏層到輸出層),梯度的計算公式如下:
def backprop(self, d_y, learning_rate, clip_value=1):n = len(self.last_inputs)d_y_pred = (self.last_outputs - d_y) / d_y.sized_Whh = np.zeros_like(self.weights_hh)d_Wxh = np.zeros_like(self.weights_ih)d_Why = np.zeros_like(self.weights_ho)d_bh = np.zeros_like(self.bias_h)d_by = np.zeros_like(self.bias_o)d_h = np.dot(d_y_pred, self.weights_ho.T)for t in reversed(range(1, n + 1)):d_h_raw = (1 - self.last_hs[t] ** 2) * d_hd_bh += d_h_rawd_Whh += np.dot(self.last_hs[t - 1].T, d_h_raw)d_Wxh += np.dot(self.last_inputs[t - 1].reshape(1, -1).T, d_h_raw)d_h = np.dot(d_h_raw, self.weights_hh.T)for d in [d_Wxh, d_Whh, d_Why, d_bh, d_by]:np.clip(d, -clip_value, clip_value, out=d)self.weights_ih -= learning_rate * d_Wxhself.weights_hh -= learning_rate * d_Whhself.weights_ho -= learning_rate * d_Whyself.bias_h -= learning_rate * d_bhself.bias_o -= learning_rate * d_by
3.2.3 權重更新
在計算出梯度后,我們使用優化算法(如隨機梯度下降)來更新權重。權重更新的公式如下: