使用numpy實現兩層神經網絡
1. 網絡結構及實現思路
以下爲次此依賴的的網絡結構,並且後邊的所有思路及編程都將遵循這個結構給出。
其中隱藏層、激活函數(採用Relu函數)、輸出層的內容如下:
其整體實現思路如下:
1. 定義神經網絡參數
2. 實現前饋神經網絡 forward pass
3. 計算損失 loss
4. 實現反向傳播 backword pass
2.編程實現及公式推導
# @Time : 2020/5/7 23:25
# @Author : kingback
# @File : model_practice.py
# @Software: PyCharm
## 使用numpy實現兩層神經網絡
import torch
import numpy as np
#一個全連接的Relu神經網絡,一個隱藏層,沒有bias,用來從x預測y:
#這一實現的三大過程:
#1.前饋神經網絡 forword pass
#2.計算損失 loss
#3.反向傳播 backword pass
#神經網絡參數定義:
N,D_in,D_out,H=64,1000,10,100
# N:代表64個人
# D_in:代表每個人輸入到神經網絡1000個數據點
# D_out:代表每個人從神經網絡輸出10個數據點
# H:代表該神經網絡含有100個隱藏層
x=np.random.randn(N,D_in)
#定義輸入到神經網絡之前的數據矩陣,大小爲64*1000
y=np.random.randn(N,D_out)
#定義從神經網絡輸出的的數據矩陣,大小爲64*10
w_1=np.random.randn(D_in,H)
#大小爲1000*100
w_2=np.random.randn(H,D_out)
#大小爲100*10
#定義學習率 learning rate
learning_rate=1e-06
for it in range(500):
#forword pass
h=x.dot(w_1)
#numpy中的點乘np.dot是數學意義上的向量內積
#print(h.shape)
#打印矩陣維度信息
h_relu=np.maximum(h,0)
#定義relu 函數,是目前深度神經網絡中經常使用的激活函數。
y_hat=h_relu.dot(w_2)
#大小爲64*10
#計算損失compute loss
loss=np.square(y_hat-y).sum()
#估計值與真實值之間差值的平方和再取和
print(it,loss)
#計算梯度,主要是對(y_hat-y)^2求各項偏導
y_hat_grad=2*(y_hat-y)
w_2_grad=h_relu.T.dot(y_hat_grad)
h_relu_grad=y_hat_grad.dot(w_2.T)
h_grad=h_relu_grad.copy()
h_grad[h<0]=0
w_1_grad=x.T.dot(h_grad)
#更新w_1和w_2的權值
w_1=w_1-learning_rate*w_1_grad
w_2=w_2-learning_rate*w_2_grad
這裏需要說明的一點就是在計算各參數的梯度問題時,是在估計值與真實值之間差值的平方的基礎上進行求偏導的,我們令其爲A,則有:
易得:
後面幾個偏導的計算就很容易寫錯了:
因爲,則有:
所以對h求偏導則有:
最後我們再對w_1求偏導:
有了上邊的推導,相信大家很容易就理解代碼了吧。嘿嘿嘿
3.結果測試
在結果中我們可以看到,在程序剛開始時和程序結束時的loss值有了明顯減小:
程序開始時loss值 | 程序結束時loss值 |
---|---|
可以看到程序在訓練了500次的情況下,我們的這個兩層的神經網絡效果還是比較不錯的。接下來我也將會繼續將該模型改寫爲torch版本的。