目錄
BP學習目标
BP計算圖
BP的鍊式法則chain rule
計算流程:
前向網絡傳播
反向傳播過程
完整的計算圖舉例:
代碼剖析:
練習:
練習代碼:
結果:
總結:
BP學習目标
對權重w進行更新,随機梯度下降采用的是loss對w進行求導求梯度,使得w的更新來減少loss,并盡可能是loss最小。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPFRVT4VEVNhXRU1UdsdlYrZkMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4UzNzQTNyMjMxADOwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
BP計算圖
這個結構就成為神經網絡中的一層
完整的兩層神經網絡如下圖。 具體的Matrix multiplication矩陣乘法可以參考 matrix cookbook。
BP的鍊式法則chain rule
1. 前饋網絡形式,先向前計算從輸入x和權重w,然後算出loss
2. Local gradient,求f關于x的導數和關于w的導數
3. 再反向将loss關于z的偏導傳遞
4. 反向傳播,使用鍊式法則來求的loss關于x的偏導和關于w的偏導,進而産生新的輸入内容
計算流程:
前向網絡傳播
反向傳播過程
完整的計算圖舉例:
Tensor 張量,可以是标量,向量,也可以是三維的,還可以是更高階的資料。
代碼剖析:
1. 确定好張量w後,建構計算圖、
因為目前張量w是一個數,是以torch.Tensor([1.0]),用中括号括起來的數值填寫1.0就可以了。
預設情況下tensor不會保留計算的梯度,是以需要w.requires_grad = True 來計算獲得張量的梯度。
2. 因為w是張量需要擷取w的梯度,是以x*w計算後也是張量也需要擷取x*w的梯度
3. 每調用一次loss函數,建構一次計算圖。獲得loss
4. 前饋過程,計算loss
5. 回報過程,計算張量的梯度,在反向傳播的過程中計算所有張量需要的梯度
6. 利用梯度來更新權重,因為梯度也是tensor,而進行tensor的計算需要建構計算圖,但是更新權重隻是數值的計算也不需要建構計算圖,是以需要用tensor的data,即w.data= w.data - 0.01 * w.grad.data.
在更新權重之前可以使用張量直接計算,但是到權重更新時隻能使用标量。
7. 将權重裡面的梯度資料全部清零。在這裡梯度不需要累加,是以需要顯式地清零。不然得到的權重的梯度就是累加的結果。
8. 擷取損失,繼續疊代。l.item()來擷取标量的損失,epoch表示疊代第幾輪
練習:
練習代碼:
import torch
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
# create the data
x_data = [1.0, 2.0, 3.0]
y_data = [4.0, 9.0, 16.0]
# create the Tensor for grad
w1 = torch.Tensor([1.0]) # 初始權值
w1.requires_grad = True
w2 = torch.Tensor([1.0])
w2.requires_grad = True
b = torch.Tensor([1.0])
b.requires_grad = True
# define the linear model
def forward(x):
return x * x * w1 + x * w2 + b # x^2*w1 + x * w2 also is a Tensor w1=1, w2=2, b=1
def loss(x, y): # 建構計算圖
y_pred = forward(x)
return (y_pred - y) ** 2
print("predict (before training)", 4, forward(4).item())
# training
epoch_list = []
loss_list = []
for epoch in range(1000):
for x, y in zip(x_data, y_data):
l = loss(x, y)
l.backward()
print('\t grad:', x, y, w1.grad.item(), w2.grad.item(), b.grad.item())
w1.data = w1.data - 0.01 * w1.grad.data #注意這裡的grad是一個tensor,是以要取他的data
w2.data = w2.data - 0.01 * w2.grad.data
b.data = b.data - 0.01 * b.grad.data
w1.grad.data.zero_() #釋放之前計算的梯度
w2.grad.data.zero_()
b.grad.data.zero_()
epoch_list.append(epoch)
loss_list.append(l.item())
print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())
plt.plot(epoch_list, loss_list)
plt.ylabel("loss")
plt.xlabel("epoch")
plt.show()
結果:
#predict (before training) 4 21.0
#訓練1000epoch
#predict (after training) 4 25.152122497558594
#訓練10000epoch
#predict (after training) 4 25.000938415527344
#在修改訓練集的x,y值後,訓練結果接近25,
總結:
BP學習過程由信号正向傳播和誤差反向傳播兩個階段構成。其中信号正向傳播用于獲得在隐含層神經元和輸出層神經元的輸出信号;誤差反向傳播用于将網絡期望輸出與實際輸出的誤差從輸出層反向傳播至隐含層在至輸入層,并在此過程中更新各個神經元的連接配接權值。
參考:《PyTorch深度學習實踐》完結合集_哔哩哔哩_bilibili