Pytorch(5)-梯度反向传播
自動(dòng)求梯度
- 1. 函數(shù)對(duì)自變量x求梯度--ax^2+b
- 2. 網(wǎng)絡(luò)對(duì)參數(shù)w求梯度- loss(w,x)
- 3. 自動(dòng)求梯度的底層支持--torch.autograd
- 3.1 Variable
- 3.1.1 Variable構(gòu)造函數(shù)
- 3.1.2 Variable鏈?zhǔn)角髮?dǎo)--backward()
- 3.1.3 Variable反向傳播函數(shù)--grad_fn
- 3.2 計(jì)算圖
- 3.2.1 動(dòng)態(tài)創(chuàng)建計(jì)算圖
- 3.2.2 非葉子節(jié)點(diǎn)的梯度--autograd.grad 與 hook
- 3.3 復(fù)雜自建函數(shù),自動(dòng)求導(dǎo)支持
1. 函數(shù)對(duì)自變量x求梯度–ax^2+b
torch提供了簡(jiǎn)便的求梯度方法:帶入變量值x,求解目標(biāo)函數(shù)f(x),將目標(biāo)函數(shù)的值反向傳播f.backward(),就能計(jì)算對(duì)應(yīng)變量的導(dǎo)數(shù)。
輸出
初始化 None 一次傳播 tensor([2.]) 梯度置零 tensor([0.]) 二次傳播 tensor([4.])2. 網(wǎng)絡(luò)對(duì)參數(shù)w求梯度- loss(w,x)
神經(jīng)網(wǎng)絡(luò)訓(xùn)練:通過(guò)調(diào)整神經(jīng)網(wǎng)絡(luò)參數(shù)使網(wǎng)絡(luò)輸出盡可能接近于想要的對(duì)象。具體通過(guò)損失函數(shù)的梯度下降實(shí)現(xiàn)的,即損失函數(shù)對(duì)網(wǎng)絡(luò)參數(shù)求梯度,利用該梯度調(diào)整網(wǎng)絡(luò)參數(shù)。
模型的損失函數(shù)實(shí)際是輸入x 和模型參數(shù)w 的函數(shù):loss(w,x)。依據(jù)part1demo流程,隨機(jī)初始化w后,輸入觀測(cè)數(shù)據(jù)x(圖像 或者 其他需要分類(lèi)或者回歸的數(shù)據(jù))。loss(w, x).backward()就可以求出對(duì)應(yīng)的網(wǎng)絡(luò)參數(shù)w的梯度。再利用各種優(yōu)化算法(SGD,admn)更新各個(gè)網(wǎng)絡(luò)參數(shù)w即可。
pytorch 網(wǎng)絡(luò)訓(xùn)練的流程
注意事項(xiàng):在每次損失函數(shù)反向傳播計(jì)算梯度時(shí),原本的參數(shù)梯度必須設(shè)置為0。否則,各個(gè)參數(shù)的梯度會(huì)累加之前的梯度。網(wǎng)絡(luò)參數(shù)梯度置0:
optimizer=torch.optim.SGD(net.parameters(),lr=0.001,momentum=0.1)
optimizer.zero_grad()
loss.backward()
3. 自動(dòng)求梯度的底層支持–torch.autograd
torch.autograd 是一套自動(dòng)求導(dǎo)引擎,能夠根據(jù)輸入和前向傳播過(guò)程自動(dòng)構(gòu)建計(jì)算圖,并執(zhí)行反向傳播. 計(jì)算圖是深度學(xué)習(xí)框架的核心。
[本節(jié)為陳云<<深度學(xué)習(xí)框架-pytorch 入門(mén)與實(shí)踐>>一書(shū)第3.2章的內(nèi)容autograd 讀書(shū)筆記.]
pytorch 中 autograd模塊 實(shí)現(xiàn)了 計(jì)算圖 相關(guān)功能. autograd 的核心數(shù)據(jù)結(jié)構(gòu)Variable。
pytorch 中 autograd模塊 底層采用 計(jì)算圖 實(shí)現(xiàn)梯度計(jì)算。
3.1 Variable
Variable中封裝了以下三個(gè)部分內(nèi)容
3.1.1 Variable構(gòu)造函數(shù)
Variable的構(gòu)造函數(shù)–需要傳入tensor,還有兩個(gè)可選參數(shù):
volatile優(yōu)先級(jí)別比requires_grad高。在計(jì)算路徑上同時(shí)存在requires_grad=True 和 volatile=True 的變量,那么其后的通過(guò)計(jì)算得出的變量的requires_grad 為False.
3.1.2 Variable鏈?zhǔn)角髮?dǎo)–backward()
Variable支持大部分的tensor操作,但不支持部分inplace函數(shù)。如果想要計(jì)算各個(gè)Variable的梯度,只需要調(diào)用根節(jié)點(diǎn)variable的backward方法,autograd 會(huì)自動(dòng)沿計(jì)算圖反向傳播,計(jì)算每一個(gè)葉子節(jié)點(diǎn)的梯度.
Variable.backward(grad_variables=None,retain_graph=None,create_graph=None)
grad_variables : 相當(dāng)與鏈?zhǔn)椒▌t?z?x=?z?y?y?x\frac{\partial z}{\partial x}=\frac{\partial z}{\partial y}\frac{\partial y}{\partial x}?x?z?=?y?z??x?y?中的?z?y\frac{\partial z}{\partial y}?y?z? 。y.backward(grad_y) 等價(jià)于 z.backward()
retain_graph : 反向傳播中會(huì)緩存一些中間結(jié)果,反向傳播結(jié)束后緩存被清空。可以通過(guò)指定這個(gè)參數(shù)不清空緩存,用于多次反向傳播。
create_graph : 反向傳播過(guò)程中再次構(gòu)建計(jì)算圖,通過(guò)backward of backward實(shí)現(xiàn)高階求導(dǎo).
3.1.3 Variable反向傳播函數(shù)–grad_fn
variable變量的grad_fn 屬性可以用來(lái)查看反向傳播函數(shù), next_functions保存grad_fn的輸入,是一個(gè)tuple。每個(gè)變量在圖中的位置可以通過(guò)grad_fn 屬性在圖中的位置推測(cè)得到。每一個(gè)前向傳播函數(shù)都有一個(gè)與之對(duì)應(yīng)的反向傳播函數(shù),用來(lái)計(jì)算各個(gè)輸入變量的梯度;這些函數(shù)以Backward結(jié)尾。
x=Variable(torch.ones(1)) b=Variable(torch.rand(1,requires_grad=True)) w=Variable(torch.rand(1),requires_grad=True) y=w*x z=y+b z.grad_fn # 查看z的反向傳播函數(shù) Out[16]: <AddBackward0 at 0x7f84b0a0e3c8>z.grad_fn.next_functions # z 反向傳播函數(shù)的輸入,一個(gè)為y.grad_fn(為MulBackward0),另一個(gè)是b.grad_fn(為none) Out[17]: ((<MulBackward0 at 0x7f84903a9588>, 0), (None, 0))y.grad_fn Out[27]: <MulBackward0 at 0x7f84903a9588> y.grad_fn.next_functions Out[19]: ((<AccumulateGrad at 0x7f84b0a0ee10>, 0), (None, 0))z.backward(retain_graph=True) # 保留中間結(jié)果 w.grad Out[23]: tensor([1.])z.backward(retain_graph=True) # 保留中間結(jié)果, 才能二次傳播 w.grad Out[26]:tensor([2.]) # 這個(gè)為2 不是保留中間結(jié)果的原因,而是兩次梯度傳播3.2 計(jì)算圖
pytorch 中 autograd模塊 底層采用 計(jì)算圖 實(shí)現(xiàn)梯度計(jì)算。計(jì)算圖是一種特殊的有向無(wú)環(huán)圖 , 用于記錄算子 與 變量 之間的關(guān)系。
在pytorch 中autograd模塊會(huì)隨著用戶(hù)操作,記錄生成當(dāng)前 variable 的所有操作。以此建立一個(gè)有向無(wú)環(huán)圖(每個(gè)變量都有一個(gè)有向無(wú)環(huán)圖?還以一個(gè)計(jì)算過(guò)程有一個(gè)?應(yīng)該是一個(gè)計(jì)算過(guò)程有一個(gè)圖)。用戶(hù)每進(jìn)行一次操作,計(jì)算圖就會(huì)變化。對(duì)應(yīng)的變化會(huì)通3.1.3 的grad_fn 記錄
3.2.1 動(dòng)態(tài)創(chuàng)建計(jì)算圖
pytorch 的計(jì)算圖在每次前向傳播的時(shí)候都是從頭開(kāi)始構(gòu)建的 , 所以能夠利用python的控制語(yǔ)句(for,if) 根據(jù)需求 創(chuàng)建動(dòng)態(tài)圖.
少一個(gè)例子
3.2.2 非葉子節(jié)點(diǎn)的梯度–autograd.grad 與 hook
在反向傳播的過(guò)程中,非葉子節(jié)點(diǎn)的導(dǎo)數(shù)在計(jì)算完成之后即被清空,若想查看這些變量的梯度,有兩種方法:autograd.grad 與 hook。
torch.autograd.grad()
In [28]: x=Variable(torch.ones(3),requires_grad=True) In [30]: w=Variable(torch.ones(3),requires_grad=True) In [31]: y=x*w In [32]: z=y.sum() In [33]: z.backward() In [34]: (x.grad,w.grad,y.grad) Out[34]: (tensor([1., 1., 1.]), tensor([1., 1., 1.]), None) # y.grad的梯度計(jì)算完被釋放掉了 # 使用torch.autograd.grad()計(jì)算中間節(jié)點(diǎn)的梯度 In [35]: torch.autograd.grad(z,y) # 求Z對(duì)Y的梯度 Out[35]: (tensor([1., 1., 1.]),)hook 呢?🤔?
3.3 復(fù)雜自建函數(shù),自動(dòng)求導(dǎo)支持
自己寫(xiě)一個(gè)復(fù)雜函數(shù),不支持自動(dòng)求導(dǎo)。這種情況下,定義此復(fù)雜函數(shù)為Function(), 繼承自,Torch.autograd.Function。實(shí)現(xiàn)前向與反向傳播 的代碼。使用Function.apply(variable)調(diào)用實(shí)現(xiàn)Function。
詳見(jiàn):p95
總結(jié)
以上是生活随笔為你收集整理的Pytorch(5)-梯度反向传播的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《Python Cookbook 3rd
- 下一篇: 《C++ Primer 5th》笔记(5