1. 程式人生 > >用純Python實現迴圈神經網路RNN向前傳播過程(吳恩達DeepLearning.ai作業)

用純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步:

  1. 取出引數。

  2. 計算at。

  3. 計算yt^。

  4. 返回輸出的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