專欄推薦
正文
深度學習框架pytorch擁有自動求導的機制,自動求導是 PyTorch 中非常重要的特性,能夠讓我們避免手動去計算非常複雜的導數,這能夠極大地減少了我們構建模型的時間。
導入的包
import torch
from torch.autograd import Variable
對標量進行自動求導
x = Variable(torch.Tensor([2]), requires_grad=True)
y = x + 2
z = y ** 2 + 3
print(z)
z.backward()
print(x.grad)
我們可以看到變量x在申明的時候,指定了requires_grad=True,這樣和x進行運算的所有變量都相當於設置了requires_grad=True,比如y、z都相當於設置了requires_grad=True。這樣我們就可以使用反向傳播了,本例中z.backward()就是表示的執行反向傳播,最後x.grad表示的是z對x的偏導數。
對矩陣求梯度
x = Variable(torch.randn(10, 20), requires_grad=True)
y = Variable(torch.randn(10, 5), requires_grad=True)
w = Variable(torch.randn(20, 5), requires_grad=True)
out = torch.mean(y - torch.matmul(x, w))
out.backward()
print(x.grad)
print(w.grad)
本例中我們申明瞭三個矩陣,分別是x、y、w,然後我們對其進行計算操作。torch.matmul 是做矩陣乘法,torch.mean是做均值化。然後執行反向傳播就可以獲取到矩陣x的梯度了。
在pytorch0.4之後Variable 正式合併入Tensor, Variable 本來實現的自動微分功能,Tensor就能支持,所以我們可以直接在創建tensor的時候,使用autograd功能,只需要設置tensor.requries_grad=True.
x = t.ones(2, 2, requires_grad=True)
這樣這個x就可以自動求導了
y = w * x + b
x=torch.ones(1)
b=torch.rand(1,requires_grad=True)
w=torch.rand(2,requires_grad=True)
z=w*x
y=z+b
y.backward()#自動求導,它會對所有需要求梯度的變量進行求導,然後得到他們的梯度。y.backward()等價於y.backward(torch.FloatTensor([1])),因為我們上面求得梯度都是標量(維度是1,所以torch.FloatTensor([1])),backward中的參數就沒有必要來寫了。
求完梯度之後,我們就可以使用屬性grad來求出每個變量的梯度
print (x.grad) #求變量x的梯度,梯度為w,也就是2
print(w.grad)#求變量w的梯度,梯度為x,也就是1
print (b. grad)#求變量b的梯度,梯度為常數1
我們前面是對我們的標量進行求導,我們也可以來對我們的矩陣進行求導
x = torch.randn(3) #創建一個隨機矩陣,類型是tensor,x的結果為tensor([-0.2895, 0.7542, -1.3040])
x=Variable(x, requires_grad=True) #我們將tensor轉成變量
y= x * 2 #構建計算圖print (y)
y.backward(torch.FloatTensor( [1, 1,1])) #對變量進行求梯度,因為我們的矩陣是三維的,所以我們需要torch.FloatTensor( [1, 1,1])
print (x. grad) #輸出變量x的梯度,結果為:tensor([2., 2., 2.]),因為我們的tensor為三行一列的向量,所以我們的梯度需要[1,1,1]表示對這個向量中的每一個進行求梯度。
我們也可以y.backward(torch.FloatTensor( [1, 0.1 , 0. 01] )) ,這樣得到的梯度就是它們原本的梯度分別乘上 1 , 0.1 和 0.01,結果為:
tensor([2.0000, 0.2000, 0.0200])
可運行代碼為:
import torch
from torch.autograd import Variable
x= torch.randn(3) #創建一個隨機矩陣,1行3列,類型是tensor
print(x)
x=Variable(x, requires_grad=True)
print(x)
y=x*2
y.backward(torch.FloatTensor([1,1,1]))
print(x.grad)
結果為:
對矩陣求梯度
import torch
from torch.autograd import Variable
x= torch.randn(2,3) #創建一個隨機矩陣,1行3列,類型是tensor
print(x)
x=Variable(x, requires_grad=True)
print(x)
y=x*2
y.backward(torch.FloatTensor([[1,0.1,0.01],[1,1,1]]))
print(x.grad)
如果我們要是將x= torch.randn(2,3),建立一個兩行三列的,那麼我們的這裡y.backward(torch.FloatTensor([[1,0.1,0.01],[1,1,1]]))也要兩行三列,這樣才能一一對應,結果為:
多次自動求導
#調用 backward就會自動反向求導,但是求導完之後計算圖就會被丟棄,以後就不能調用backward了,為了防止這種情況,我們可以在自動求導的時候,指定不丟棄計算圖retain_graph=True。
x=torch.randn(3)
x=Variable(x,requires_grad=True)
y=x*3
y.backward(torch.FloatTensor([1,1,1]),retain_graph=True)#第一次求導
print(x.grad)
x.grad.data.zero_() # 歸零之前求得的梯度
y.backward(torch.FloatTensor([1,1,1]))#第二次求導
print(x.grad)
閱讀更多 幻風的AI之路 的文章