神經網路的典型處理如下所示:
- 定義可學習引數的網路結構(堆疊各層和層的設計);
- 資料集的制作和輸入;
- 對輸入進行處理(由定義的網路層進行處理),主要體現在網路的前向傳播;
- 計算loss ,由Loss層計算;
- 反向傳播求梯度;
- 根據梯度改變引數值,最簡單的實作方式(SGD)為:
weight = weight - learning_rate * gradient
使用pytorch和auto_grad(torch自動求導功能):
import torch
#import numpy
#from torch.autograd import Variable
EPOCH = 500
LEARNING_RATE = 1e-6
N , D_in , H , D_out = 64 , 1000, 100 , 10
# N代表的是樣本個數,D_in是樣本的維度,H是隱藏層的維度,D_out是輸出層的維度
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用隨機值初始化兩層神經網路的權重
w1 = torch.randn(D_in,H,requires_grad=True)
w2 = torch.randn(H,D_out,requires_grad=True)
"""h = w1 * x
h_relu = relu(h)
y = w2 * x"""
for step in range(EPOCH):
#前向傳播
h = torch.mm(X, w1) # 隱層 h = w1 * x
h_relu = h.clamp(min=0) # relu 將小于0的部分修正為0 大于0的部分則不變
y_pred = torch.mm(h_relu, w2) # 輸出層 y = w2 * h_relu
# 損失函式計算誤差
loss = (y_pred - Y).pow(2).sum()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss.item()))#loss為(1,)的tensor
# 反向傳播 計算導數
loss.backward() # 會自動計算所有引數的導數(包括W1、W2、X)
#更新引數
with torch.no_grad():
#隨機梯度下降
w1 -= LEARNING_RATE * w1.grad
w2 -= LEARNING_RATE * w2.grad
#更新完梯度之后要手動置0,不置0會一直疊加
w1.grad.zero_()
w2.grad.zero_()
使用pytorch(反向傳播要自己求導):
import torch
EPOCH = 500
LEARNING_RATE = 1e-6
#超引數初始化
N , D_in , H , D_out = 64 , 1000, 100 , 10 # N代表的是樣本個數,D_in是樣本的維度,H是隱藏層的維度,D_out是輸出層的維度
#訓練資料和引數初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用隨機值初始化兩層神經網路的權重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
#print("X:",X,"Y:",Y,w1,w2)
for step in range(500):
#前向傳播
h = X.mm(w1) #(N,H)
h_relu = h.clamp(min=0)#(N,H)
y_pred = h_relu.mm(w2) #(N,D_out)
#定義損失函式
loss = (y_pred - Y).pow(2).sum().item()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss))#loss為(1,)的tensor
#反向傳播
grad_y_pred = 2.0 * (y_pred - Y)#(N,D_out)
grad_w2 = h_relu.t().mm(grad_y_pred)#(H,D_out)
grad_h_relu = grad_y_pred.mm(w2.t())#(N,H)
grad_h[h > 0] = grad_h_relu[h > 0].clone()#大于0時導數不變
grad_h[h < 0] = 0#小于0時導數變0
grad_w1 = X.t().mm(grad_h)#要grad_w1的矩陣維度和w1維度相同,才能相減
#引數更新
w1 -= LEARNING_RATE * grad_w1
w2 -= LEARNING_RATE * grad_w2
這種寫法,反向傳播的求導是最大的難點,需要理解正向傳播和反向傳播來推導公式,再把公式用代碼實作,最好需要看一下吳恩達的機器學習視頻的前三章(代價函式和梯度求導)和神經網路部分,理解反向傳播的計算方法,但是它的視頻的激勵函式不同,我們需要針對本代碼中的relu函式來實作反向傳播,
這里我貼出了手寫的推導程序:

下面是對神經網路里面的一些tensor進行輸出,從維度來理解
import torch
lr = 1e-6
EPOCH = 500
LEARNING_RATE = 1e-6
#超引數初始化
N , D_in , H , D_out = 3 , 4, 2 ,1 # N代表的是樣本個數,D_in是樣本的維度,H是隱藏層的維度,D_out是輸出層的維度
#訓練資料和引數初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用隨機值初始化兩層神經網路的權重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
print("X:",X)#3樣本 4特征
print("Y:",Y)#3結果
print("w1:",w1)
print("w2",w2)
h = X.mm(w1)
print("h:",h)
h_relu = h.clamp(min=0)#(N,h_dim)
print("h_relu",h_relu)
附上運行結果和個人理解:
X: tensor([[ 1.3393, -0.3668, -0.3531, 1.4490],
[-0.2834, 0.3056, 1.0691, 1.7448],
[ 0.1956, 0.9079, 0.4525, -1.1220]])
Y: tensor([[-1.8117],
[-0.4406],
[ 1.1850]])
w1: tensor([[ 1.4459, -0.1429],
[-0.8366, -0.5614],
[-1.4148, -0.4373],
[ 0.4911, -1.1529]])
w2 tensor([[-0.6083],
[-0.2623]])
h: tensor([[ 3.4545, -1.5016],
[-1.3210, -2.6101],
[-1.6679, 0.5581]])
h_relu tensor([[3.4545, 0.0000],
[0.0000, 0.0000],
[0.0000, 0.5581]])
- 神經網路的示意圖是以一個特征(維度)為一個單元,而不是變數,
- X有三個變數,每個變數有四個特征(維度),W1分別對四個特征的每個特征有兩種權值
- 隱藏層有三個變數,兩個單元(維度)
- 將變數的4種特征×權值1相加之后,就得到了隱藏層單元里這個對應變數的特征值1
- 將變數的4種特征×權值2相加之后,就得到了隱藏層單元里這個對應變數的特征值2
參考:
- 吳恩達機器學習視頻:https://www.bilibili.com/video/av50747658?from=search&seid=8008773056378130405
- https://blog.csdn.net/qq_30057549/article/details/103018003
- 個人的針對吳恩達機器學習視頻的筆記(下一篇推出,參考修改自黃海廣博士)
最后
其實這已經是年初1月做的了, 距離現在已經很久啦, 如今想來, 這依然是入門深度學習最好的實踐之一 , 入門深度學習的第一份代碼,應該是這個,
然后吳恩達的機器學習視頻也在上半年看完了,我是在黃海廣博士的博客上稍作修改我的吳恩達機器學習筆記的,
但是后來發現,本地的markdown博客并不能在csdn上直接展示,里面的圖很難傳,就不更新啦,有需要可以聯系我要,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/226619.html
標籤:AI
