反向傳播
B站視頻學習鏈接:3 反向傳播
0 復習回顧
在上一節課程中,主要使用的是numpy庫函數配合梯度下降算法來進行咱們權重的一個選取操作。
主要的模型是一個最簡單的線性模型(是線性模型里面最簡單的一個哈),\(\hat{y}=x*\omega\),用這個模型進行的一個算法的模擬。就像是下面這個圖片展示的這個樣子。
第一步、咱們輸入了變量\(x\)和相對應的權重\(w\),并將這兩個變量按照函數要求進行數值相乘,得到咱們的計算值\(\hat{y}\)。
第二步、將得到的計算值\(\hat{y}\)作為輸入重新進入下一層內求出損失函數\(loss\)。

第三步、求解該損失函數在該條件下的梯度,\(\frac{\partial loss_n}{\partial\omega}=2\cdot x_n\cdot(x_n\cdot\omega-y_n)\)。
第四步、重新更新咱們的權重,\(\omega=\omega-\alpha\frac{\partial loss}{\partial\omega}\),知道穩定收斂為止。

咱們上一次的例子是一個線性的模型,同時還是線性模型里面最簡單的一個模型,因此在計算解析式的時候難度不大,但是一般而言,咱們的深度學習網絡是有很多層的,并且輸入的變量個數也不僅僅只有一個,像是下面這圖片所示。
試問這種類型的深度學習網絡模型該如何求解他的解析式呢?
這個模型左側有\(5\)組\(x\)的輸入,第一個隱層有\(6\)個節點,因此第一層就有\(30\)個權重,那么后面慢慢累積起來,這個運算量大的恐怖,基本上是無法求解他的解析式的!

那么我們應該如何求解他的梯度呢,這個時候咱們想到了鏈式法則。
1 反向傳播原理
1.1 引入原理
首先讓我們上一點難度,看看雙層的線性模型是個什么樣子的,下面是一個雙層的神經網絡模型\(\hat{y}=W_{2}(W_{1}\cdot X+b_{1})+b_{2}\)。

這個是一個雙層的神經網絡,首先咱們看看他的第一層,也就是權重\(w_1\)所在的那一層

在這里面我們令\(H^{(1)}\)作為我們的隱層則有\(H^{(1)} = W_1^{T}X\)。這幾個數據的形狀為

因此第一層是這個玩意兒,我們需要確定矩陣的形狀大小,一定要求這\(W_1\)的大小是\(m \times n\)的其中\(mm\)表示的是\(matrix multiplication\) 每一個隱層都有一個偏置量即\(bias-b\),\(b_1\)是\(m\)維度的

然后我們將第一層的輸出結果進行再一次的矩陣乘法,便得到了第二層的神經網絡。

而對于矩陣求導的話可以找一本書叫做\(mairix\ cookbook\)這本書
本地位置: [martix cookbook.pdf](....\martix cookbook.pdf)
網絡連接:martix-cookbook-pdf
j如果咱們現在將上面講的雙層線性模型進行展開可以得到下面這個東西,不難看出多層線性變換可以獲得同一個形式的解,因此這么多層就沒有意義了,故需要添加非線性的層才有意義。
就像下面一樣我們可以適當的引入一些非線性層會更加的有意義。

上面就是采用了一些非線性的函數進行了優化以防止展開成基本相同的線性函數。
1.3 求導法則

