Autograd:自動(dòng)求導(dǎo)
PyTorch中所有神經(jīng)網(wǎng)絡(luò)的核心是autograd包筛谚。我們首先簡(jiǎn)要地看看捻脖,然后訓(xùn)練第一個(gè)神經(jīng)網(wǎng)絡(luò)锐峭。
Autograd包為T(mén)ensors所有操作提供了自動(dòng)求導(dǎo)。這是一個(gè)逐個(gè)運(yùn)行的框架可婶,這意味著用戶(hù)的BP反向傳遞是由代碼運(yùn)行方式定義沿癞,并且每個(gè)迭代都不同。
Tensor
幾個(gè)重要的類(lèi)和參數(shù)
torch.Tensor是Autograd的核心類(lèi)矛渴,如果設(shè)置參數(shù).requires_grad為T(mén)rue椎扬,將會(huì)開(kāi)始追蹤Tensor的所有操作惫搏。當(dāng)完成計(jì)算后,可以使用.backward()并自動(dòng)獲取所有梯度計(jì)算蚕涤。Tensor的梯度將被匯集到.grad參數(shù)中筐赔。
如果想阻止Tensor追蹤歷史記錄。
- 可以調(diào)用.detach()揖铜,將其從歷史記錄中分離出來(lái)茴丰,并且能夠防止將來(lái)的計(jì)算被追蹤。
- 可以調(diào)用torch.no_grad()來(lái)包裹代碼天吓,在評(píng)估模型時(shí)會(huì)有用贿肩,因?yàn)槟P涂赡芫哂衦equires_grad = True的可訓(xùn)練參數(shù),但我們不需要漸變龄寞。
還有一個(gè)重要的類(lèi)汰规,F(xiàn)unction。
可以通過(guò)屬性** .data 來(lái)訪問(wèn)原始的tensor萄焦,而關(guān)于這一Variable的梯度則集中于 .grad **屬性中控轿。
Tensor和Function相互連接并構(gòu)建一個(gè)無(wú)環(huán)圖,這個(gè)圖能夠編碼一個(gè)完整的計(jì)算歷史拂封。每一個(gè)Tensor都有一個(gè).grad_fn參數(shù)茬射,這個(gè)參數(shù)可以引用已創(chuàng)建的Tensor中的Function(除非用戶(hù)創(chuàng)建的 Tensor中參數(shù).grad_fn為None)。
如果如果要計(jì)算導(dǎo)數(shù)冒签,可以在Tensor上調(diào)用.backward()在抛。如果Tensor是標(biāo)量,(即它包含一個(gè)元素?cái)?shù)據(jù))萧恕,則不需要為backward()指定任何參數(shù)刚梭,但是如果它有更多元素,則需要指定一個(gè)漸變參數(shù)票唆,該參數(shù)是匹配形狀的張量朴读。
下面來(lái)試試grad_fn
#創(chuàng)建一個(gè)tensor,設(shè)定requires_grad=True來(lái)追蹤計(jì)算
x=torch.ones(2,2,requires_grad=True)
print(x)
#進(jìn)行tensor操作
y=x+2
print(y)
#查看y的grad_fn
print(y.grad_fn)
#完成更多的操作
z=y*y*3
out=z.mean()
print(z, z.grad_fn,out)
.requires_grad_(...) 能夠更改現(xiàn)有的Tensor的requires_grad標(biāo)志走趋。如果沒(méi)有給出衅金,輸入標(biāo)志默認(rèn)為False。
a = torch.randn(2, 2)
a = ((a * 3) / (a - 1))
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
梯度
開(kāi)始BP反向傳遞簿煌,因?yàn)閛ut包括了一個(gè)單獨(dú)scalar氮唯,out.backward()和out.backward(torch.tensor(1.))相同。
out.forward()
print(x.grad)
你應(yīng)該有一個(gè)含有4.5的矩陣姨伟。我們稱(chēng)之為“Tensor”惩琉。
在數(shù)學(xué)上,如果你有一個(gè)向量值函數(shù)夺荒,那么相對(duì)于的漸變是一個(gè)Jacobian matrix:一般來(lái)說(shuō)瞒渠,torch.autograd是一個(gè)Jacobian matrix的引擎良蒸。也就是說(shuō),給定任何向量伍玖,計(jì)算結(jié)果诚啃。如果恰好是標(biāo)量函數(shù)的梯度,也就是說(shuō)私沮,那么通過(guò)鏈規(guī)則始赎,Jacobian matrix乘積將是相對(duì)于的梯度:(注意,給出一個(gè)可以被視為列向量的行向量通過(guò)服用仔燕。)
上面這段在原教程中有點(diǎn)問(wèn)題造垛,總之就是pytorch包含有一個(gè)自動(dòng)求導(dǎo)的核心功能,在Jacobian matrix同樣適用晰搀。
現(xiàn)在讓我們看一下Jacobian matrix的例子
x=torch.randn(3,requires_grad=True)
y=x*2
while y.data.norm()<1000:
y=y*2
print(y)
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)