遞歸神經網絡(RNN)對於天然語言處理和其餘序列任務很是有效,由於它們具備「記憶」功能。 它們能夠一次讀取一個輸入x⟨t⟩
(如單詞),而且經過隱藏層激活從一個時間步傳遞到下一個時間步來記住一些信息/上下文,這容許單向RNN從過去獲取信息來處理後面的輸入,雙向RNN能夠從過去和將來中獲取上下文。網絡
有些東西須要聲明:
app
1 - 循環神經網絡的前向傳播
咱們來看一下下面的循環神經網絡的圖,在這裏使用的是Tx=Ty,咱們來實現它。
函數
咱們怎麼才能實現它呢?有如下步驟:spa
實現RNN的一個時間步所須要計算的東西。
在Tx 時間步上實現一個循環,以便一次處理全部輸入。
code
循環神經網絡能夠看做是單元的重複,首先要實現單個時間步的計算,下圖描述了RNN單元的單個時間步的操做。blog
1 def rnn_cell_forward(xt, a_prev, parameters): 2 """ 3 根據圖2實現RNN單元的單步前向傳播 4 5 參數: 6 xt -- 時間步「t」輸入的數據,維度爲(n_x, m) 7 a_prev -- 時間步「t - 1」的隱藏隱藏狀態,維度爲(n_a, m) 8 parameters -- 字典,包含了如下內容: 9 Wax -- 矩陣,輸入乘以權重,維度爲(n_a, n_x) 10 Waa -- 矩陣,隱藏狀態乘以權重,維度爲(n_a, n_a) 11 Wya -- 矩陣,隱藏狀態與輸出相關的權重矩陣,維度爲(n_y, n_a) 12 ba -- 偏置,維度爲(n_a, 1) 13 by -- 偏置,隱藏狀態與輸出相關的偏置,維度爲(n_y, 1) 14 15 返回: 16 a_next -- 下一個隱藏狀態,維度爲(n_a, m) 17 yt_pred -- 在時間步「t」的預測,維度爲(n_y, m) 18 cache -- 反向傳播須要的元組,包含了(a_next, a_prev, xt, parameters) 19 """ 20 21 # 從「parameters」獲取參數 22 Wax = parameters["Wax"] 23 Waa = parameters["Waa"] 24 Wya = parameters["Wya"] 25 ba = parameters["ba"] 26 by = parameters["by"] 27 28 # 使用上面的公式計算下一個激活值 29 a_next = np.tanh(np.dot(Waa, a_prev) + np.dot(Wax, xt) + ba) 30 31 # 使用上面的公式計算當前單元的輸出 32 yt_pred = rnn_utils.softmax(np.dot(Wya, a_next) + by) 33 34 # 保存反向傳播須要的值 35 cache = (a_next, a_prev, xt, parameters) 36 37 return a_next, yt_pred, cache
能夠看到的是RNN是剛剛構建的單元格的重複鏈接,若是輸入的數據序列通過10個時間步,那麼將複製RNN單元10次,每一個單元將前一個單元中的隱藏狀態遞歸
(a⟨t−1⟩ a^{\langle t-1 \rangle}a ⟨t−1⟩)和當前時間步的輸入數據(x⟨t⟩ x^{\langle t \rangle}x ⟨t⟩)做爲輸入。 它爲此時間步輸出隱藏狀態(a⟨t⟩ a^{\langle t \rangle}a ⟨t⟩)和預測(y⟨t⟩ y^{\langle t \rangle}y ⟨t⟩)。
class
咱們要根據圖3來實現前向傳播的代碼,它由如下幾步構成:神經網絡
建立0向量zeros(a),它將保存RNN計算的全部的隱藏狀態。循環
使用「a0 a_0a
0
」初始化「next」隱藏狀態。
循環全部時間步:
使用rnn_cell_forward函數來更新「next」隱藏狀態與cache。
使用a來保存「next」隱藏狀態(第t)個位置。
使用y來保存預測值。
把cache保存到「caches」列表中。
返回a,y與caches。
1 def rnn_forward(x, a0, parameters): 2 """ 3 根據圖3來實現循環神經網絡的前向傳播 4 5 參數: 6 x -- 輸入的所有數據,維度爲(n_x, m, T_x) 7 a0 -- 初始化隱藏狀態,維度爲 (n_a, m) 8 parameters -- 字典,包含了如下內容: 9 Wax -- 矩陣,輸入乘以權重,維度爲(n_a, n_x) 10 Waa -- 矩陣,隱藏狀態乘以權重,維度爲(n_a, n_a) 11 Wya -- 矩陣,隱藏狀態與輸出相關的權重矩陣,維度爲(n_y, n_a) 12 ba -- 偏置,維度爲(n_a, 1) 13 by -- 偏置,隱藏狀態與輸出相關的偏置,維度爲(n_y, 1) 14 15 返回: 16 a -- 全部時間步的隱藏狀態,維度爲(n_a, m, T_x) 17 y_pred -- 全部時間步的預測,維度爲(n_y, m, T_x) 18 caches -- 爲反向傳播的保存的元組,維度爲(【列表類型】cache, x)) 19 """ 20 21 # 初始化「caches」,它將以列表類型包含全部的cache 22 caches = [] 23 24 # 獲取 x 與 Wya 的維度信息 25 n_x, m, T_x = x.shape 26 n_y, n_a = parameters["Wya"].shape 27 28 # 使用0來初始化「a」 與「y」 29 a = np.zeros([n_a, m, T_x]) 30 y_pred = np.zeros([n_y, m, T_x]) 31 32 # 初始化「next」 33 a_next = a0 34 35 # 遍歷全部時間步 36 for t in range(T_x): 37 ## 1.使用rnn_cell_forward函數來更新「next」隱藏狀態與cache。 38 a_next, yt_pred, cache = rnn_cell_forward(x[:, :, t], a_next, parameters) 39 40 ## 2.使用 a 來保存「next」隱藏狀態(第 t )個位置。 41 a[:, :, t] = a_next 42 43 ## 3.使用 y 來保存預測值。 44 y_pred[:, :, t] = yt_pred 45 46 ## 4.把cache保存到「caches」列表中。 47 caches.append(cache) 48 49 # 保存反向傳播所須要的參數 50 caches = (caches, x) 51 52 return a, y_pred, caches