PyTorch 2 Autograd 自動微分

2021-10-03 18:07:45 字數 3410 閱讀 5754

原文出自

在pytorch的所有神經網路中,核心是 autograd 包。讓我們先簡單介紹一下, 然後我們將開始訓練我們的第乙個神經網路。

autograd package 為張量上的所有操作提供自動微分(automatic differentiation)。 它是乙個按執行定義的框架(define-by-run framework), 這意味著您的後端(backprop)由您的**執行方式來定義,並且每個迭代都可能是不同的。

讓我們用更簡單的術語來看這一點,並舉幾個例子。

張量(tensor)

torch.tensor 是此package的核心類。 如果你將它的屬性 .requires_grad 設定為 true, 它就開始跟蹤在它上面的所有運算操作。當你完成計算時你可以呼叫 .backward() , 這會使得所有的梯度都被自動計算出來。對於這個tensor的梯度將會被累加到 .grad 屬性中去。

如果想要阻止乙個tensor不去跟蹤歷史(tracking history), 你可以呼叫 .detach() 方法 把它從計算歷史中分離出來, 並且會阻止進一步的計算被跟蹤。

若要防止跟蹤歷史記錄(並使用記憶體),還可以把**塊封裝在with語句 with torch.no_grad(): 中。 這在評估模型時特別有用,因為模型可能具有可訓練的引數(requires_grad=true)。但是在評估模型的 時候不需要計算梯度,而且我們不想把模型的這些可訓練引數設定為 requires_grad=false ,那麼封裝在 with語句 with torch.no_grad(): 中是很贊的。

還有乙個類對於實現自動微分至關重要,那就是— function 。

tensor 和 function 是內部相互聯絡的,並建立了乙個無環圖(acyclic graph),它編碼了乙個完整的計算歷史。 每個tensor都有乙個 .grad_fn 屬性,它引用了建立了 tensor 的 function 。 (除了由使用者建立的 tensors -它們的 grad_fn is none)。

如果要計算導數(derivatives),可以在 tensor 上呼叫 .backward() 。 如果 tensor 是乙個標量(scalar) (i.e. 它裡面只持有乙個元素的資料), 那麼你不需要為 backward() 方法傳遞任何引數。然而,如果 tensor 有更多的元素,那麼 你需要指定乙個 gradient 引數,其必須是乙個shape相匹配的 tensor 。

import torch

建立乙個 tensor 並設定 requires_grad=true 來跟蹤這個tensor上的計算

x = torch.ones(2, 2, requires_grad=true)

print(x)

對 tensor 做運算:

y = x + 2

print(y)

y 作為加法運算的結果被建立了出來, 因此它有乙個 grad_fn.

print(y.grad_fn)

在張量 y 上做更多運算操作

z = y * y * 3

out = z.mean()

print(z, out)

.requires_grad_( … ) 可以原位(in-place)修改乙個已經存在的 tensor 的 requires_grad 標誌位。 如果沒有給定, 輸入的標誌位預設是 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)

print(b.requires_grad)

梯度(gradient)

現在我們開始反向傳播啦 因為 out 包含乙個單個的標量, out.backward() 是等價於 out.backward(torch.tensor(1.)) 的。

out.backward()

輸出梯度 d(out)/dx

print(x.grad)

你應該得到了乙個 4.5 的2x2矩陣。 我們把 out 稱為 tensor 「o

」 。 我們有這樣乙個式子成立 o=14∑izi, zi=3(xi+2)2 和 zi∣∣xi=1=27. 因此, ∂o∂xi=32(xi+2), 因此 ∂o∂xi∣∣xi=1=92=4.5

的梯度 是乙個雅克比矩陣(jacobian matrix) :

j=⎛⎝⎜⎜⎜⎜∂y1∂x1⋮∂y1∂xn⋯⋱⋯∂ym∂x1⋮∂ym∂xn⎞⎠⎟⎟⎟⎟

廣義上說, torch.autograd 是乙個用來計算雅克比向量乘積(jacobian-vector product)的引擎。 這就是說, 給定任意的向量 v=(v1v2⋯vm)t

, 計算乘積 j⋅v 。 如果 v 恰好是乙個標量函式 l=g(y⃗ ) 的梯度, 即, v=(∂l∂y1⋯∂l∂ym)t, 那麼根據鏈式法則, 雅克比向量乘積 就是 l 相對於 x⃗

的梯度 :

j⋅v=⎛⎝⎜⎜⎜⎜∂y1∂x1⋮∂y1∂xn⋯⋱⋯∂ym∂x1⋮∂ym∂xn⎞⎠⎟⎟⎟⎟⎛⎝⎜⎜⎜⎜∂l∂y1⋮∂l∂ym⎞⎠⎟⎟⎟⎟=⎛⎝⎜⎜⎜∂l∂x1⋮∂l∂xn⎞⎠⎟⎟⎟

雅克比向量乘積的這個特點使得 將外部梯度輸入到乙個具有非標量輸出的模型中去 變得非常方便。

現在呢 我就來看看 雅克比向量乘積(jacobian-vector product) 的乙個例子:

x = torch.randn(3, requires_grad=true)

y = x * 2

while y.data.norm() < 1000:

y = y * 2

print(y)

現在 y 不再是乙個標量啦。 torch.autograd 不能直接計算出整個雅可比矩陣, 但如果我們只想要雅可比向量積(jacobian-vector product), 只需要簡單的傳遞乙個向量到函式 backward 的引數中去:

v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)

y.backward(v)

print(x.grad)

您還可以通過將**塊包裝在下面的 with torch.no_grad() **塊中, 從而停止使用autograd來跟蹤狀態為 .requires_grad=true 的 tensors 上的歷史記錄:

print(x.requires_grad)

print((x ** 2).requires_grad)

with torch.no_grad():

print((x ** 2).requires_grad)

後續閱讀:

autograd 和 function 的文件在

total running time of the script: ( 0 minutes 0.000 seconds)

Pytorch學習 2 快速模型

好久不寫題解了,今天寫了乙個線段樹果然一點手感都沒有了。不過是個很好的題目,兩種標記是互相影響的,注意到什麼標記的更新會使得另外的標記一併更新 題目和解法見注釋 uva 11402 四種操作 注意兩種標記會相互影響的時候的處理 include include include include incl...

pytorch入門2 常用函式

import numpy as np import torch 獲取張量資料型別 a torch.randn 2,3 返回 1到1之間的隨機數2行3列 print a b a.shape 返回a形狀 touch.size 2,3 print b c a.size 返回的值和shape是一樣的 d a...

利用pytorch進行深度學習(2)

一 資料集 面對問題的時候,我們已知的資料集可以被用來測試,訓練模型,然後再利用模型對未知的資料集來進行推理 其中在學習的時候我們知道輸出的結果,可以通過結果來對模型進行糾正,這種學習過程叫做監督學習。在監督學習的過程中我們可獲得的已知的資料集被分為測試集和訓練集,其中測試集的資料在訓練過程中不能使...