網(wǎng)站建設(shè)基礎(chǔ)教程如何做線上推廣
目錄
1 問題背景
1.1計(jì)算圖(Computational Graph)
1.2 激活函數(shù)(Activation Function)引入
1.3 問題引入
2?反向傳播(Back Propagation)
2.1 為什么要使用反向傳播
2.2 前饋運(yùn)算(Forward Propagation)過程
2.3 反向傳播過程
2.3.1 計(jì)算過程?
2.3.2 課堂練習(xí)
3 在Pytorch中進(jìn)行前饋和反向傳播計(jì)算
3.1 Tensor數(shù)據(jù)類型
3.2 代碼實(shí)現(xiàn)
3.2.1 實(shí)現(xiàn)線性模型
1 問題背景
1.1計(jì)算圖(Computational Graph)
計(jì)算圖(Computational Graph)是一種用于表示數(shù)學(xué)運(yùn)算的圖形模型。在計(jì)算圖中,每個(gè)節(jié)點(diǎn)代表一個(gè)數(shù)學(xué)運(yùn)算,而每條邊代表運(yùn)算之間的輸入輸出關(guān)系。
計(jì)算圖用于記錄和組織復(fù)雜的數(shù)學(xué)運(yùn)算,可以幫助我們快速理解運(yùn)算的依賴關(guān)系和結(jié)構(gòu)。在機(jī)器學(xué)習(xí)和深度學(xué)習(xí)中,計(jì)算圖是一種常用的工具,用于定義和計(jì)算模型的損失函數(shù)和梯度。
計(jì)算圖還可以用于求導(dǎo),通過利用計(jì)算圖上的梯度進(jìn)行反向傳播,可以快速計(jì)算模型的損失函數(shù)對于每個(gè)參數(shù)的導(dǎo)數(shù)。因此,計(jì)算圖不僅提高了計(jì)算效率,而且可以方便地實(shí)現(xiàn)自動微分和反向傳播。
比如下式

?用計(jì)算圖表示

?注:MM表示相乘
1.2 激活函數(shù)(Activation Function)引入
對于剛剛舉例的神經(jīng)網(wǎng)絡(luò)計(jì)算圖,計(jì)算機(jī)會直接對其進(jìn)行簡化:

?
?這就導(dǎo)致了計(jì)算過程中添加的新的權(quán)重值變得毫無意義,層數(shù)的劃分變得多余,導(dǎo)致神經(jīng)網(wǎng)絡(luò)的表示能力下降。
? 為了解決這個(gè)問題,我們需要在每一層的輸出處應(yīng)用上一個(gè)非線性變換函數(shù)(Nonlinear
Function),這樣模型就不會被簡化了

? 如果一個(gè)神經(jīng)網(wǎng)絡(luò)只使用線性變換函數(shù),那么其最終的表示能力仍然有限,因?yàn)樗鼈兊妮敵鼋Y(jié)果是線性的,無法對復(fù)雜的數(shù)據(jù)進(jìn)行分類或回歸。因此,在每一層的輸出都應(yīng)用非線性變換函數(shù),以增強(qiáng)神經(jīng)網(wǎng)絡(luò)的表示能力。
??非線性變換函數(shù)通常也稱為激活函數(shù)(Activation Function)。常見的激活函數(shù)有Sigmoid函數(shù)、ReLU函數(shù)等。
補(bǔ)充
線性函數(shù)與非線性函數(shù)的簡單區(qū)別:線性函數(shù)其函數(shù)圖像是一條直線;非線性函數(shù)的函數(shù)圖像是一條曲線,等等。
1.3 問題引入
對于一個(gè)簡單線性模型 ,我們可以利用解析式來進(jìn)行簡單的計(jì)算。

?通過計(jì)算圖,我們可以直觀地看出計(jì)算的過程:

然后利用解析式來更新權(quán)重:

?但是對于復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型來說,可能同時(shí)含有多個(gè)𝜔,如果為每個(gè)𝜔寫解析式來計(jì)算,任務(wù)會非常繁重,且解析式也會變得很復(fù)雜:

