人工智能:損失函數對標量、向量、矩陣求導的是如何計算的?

專欄推薦



正文

深度學習框架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)



分享到:


相關文章: