日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

pytorch的backward

發布時間:2023/11/28 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pytorch的backward 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在學習的過程中遇見了一個問題,就是當使用backward()反向傳播時傳入參數的問題:

net.zero_grad() #所有參數的梯度清零
output.backward(Variable(t.ones(1, 10))) #反向傳播

這里的backward()中為什么需要傳入參數Variable(t.ones(1, 10))呢?沒有傳入就會報錯:

RuntimeError: grad can be implicitly created only for scalar outputs

這個錯誤的意思就是梯度只能為標量(即一個數)輸出隱式地創建

?

比如有一個例子是:

1)

#使用Tensor新建一個Variable
x = Variable(t.ones(2, 2),requires_grad = True)
x

返回:

tensor([[1., 1.],[1., 1.]], requires_grad=True)

此時查看該值的grad和grad_fn是沒有返回值的,因為沒有進行任何操作

x.grad_fn
x.grad

?

進行求和操作,查看梯度

y = x.sum()
y

返回:

tensor(4., grad_fn=<SumBackward0>)

這時候可查看:

y.grad_fn

返回:

<SumBackward0 at 0x122782978>

可知y是變量Variable x進行sum操作求來的,但是這個時候y.grad是沒有返回值的,因為沒有使用y進行別的操作

這個時候的x.grad也是沒有值的,雖然使用x進行了sum操作,但是還沒有對y反向傳播來計算梯度

y.backward()#反向傳播,計算梯度

然后再查看:

#因為y = x.sum() = (x[0][0] + x[0][1] + x[1][0] + x[1][1])
#每個值的梯度都為1
x.grad

返回:

tensor([[1., 1.],[1., 1.]])

?在這里我們可以看見y能夠求出x的梯度,這里的y是一個數,即標量

?

如果這里我們更改一下y的操作,將y設置為一個二維數組:

from __future__ import print_function
import torch as t
from torch.autograd import Variable
x = Variable(t.ones(2, 2),requires_grad = True)
y = x + 1
y.backward()

然后就會報上面的錯誤:

RuntimeError: grad can be implicitly created only for scalar outputs

?

總結:

因此當輸出不是標量時,調用.backwardI()就會出錯

?

解決辦法:

顯示聲明輸出的類型作為參數傳入,且參數的大小必須要和輸出值的大小相同

x.grad.data.zero_() #將之前的值清零
x.grad

返回:

tensor([[0., 0.],[0., 0.]])

進行反向傳播:

y.backward(y.data)
x.grad

也可以寫成,因為Variable和Tensor有近乎一致的接口

y.backward(y)
x.grad

返回:

tensor([[2., 2.],[2., 2.]])

但是這里返回值與預想的1不同,這個原因是得到的梯度會與參數的值相乘,所以最好傳入值為1,如:

y.backward(Variable(t.ones(2, 2)))
x.grad

這樣就能夠成功返回想要的值了:

tensor([[1., 1.],[1., 1.]])

?

更加復雜的操作:

在上面的例子中,x和y都是(2,2)的數組形式,每個yi都只與對應的xi相關

1)如果每個yi都與多個xi相關時,梯度又是怎么計算的呢?

比如x = (x1?= 2, x2?= 4), y = (x12+2x2, 2x1+3x22)

?

(i,j)的值就是傳入.backward()的參數的值

x = Variable(t.FloatTensor([[2, 4]]),requires_grad = True)
y = Variable(t.zeros(1, 2))
y[0,0] = x[0,0]**2 + 2 * x[0,1]
y[0,1] = 2 * x[0,0] + 3 * x[0,1]**2
y.backward(Variable(t.ones(1, 2))) #(i,j)= (1,1)
x.grad

返回:

tensor([[ 6., 26.]])

?

?

2)如果x和y不是相同的數組形式,且每個yi都與多個xi相關時,梯度又是怎么計算的呢?

比如x = (x1?= 2, x2?= 4, x3=5), y = (x12+2x2+4x3, 2x1+3x22+x32)

x = Variable(t.FloatTensor([[2, 4, 5]]),requires_grad = True)
y = Variable(t.zeros(1, 2))
y[0,0] = x[0,0]**2 + 2 * x[0,1] + 4 * x[0,2]
y[0,1] = 2 * x[0,0] + 3 * x[0,1]**2 + x[0,2]**2
y.backward(Variable(t.ones(1, 2)))
x.grad

返回:

tensor([[ 6., 26., 14.]])

如果(i, j) = (2,2),結果是否為(12, 52, 28)呢?

x = Variable(t.FloatTensor([[2, 4, 5]]),requires_grad = True)
y = Variable(t.zeros(1, 2))
y[0,0] = x[0,0]**2 + 2 * x[0,1] + 4 * x[0,2]
y[0,1] = 2 * x[0,0] + 3 * x[0,1]**2 + x[0,2]**2
y.backward(Variable(t.FloatTensor([[2, 2]])))
x.grad

返回:

tensor([[12., 52., 28.]])

?

3)如果你想要分別得到y1,y2對x1,x2,x3的求導值,方法是:

x = Variable(t.FloatTensor([[2, 4, 5]]),requires_grad = True)
y = Variable(t.zeros(1, 2))
y[0,0] = x[0,0]**2 + 2 * x[0,1] + 4 * x[0,2]
y[0,1] = 2 * x[0,0] + 3 * x[0,1]**2 + x[0,2]**2
j = t.zeros(3,2)#用于存放求導的值
#(i,j)=(1,0)這樣就會對應只求得y1對x1,x2和x3的求導
#retain_variables=True的作用是不在反向傳播后釋放內存,這樣才能夠再次反向傳播
y.backward(Variable(t.FloatTensor([[1, 0]])),retain_variables=True) 
j[:,0] = x.grad.data
x.grad.data.zero_() #將之前的值清零
#(i,j)=(1,0)這樣就會對應只求得y2對x1,x2和x3的求導
y.backward(Variable(t.FloatTensor([[0, 1]]))) 
j[:,1] = x.grad.data
print(j)

報錯:

TypeError: backward() got an unexpected keyword argument 'retain_variables'

原因是新版本使用的參數名為retain_graph,改了即可:

x = Variable(t.FloatTensor([[2, 4, 5]]),requires_grad = True)
y = Variable(t.zeros(1, 2))
y[0,0] = x[0,0]**2 + 2 * x[0,1] + 4 * x[0,2]
y[0,1] = 2 * x[0,0] + 3 * x[0,1]**2 + x[0,2]**2
j = t.zeros(3,2)#用于存放求導的值
#(i,j)=(1,0)這樣就會對應只求得y1對x1,x2和x3的求導
#retain_graph=True的作用是不在反向傳播后釋放內存,這樣才能夠再次反向傳播
y.backward(Variable(t.FloatTensor([[1, 0]])),retain_graph=True) 
j[:,0] = x.grad.data
x.grad.data.zero_() #將之前的值清零
#(i,j)=(1,0)這樣就會對應只求得y2對x1,x2和x3的求導
y.backward(Variable(t.FloatTensor([[0, 1]]))) 
j[:,1] = x.grad.data
print(j)

返回:

tensor([[ 4.,  2.],[ 2., 24.],[ 4., 10.]])
  

                            

總結

以上是生活随笔為你收集整理的pytorch的backward的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。