用純Python實現迴圈神經網路RNN向前傳播過程(吳恩達DeepLearning.ai作業)
Google TensorFlow程式設計師點讚的文章!
前言
目錄:
- 向量表示以及它的維度
- rnn cell
- rnn 向前傳播
重點關注:
- 如何把資料向量化的,它們的維度是怎麼來的
- 一共其實就是兩步: 單個單元的rnn計算,拉通來的rnn計算
在看本文前,可以先看看這篇文章回憶一下:
吳恩達deepLearning.ai迴圈神經網路RNN學習筆記(理論篇)
我們將實現以下結構的RNN,在這個例子中 Tx = Ty。
向量表示以及它的維度
Input with nx number of units
-
對單個輸入樣本,x(i) 是一維輸入向量。
-
用語言來舉個例子,將具有5k個單詞詞彙量的語言用one-hot編碼成具有5k個單位的向量,所以 x(i) 的維度是(5000,)。
-
我們將用符號 nx 表示單個訓練樣本的單位數。
Batches of size m
-
如果我們取小批量(mini-batches),每個批次有20個訓練樣本。
-
為了受益於向量化,我們將20個樣本 x(i) 變成一個2維陣列(矩陣)。
-
比如一個維度是(5000,20)的向量。
-
我們用m來表示訓練樣本的數量。
-
所以小批量訓練資料的維度是 (nx, m)。
Time steps of size Tx
-
迴圈神經網路有多個時間步驟,我們用t來表示。
-
我們將看到訓練樣本 x(i) 將經歷多個時間步驟 Tx, 比如如果有10個時間步驟,那麼 Tx = 10。
3D Tensor of shape (nx, m, Tx)
-
輸入x就是用維度是 (nx, m, Tx) 的三維張量來表示。
Taking a 2D slice for each time step:
-
每一個時間步驟,我們用小批量訓練樣本(不是單個的訓練樣本)。
-
所以針對每個時間步驟t,我們用維度是 (nx, m)的2維切片。
-
我們把它表示成xt。
隱藏狀態a的維度
-
a的定義: 從一個時間步驟到另一個時間步驟的啟用值 at, 我們把它叫做隱藏狀態。
-
同輸入張量 x 一樣,對於單個訓練樣本的隱藏狀態,它的向量長度是na。
-
如果我們是包含了m個訓練樣本的小批量資料,那麼小批量維度是 (na, m)。
-
如果我們把時間步加進去,那麼隱藏狀態的維度就是 (na, m, Tx)。
-
我們將用索引t來遍歷時間步,每次操作是從3維張量切片成的2維向量。
-
我們用at來表示2維的切片,它的維度是 (na, m)。
預測值y^的維度
-
同輸入x和隱藏狀態一樣,y^是一個維度是 (ny, m, Ty) 的3維張量。
-
ny: 代表預測值的單位數。
-
m: 小批次訓練的樣本數量。
-
Ty: 預測的時間數。
-
比如單個時間步 t,2維的切片 y^ 的維度是 (ny, m)。
RNN cell
我們的第一個任務就是執行單個時間步驟的計算,計算如下圖。
輸入是a^<t-1>, xt,輸出是at, yt^。以下的程式碼其實就是把上面的公式程式碼化,總的步驟分成4步:
-
取出引數。
-
計算at。
-
計算yt^。
-
返回輸出的at, yt^,還要儲存一些值快取起來。
import numpy as np def rnn_cell_forward(xt, a_prev, parameters): """ Implements a single forward step of the RNN-cell as described in Figure (2) Arguments: xt -- your input data at timestep "t", numpy array of shape (n_x, m). a_prev -- Hidden state at timestep "t-1", numpy array of shape (n_a, m) parameters -- python dictionary containing: Wax -- Weight matrix multiplying the input, numpy array of shape (n_a, n_x) Waa -- Weight matrix multiplying the hidden state, numpy array of shape (n_a, n_a) Wya -- Weight matrix relating the hidden-state to the output, numpy array of shape (n_y, n_a) ba -- Bias, numpy array of shape (n_a, 1) by -- Bias relating the hidden-state to the output, numpy array of shape (n_y, 1) Returns: a_next -- next hidden state, of shape (n_a, m) yt_pred -- prediction at timestep "t", numpy array of shape (n_y, m) cache -- tuple of values needed for the backward pass, contains (a_next, a_prev, xt, parameters) """ # 取計算的引數 Wax = parameters["Wax"] Waa = parameters["Waa"] Wya = parameters["Wya"] ba = parameters["ba"] by = parameters["by"] # 用公式計算下一個單元的啟用值 a_next = np.tanh(np.dot(Waa, a_prev) + np.dot(Wax, xt) + ba) # 計算當前cell的輸出 yt_pred = softmax(np.dot(Wya, a_next) + by) # 用於向後傳播的快取值 cache = (a_next, a_prev, xt, parameters) return a_next, yt_pred, cache
RNN向前傳播
-
一個迴圈神經網路就是不斷的重複你上面建立的rnn 單元。
-
如果你的輸入資料序列是10個時間步,那麼你就要重複你的rnn cell 10次。
-
在每個時間步中,每個單元將用2個輸入:
-
a<t-1>: 前一個單元的隱藏狀態。
-
xt: 當前時間步的輸入資料。
-
每個時間步有兩個輸出:
-
一個隱藏狀態at
-
一個測值y^⟨t⟩
-
權重和偏差 (Waa,ba,Wax,bx) 將在每個時間步中迴圈使用,它們儲存在"parameters"的變數中。
def rnn_forward(x, a0, parameters): """ Implement the forward propagation of the recurrent neural network described in Figure (3). Arguments: x -- Input data for every time-step, of shape (n_x, m, T_x). a0 -- Initial hidden state, of shape (n_a, m) parameters -- python dictionary containing: Waa -- Weight matrix multiplying the hidden state, numpy array of shape (n_a, n_a) Wax -- Weight matrix multiplying the input, numpy array of shape (n_a, n_x) Wya -- Weight matrix relating the hidden-state to the output, numpy array of shape (n_y, n_a) ba -- Bias numpy array of shape (n_a, 1) by -- Bias relating the hidden-state to the output, numpy array of shape (n_y, 1) Returns: a -- Hidden states for every time-step, numpy array of shape (n_a, m, T_x) y_pred -- Predictions for every time-step, numpy array of shape (n_y, m, T_x) caches -- tuple of values needed for the backward pass, contains (list of caches, x) """ # 用於儲存所有cache的列表,初始化它 caches = [] # 取一些緯度值,用於後面初始化變數 n_x, m, T_x = x.shape n_y, n_a = parameters["Wya"].shape # 初始化 a 和 y_pred a = np.zeros((n_a, m, T_x)) y_pred = np.zeros((n_y, m, T_x)) # 初始化 a_next a_next = a0 # loop over all time-steps of the input 'x' for t in range(T_x): # Update next hidden state, compute the prediction, get the cache xt = x[:,:,t] # 通過切片的方式從輸入變數x中取出當前t時間步的輸入xt a_next, yt_pred, cache = rnn_cell_forward(xt, a_next, parameters) # 儲存當前單元計算的a_next值 a[:,:,t] = a_next # 儲存當前單元的預測值y y_pred[:,:,t] = yt_pred # 新增每個單元的快取值 caches.append(cache) # store values needed for backward propagation in cache caches = (caches, x) return a, y_pred, caches
恭喜你(*^▽^*),到這裡你已經能夠從0到1的構建迴圈神經網路的向前傳播過程。
在現代深度學習框架中,您僅需實現前向傳遞,而框架將處理後向傳遞,因此大多數深度學習工程師無需理會後向傳遞的細節。我就不寫向後傳播了。
&n