機器學習入門(13)— Affine 仿射層、Softmax 歸一化指數函數層實現

1. 一維 Affine 仿射層

我們回顧下之前爲了計算加權信號的總和,使用了矩陣的乘積運算 NumPy 中是 np.dot() , 參照代碼如下:

In [7]: X = np.random.rand(2)

In [8]: W = np.random.rand(2,3)

In [9]: B = np.random.rand(3)

In [10]: X
Out[10]: array([0.4789532 , 0.09922952])

In [11]: W
Out[11]: 
array([[0.57158149, 0.58963237, 0.99674485],
       [0.80968617, 0.57239467, 0.07508432]])

In [12]: X.shape
Out[12]: (2,)

In [13]: W.shape
Out[13]: (2, 3)

In [14]: B.shape
Out[14]: (3,)

In [15]: Y = np.dot(X, W) + B

In [16]: 

這裏,XWB 分別是形狀爲 (2,)、(2, 3)、(3,) 的多維數組。這樣一來,神經元的加權和可以用 Y = np.dot(X, W) + B 計算出來。然後,Y 經過激活函數轉換後,傳遞給下一層。這就是神經網絡正向傳播的流程。

矩陣的乘積運算的要點是使對應維度的元素個數一致。比如,如下面的圖5-23 所示,XW 的乘積必須使對應維度的元素個數一致。

矩陣乘積對應維度

神經網絡的正向傳播中進行的矩陣的乘積運算在幾何學領域被稱爲“仿射變換”。因此,這裏將進行仿射變換的處理實現爲 “Affine層”。

計算圖如下,並且在各個變量的上方標記了它們的形狀(比如,計算圖上顯示了 X 的形狀爲(2,),X·W 的形狀爲(3,) 等。)
放射變換層
圖5-24 的計算圖的反向傳播。以矩陣爲對象的反向傳播,按矩陣的各個元素進行計算時,步驟和以標量爲對象的計算圖相同。如下式所示:

計算圖公式
我們根據式(5.13),嘗試寫出計算圖的反向傳播,如圖5-25 所示。
反向傳播圖
式 5.13 的推導
圖 5.26

2. 多維 Affine 仿射層

多維 Affine 層的計算圖,如圖 5-27 所示。
多維仿射層計算圖
加上偏置時,需要特別注意。正向傳播時,偏置被加到 X·W 的各個數據上。比如,N = 2(數據爲2 個)時,偏置會被分別加到這 2 個數據(各自的計算結果)上,具體的例子如下所示。

In [17]: X_dot_W = np.array([[0, 0, 0], [10, 10, 10]])

In [18]: B = np.array([1,2,3])

In [19]: X_dot_W
Out[19]: 
array([[ 0,  0,  0],
       [10, 10, 10]])

In [20]: X_dot_W + B
Out[20]: 
array([[ 1,  2,  3],
       [11, 12, 13]])

In [21]:

正向傳播時,偏置會被加到每一個數據(第1 個、第2 個……)上。因此,反向傳播時,各個數據的反向傳播的值需要彙總爲偏置的元素。用代碼表示的話,如下所示。

In [21]: dY = np.array([[1,2,3], [4,5,6]])

In [22]: dY
Out[22]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [23]: dB = np.sum(dY, axis=0)

In [24]: dB
Out[24]: array([5, 7, 9])

In [25]: 

這個例子中,假定數據有2 個(N = 2)。偏置的反向傳播會對這 2 個數據的導數按元素進行求和。因此,這裏使用了 np.sum() 對第0 軸(以數據爲單位的軸,axis=0)方向上的元素進行求和。

下面代碼考慮了輸入數據爲張量(四維數據)的情況。

class Affine:
    def __init__(self, W, b):
        self.W =W
        self.b = b
        
        self.x = None
        self.original_x_shape = None
        # 權重和偏置參數的導數
        self.dW = None
        self.db = None

    def forward(self, x):
        # 對應張量
        self.original_x_shape = x.shape
        x = x.reshape(x.shape[0], -1)
        self.x = x

        out = np.dot(self.x, self.W) + self.b

        return out

    def backward(self, dout):
        dx = np.dot(dout, self.W.T)
        self.dW = np.dot(self.x.T, dout)
        self.db = np.sum(dout, axis=0)
        
        dx = dx.reshape(*self.original_x_shape)  
        # 還原輸入數據的形狀(對應張量)
        return dx

3. Softmax 歸一化指數函數層

待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章