上面是一個比較好的一個概念,其中\(g , f\)這兩個分別是兩種對應法則,\(fog(x)\)就是\(f(g(x))\)因此,如果相對x求導數,那么就需要使用矩陣的鏈式法則。
\(\frac{\mathrmw0obha2h00fog(x)}{\mathrmw0obha2h00x}=\frac{\mathrmw0obha2h00fog(x)}{\mathrmw0obha2h00g(x)}\times\frac{\mathrmw0obha2h00g(x)}{\mathrmw0obha2h00x}\)
最主要的就是這個鏈式法則在矩陣上面的應用。
1.4 求導計算圖
現在咱們同樣對一個最簡單的模型\(\hat{y}=x\times \omega\)進行講解。
前饋;輸入參數\(x,w\)我們將這兩個參數傳入到模型\(f(x)\)中,便可以得到第一個函數\(z= f(x,w)\),這個時候的\(z\)實際上就是所謂的虛擬計算值,將這個數值和真實值一起邊可求得損失函數\(loss()\),有了損失函數便可以使用梯度下降算法進行權重的求解啦。
反饋(反向傳播);反向和正向在說法上就剛好相反,首先我們得到了損失函數關于傳入參數\(z\)的導數\(\frac{\partial z}{\partial \omega}\)這時候我們擬用鏈式求導法則,通過\(\frac{\partial L}{\partial x}=\frac{\partial L}{\partial z}\cdot\frac{\partial z}{\partial x}\)求得\(z\)對\(x\)的導數;通過\(\frac{\partial L}{\partial\omega}=\frac{\partial L}{\partial z}\cdot\frac{\partial z}{\partial\omega}\)求得\(z\)對\(\omega\)的導數。

這就是一個最簡單的求導計算圖。黑色箭頭就是最簡單的從前面到后面的一個前饋,而紅色箭頭便是反向傳播。
舉一個例子吧。

上面就是一個正向的前饋處理。

這個是反向傳播,首先在進行前面的傳播過程我們可以得到\(l\)對\(z\)的導數是\(5\)然后反向及逆行。這個樣子就可以求出相應的\(w\)了。注意哈l對\(z\)的偏導是給出的。
現在給出一個具體的模型來處理嘗試

先進行前向處理,后進行反向傳播之后便可以得到解答。
2 代碼使用
2.1 分塊編寫
咱們使用的是pytorch進行編寫哈。其中的所有的數據均是在一個叫做Tensor的東西。然后我們又開了兩個玩意兒一個是他的數據\(data\)也即是權重,另一個是\(grad\)也就是所謂的梯度也即是損失函數對權重的導數。這兩個就是最重要的兩個參數。

因此對于一個普通的最簡單的線性模型\(\hat{y}=x\times \omega\)而言他的計算圖繪制如下所示。

在進行代碼編寫的時候最重要的就是整出這樣子的計算圖。
現在讓我們正式開始代碼的編寫。
首先引入庫,同時定義訓練數據,并初始化權重,同時開啟自動保存梯度的開關。
import torch # 引入庫
x_data = [1.0, 2.0, 3.0] #給定訓練數據
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0]) # 初始化權重
w.requires_grad = True # 開啟自動保存梯度的開關

注意:w.requires_grad = True這個表示的是需要進行梯度的計算,并開啟自動保存。
然后咱么開始各個函數的配置。
首先就是前饋相乘函數
forward()其次就是計算損失的損失函數
loss()
def forward(x): #前饋相乘函數
return x * w
def loss(x, y): # 計算損失的損失函數
y_pred = forward(x)
return (y_pred - y) ** 2


注意:\(x\)和\(w\)是一個數乘,但是\(x\)并不是一個\(tensor\)需要將\(x\)轉換成\(tensor\)即可。
現在就可以進行深度學習求解權重的處理了。
這里給一個以循環輪數為循環變量,同時循環的最大輪數為100輪;
其次讀取咱們的訓練數據;
開始進行計算圖的前饋模擬;
前饋完畢后進行反向傳播
backward()然后重新更新這個權重,
更新好之后將權重里面的梯度數據進行一個清理操作即可。
print("predict (before training)", 4, forward(4).item())
for epoch in range(100): #以循環輪數為循環變量,同時循環的最大輪數為100輪
for x, y in zip(x_data, y_data): #讀取咱們的訓練數據
l = loss(x, y) #計算圖的前饋模擬
l.backward() #進行反向傳播
print('\tgrad:', x, y, w.grad.item())
w.data = w.data - 0.01 * w.grad.data #重新更新這個權重
w.grad.data.zero_() #將權重里面的梯度數據進行一個清理
print("progress:", epoch, l.item())
print("predict (after training)", 4, forward(4).item())


