搭建一個簡易的神經網絡及理解其中的矩陣求導及反向傳播推導

搭建一個基於PyTorch架構的簡易神經網絡模型 

代碼參考《深度學習之pytorch實戰計算機視覺》

#搭建一個簡易神經網絡
import torch
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

x = torch.randn(batch_n,input_data)
y = torch.randn(batch_n,output_data)

w1 = torch.randn(input_data,hidden_layer)
w2 = torch.randn(hidden_layer,output_data)

epoch_n = 500
learning_rate = 1e-6

for epoch in range(epoch_n):
    h1 = x.mm(w1)
    h1 = h1.clamp(min = 0)
    y_pred = h1.mm(w2)  #100*10

    loss = (y_pred - y).pow(2).sum()
    print("Epoch:{}, Loss:{:.4f}".format(epoch,loss))

    grad_y_pred = 2*(y_pred - y)
    grad_w2 = h1.t().mm(grad_y_pred)

    grand_h = grad_y_pred.clone()
    grand_h = grand_h.mm(w2.t())
    grand_h.clamp_(min=0)
    grand_w1 = x.t().mm(grand_h)

    w1 -= learning_rate * grand_w1
    w2 -= learning_rate * grad_w2

以上爲完整代碼,接下來依次解讀:

import torch
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

首先定義了4個整型變量,其中:batch_n是指在一個批次中輸入數據的數量,值是100,這意味着我們在一個批次中輸入100個數據,同時input_data = 1000,所以每個數據的數據特徵是1000個,hidden_layer = 100用於定義經過隱藏層後保留的數據特徵個數,因爲我們的模型只考慮一層隱藏層,所以代碼中僅定義了一個隱藏層的參數,output_data = 10 是輸出的數據,可以將輸出數據看做是一個分類結果值的數量,個數10表示我們最後要得到10個分類結果值。

所以一個批次的數據從完整的輸入到輸出的過程是:先輸入100個具有1000個特徵的數據,經過隱藏層後變爲100具有100個特徵的數據,再經過輸出層後輸出100個具有10個分類結果值的數據,在得到輸出結果後計算損失並進行後向傳播,這樣一次模型的訓練就完成了,然後循環這個流程指定訓練次數。

x = torch.randn(batch_n,input_data)
y = torch.randn(batch_n,output_data)

w1 = torch.randn(input_data,hidden_layer)
w2 = torch.randn(hidden_layer,output_data)

 

對輸入層到隱藏層,隱藏層再到輸出層的權重初始化定義如上,這些參數維度與前面說到的過程是一致的。我們可以觀察到輸入層維度是(100,1000),輸出層維度是(100,10),輸入層到隱藏層的權重參數維度是(1000,100),隱藏層再到輸出層的權重參數維度是(100,100)。我們將整個過程看作是矩陣連續的乘法運算就能知道權重參數的維度是如何定義的了。

明確訓練的總次數和學習速率

epoch_n = 500
learning_rate = 1e-6

接下來用梯度下降的方法來優化神經網絡的參數

for epoch in range(epoch_n):
    h1 = x.mm(w1)    #100*1000
    h1 = h1.clamp(min = 0)    #剪裁蕾絲於ReLU激活函數
    y_pred = h1.mm(w2)  #100*10

    loss = (y_pred - y).pow(2).sum()
    print("Epoch:{}, Loss:{:.4f}".format(epoch,loss))

    grad_y_pred = 2*(y_pred - y)
    grad_w2 = h1.t().mm(grad_y_pred)

    grand_h = grad_y_pred.clone()
    grand_h = grand_h.mm(w2.t())
    grand_h.clamp_(min=0)
    grand_w1 = x.t().mm(grand_h)

    w1 -= learning_rate * grand_w1
    w2 -= learning_rate * grad_w2

前向傳播的預測結果用y_pred來表示,用loss表示誤差值,使用均方誤差函數計算。代碼後面的部分就是實現後向傳播對權重參數進行優化,代碼中爲了計算方便使用的是每個節點的鏈式求導結果。在得到梯度值後按照定義好的學習速率對w1,w2對權重參數進行更新。

接下來對於梯度的反向傳播計算進行描述:(其實每個變量的梯度下降與計算的倒數有關)

以下公式及過程摘自:https://blog.csdn.net/DawnRanger/article/details/78600506

首先給出看一下計算過程

求導過程:

實值函數對矩陣求導

線性變換的導數:

矩陣線性變換求導:

 

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