? 復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型往往具有大量的權(quán)重,如果使用手動計(jì)算權(quán)重導(dǎo)數(shù)的方法,這將是一項(xiàng)非常復(fù)雜且繁瑣的任務(wù)。
2?反向傳播(Back Propagation)
2.1 為什么要使用反向傳播
? 如果使用手動計(jì)算權(quán)重導(dǎo)數(shù)的方法來計(jì)算復(fù)雜神經(jīng)網(wǎng)絡(luò)模型,將會非常困難。而反向傳播(Back Propagation)可以使用鏈?zhǔn)椒▌t自動計(jì)算損失函數(shù)對于每個(gè)權(quán)重的導(dǎo)數(shù),大大減少計(jì)算復(fù)雜度,使訓(xùn)練神經(jīng)網(wǎng)絡(luò)變得更加有效。
? 除此之外,反向傳播還有一個(gè)優(yōu)點(diǎn):實(shí)現(xiàn)最優(yōu)化,省去了重復(fù)求導(dǎo)的步驟,以及更高效地去計(jì)算偏導(dǎo)。詳情請參考相關(guān)鏈接,這里不展開:
http://t.csdn.cn/igONJ
https://zhuanlan.zhihu.com/p/25081671
2.2 前饋運(yùn)算(Forward Propagation)過程

簡單來說,就是 x和𝜔進(jìn)行f(x, 𝜔)操作后得出z,然后把z值應(yīng)用到Loss中去。
比如𝑓 = 𝑥 ? 𝜔, 𝑥 = 2, 𝜔 = 3

2.3 反向傳播過程
2.3.1 計(jì)算過程?

?
其中以下兩個(gè)局部函數(shù)是由z=𝑥 ? 𝜔,分別對x和對𝜔求導(dǎo)得到的:

簡單來說,就是沿著正方向相反的方向,為每個(gè)節(jié)點(diǎn)乘上局部導(dǎo)數(shù)后,再傳遞給下一個(gè)節(jié)點(diǎn)。

2.3.2 課堂練習(xí)
?(1)計(jì)算梯度

答案:-8
(2)計(jì)算加上偏差值后的梯度(計(jì)算仿射模型的梯度)?

?
答案:2,2
3 在Pytorch中進(jìn)行前饋和反向傳播計(jì)算
3.1 Tensor數(shù)據(jù)類型

3.2 代碼實(shí)現(xiàn)
3.2.1 實(shí)現(xiàn)線性模型
課堂上的案例,補(bǔ)充了些解釋:?
import torchx_data = [2.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0]) # 創(chuàng)建了一個(gè)一維張量,包含單一數(shù)值1.0,作為權(quán)重初始值
w.requires_grad = True # w=torch.Tensor([1.0])創(chuàng)建了一個(gè)張量,然后使用 w.requires_grad = True設(shè)置該張量需要求導(dǎo),于是PyTorch 會記錄對該張量的操作,以便在反向傳播時(shí)進(jìn)行梯度更新def forward(x):return x * w # 注意這里的x已經(jīng)自動轉(zhuǎn)換為Tensor類型,原本是list類型def loss(x, y):y_pred = forward(x)return (y_pred - y) ** 2print("predict (before training)", 4, forward(4).item())
for epoch in range(100):for x, y in zip(x_data, y_data):l = loss(x, y)# 反向傳播,這句還可以清空釋放計(jì)算圖,避免計(jì)算圖堆砌在內(nèi)存中。# 若在當(dāng)前backward()后,不執(zhí)行forward() 而是執(zhí)行另一個(gè)backward(),# 則需要在當(dāng)前backward()時(shí),指定保留計(jì)算圖,backward(retain_graph)# 換言之,想要保留計(jì)算圖,則寫成backward(retain_graph)l.backward()# 使用item將一個(gè)張量轉(zhuǎn)換成一個(gè) Python標(biāo)量,也是為了防止產(chǎn)生計(jì)算圖# 一般在進(jìn)行數(shù)學(xué)運(yùn)算時(shí)使用grad.data,而在輸出梯度數(shù)值時(shí)使用grad.item()# 一般梯度只有一個(gè)元素,所以使用.item()# 可以方便地把梯度值轉(zhuǎn)換為一個(gè)數(shù)字。print('\tgrad:', x, y, w.grad.item())# 這句代碼用來更新權(quán)重# 這里使用w.grad.data而不是w.grad是為了防止建立計(jì)算圖,我們只是對數(shù)值做修改,而不是對模型做出修改# 雖然w.data 也是 tensor 類型的數(shù)據(jù),# 但它是不需要 gradient 的,因此不會建立計(jì)算圖,只是在數(shù)值范圍上發(fā)生變化w.data = w.data - 0.01 * w.grad.dataw.grad.data.zero_() # 每次反向傳播前,需要清空梯度緩存,以避免之前的梯度對當(dāng)前梯度造成影響。print("progress:", epoch, l.item()) # 輪數(shù),每輪訓(xùn)練完后對應(yīng)的loss值,l是tensor類型,所以用item取出值來
print("predict (after training)", 4, forward(4).item())
簡單來說,每一輪,數(shù)據(jù)都會先前饋運(yùn)算出loss,再反向運(yùn)算出新的梯度,然后用梯度來更新權(quán)重值。?