注意:backward())這個函數用來反向傳播并且計算路上的每一個梯度,同時將這個求出來的梯度存儲在w里面。
但是一旦進行backward之后loss便被釋放了,這個計算圖就沒了。

注意:獲取梯度的數據方法,注意這個grad也是一個tensor,一定要用data進行計算,要不然的話會整出一個新的計算圖了。
item是將梯度的數值直接拿出來變成一個標量。防止產生計算圖。
權重的更新一定要使用data而非直接用張量計算。防止出現計算圖。

注意:將權重里面的梯度數據全部進行一個清零操作。否則在下一輪的時候上一輪的梯度數據會進行一個重合操縱,這樣就出問題了。
這就是使用pytorch來進行反向傳播的操作。
2.2 代碼綜合
- 簡單的線性模型的使用
import torch
import numpy as np # 引入庫函數
import matplotlib.pyplot as plt
import time
x_data=[1.0 ,2.0 , 3.0 , 4.0 , 5.0]
y_data=[2.0 , 4.0 , 6.0 ,8.0 , 10.0]
w = torch.tensor([1.0])
w.requires_grad = True
def forward(x):
return x*w
def loss(x,y):
y_hat= forward(x)
return (y_hat-y)**2
MSE_list = []
epoch_list = []
plt.ion()
fig,ax = plt.subplots(figsize = (10,6)) # 創建圖表對象和坐標軸對象
plt.pause(10)
for epoch in range(0 , 16 , 1): # 輪數為15輪
for x,y in zip(x_data , y_data):
l =loss(x ,y)
l.backward() # 反向傳播
w.data = w.data - 0.01 * w.grad.data
w.grad.data.zero_()
print("progress:", epoch, l.item())
MSE_list.append(l.item())
epoch_list.append(epoch)
# 更新圖表
ax.clear()
ax.plot(epoch_list , MSE_list , 'b-o' , linewidth = 2 , markersize = 4)
ax.set_xlabel('epoch' ,fontsize = 12)
ax.set_ylabel('MSE loss' , fontsize = 12)
ax.set_title(f'Training progress (Epoch{epoch})' , fontsize = 14)
ax.grid(True , alpha = 0.3)
ax.text(
0.02 , 0.95, # x坐標和y坐標
f'Current W:{w.item():.4f}',#顯示當前的權重值,并保留四位小數
transform = ax.transAxes, #使用坐標軸相對坐標
fontsize = 10, #字體大小
bbox = dict(
boxstyle="round,pad=0.3", #圓角矩形框,內邊距
facecolor = "yellow", #背景顏色
alpha = 0.7 #透明度
)
)
plt.pause(0.5) #每一輪后暫停0.5秒
plt.ioff()
plt.show()
print("predict (after training)", 4, forward(4).item())
# 最終繪制完整的損失曲線
plt.figure(figsize=(10, 6))
plt.plot(epoch_list, MSE_list, 'b-o', linewidth=2, markersize=6)
plt.xlabel('Epoch', fontsize=12)
plt.ylabel('MSE Loss', fontsize=12)
plt.title('Final Training Loss Curve', fontsize=14)
plt.grid(True, alpha=0.3)
plt.show()


3 課后作業
3.1 換一組變量進行推導并繪制其計算圖
? 
現在給出這個題目的解答。
1. 正向傳播(前饋)
\(\begin{aligned}&\text{正向傳播(前饋).}\\&①\text{輸入 }x=2;\quad w=1(\text{初步估計值}).\\&②\hat{y}:x\cdot w=2\times1=2.\\&②r=\hat{y}-y=2-4=-2\\&④loss=r^2=4.\end{aligned}\)
2. 反向傳播
\(\begin{aligned}&\text{反向傳播}\\&①\text{ 已知 }loss=r^2,\quad\Rightarrow\quad\frac{\partial loss}{\partial r}=\frac{\partial r^2}{\partial r}=2r=-4\\&②\text{ 求 }\frac{\partial loss}{\partial\hat{y}}=\frac{\partial loss}{\partial r}\times\frac{\partial r}{\partial\hat{y}}=2r\times\frac{\partial(\hat{y}-y)}{\partial\hat{y}}=2r=-4\\&②\text{ 求 }\frac{\partial loss}{\partial w}=\frac{\partial loss}{\partial\hat{y}}\times\frac{\partial\hat{y}}{\partial w}=2r\times\frac{\partial(x\cdot w)}{\partial w}=2rx=-8\end{aligned}\)
3. 計算圖的繪制

3.2 增加模型復雜度繼續進行pytorch求解
? 
現在給出這個題目的解答
- 正向傳播
- 反向傳播
\(\begin{aligned}&\text{反向傳播}\\&①\frac{\partial loss}{\partial r}=\frac{\partial r^2}{\partial r}=2r|r=1=2.\\&②\frac{\partial loss}{\partial y}=\frac{\partial loss}{\partial r}\cdot\frac{\partial r}{\partial y}=2r\times\frac{\partial(\hat{y}-y)}{\partial\hat{y}}=2r=2\\&③\frac{\partial loss}{\partial z}=\frac{\partial loss}{\partial y}\times\frac{\partial g}{\partial z}=2r\times\frac{\partial(z+b)}{\partial z}=2r=2\\&④\frac{\partial loss}{\partial w}=\frac{\partial loss}{\partial z}\times\frac{\partial z}{\partial w}=2r\times\frac{\partial(x\cdot w)}{\partial w}=2rx=2\end{aligned}\)
- 計算圖繪制

3.3 嘗試使用二次函數模型進行反向傳播的求解

現在給出這個題目的解答
- 正向傳播
① 輸入: \(w_1=2\), \(x=2\) \(\Rightarrow\) \(z_1=w_1 \times x^2=2 \times 4=8\).
② 輸入: \(w_2=2\), \(x=2\) \(\Rightarrow\) \(z_2=w_2 \times x=2 \times 2=4\).
③ 輸入: \(z_1\), \(z_2\), \(\Rightarrow\) \(z=z_1+z_2=8+4=12\).
④ 輸入: \(z\), \(b\). \(\Rightarrow\) \(\hat{y}=z+b=13\)
⑤ 輸入: \(y\) \(\Rightarrow\) \(r=\hat{y}-y=13-9=4\)
⑥ 輸入: \(r\) \(\Rightarrow\) \(loss=r^2=16\).
- 反向傳播
① \(\frac{\partial loss}{\partial r} = \frac{\partial (r^2)}{\partial r} = 2r |_{r=4} = 2 \times 4 = 8\)
② \(\frac{\partial loss}{\partial z} = \frac{\partial loss}{\partial r} \times \frac{\partial r}{\partial z} = 2r \times \frac{\partial (z+b)}{\partial z} = 2r = 8\)
③ \(\frac{\partial loss}{\partial z_1} = \frac{\partial loss}{\partial z} \times \frac{\partial z}{\partial z_1} = 2r \times \frac{\partial (z_1 + z_2)}{\partial z_1} = 2r = 8\)
④ \(\frac{\partial loss}{\partial z_2} = \frac{\partial loss}{\partial z} \times \frac{\partial z}{\partial z_2} = 2r \times \frac{\partial (z_1 + z_2)}{\partial z_2} = 2r = 8\)
⑤ \(\frac{\partial loss}{\partial w_1} = \frac{\partial loss}{\partial z_1} \times \frac{\partial z_1}{\partial w_1} = 2r \times \frac{\partial (w_1 \cdot x^2)}{\partial w_1} = 2r \times 4 = 32\)
⑥ \(\frac{\partial loss}{\partial w_2} = \frac{\partial loss}{\partial z_2} \times \frac{\partial z_2}{\partial w_2} = 2r \times \frac{\partial (w_2 \cdot x)}{\partial w_2} = 2r \times 2 = 16\)
- 計算圖的繪制


浙公網安備 33010602011771號