婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 淺談Pytorch中autograd的若干(踩坑)總結

淺談Pytorch中autograd的若干(踩坑)總結

熱門標簽:哈爾濱ai外呼系統定制 海南400電話如何申請 白銀外呼系統 公司電話機器人 唐山智能外呼系統一般多少錢 激戰2地圖標注 廣告地圖標注app 陜西金融外呼系統 騰訊外呼線路

關于Variable和Tensor

舊版本的Pytorch中,Variable是對Tensor的一個封裝;在Pytorch大于v0.4的版本后,Varible和Tensor合并了,意味著Tensor可以像舊版本的Variable那樣運行,當然新版本中Variable封裝仍舊可以用,但是對Varieble操作返回的將是一個Tensor。

import torch as t
from torch.autograd import Variable
 
a = t.ones(3,requires_grad=True)
print(type(a))
#輸出:class 'torch.Tensor'>
 
a=Variable(a)
print(type(a))
#輸出仍舊是:class 'torch.Tensor'>
 
print(a.volatile)
#輸出:__main__:1: UserWarning: volatile was removed (Variable.volatile is always False)
a.volatile=True
print(a.volatile)
#輸出:__main__:1: UserWarning: volatile was removed (Variable.volatile is always False)
#現版本pytorch中移除了volatile這個屬性,即volatile總是false

葉子節點leaf

對于那些不是任何函數(Function)的輸出,由用戶創建的節點稱為葉子節點,葉子節點的grad_fn為None。

import torch as t
a = t.ones(3,requires_grad=True)
b = t.rand(3,requires_grad=True)
a,a.is_leaf
#輸出:(tensor([1., 1., 1.], requires_grad=True), True)
b
#輸出:(tensor([0.4254, 0.8763, 0.5901], requires_grad=True), True)
 
c = a*b
c.is_leaf
#輸出:False.說明c不是葉子節點
a.grad_fn
#輸出:None.葉子節點的grad_fn為None.
c.grad_fn
#輸出:MulBackward0 object at 0x7fa45c406278> 

autograd操作

首先Tensor是默認不需要求導的,即requires_grad默認為False。

import torch as t
a = t.ones(3)
a.requires_grad
#輸出:False.Tensor默認不需要求導

如果某一個節點requires_grad被設置為True,那么所有依賴它的節點requires_grad都為True。

import torch as t
 
a = t.ones(3)
b = t.ones(3,requires_grad=True)
b.requires_grad
#輸出:True
c = a + b
c.requires_grad
#輸出:True.雖然c沒有指定需要求導,然是c依賴于b,而b需要求導,所以c.requires_grad=True

只有scalar才能進行反向backward()操作,并且backward對于葉節點的grad的是累加的。當只進行計算操作不做backward,葉節點的grad不發生變化。

更正一下,并不是只有scaler才能進行backward操作,矩陣和向量也可以,只不過backward()中要添加對應維度的參數。

import torch as t
 
a = t.ones(3,requires_grad=True)
b = t.rand(3,requires_grad=True)
a,b
#輸出:(tensor([1., 1., 1.], requires_grad=True), 
#tensor([0.9373, 0.0556, 0.6426], requires_grad=True))
c = a*b
c
#輸出:tensor([0.9373, 0.0556, 0.6426], grad_fn=MulBackward0>)
c.backward(retain_graph=True)
#輸出:RuntimeError: grad can be implicitly created only for scalar outputs
#只有數值scalar才能進行backward操作
d = c.sum()
d.backward(retain_graph=True)
#retain_graph=True是為了保存中間緩存,否則再次backward的時候會報錯
a.grad
#輸出:tensor([0.9373, 0.0556, 0.6426])
b.grad
#輸出:tensor([1., 1., 1.])
#backward后a和b的grad產生了數值
e = c.sum()
e.backward(retain_graph=True)
b.grad
#輸出:tensor([2., 2., 2.]).b的grad進行了兩次backward后進行了累加.
f = c.sum()
b.grad
#輸出:tensor([2., 2., 2.])
#只進行計算不backward,梯度不更新

Tensor.data和Tensor.detach()

如過tensor的數值需要參與計算又不想參與到計算圖的更新中,計算的時候可以用tensor.data,這樣既能利用tensor的數值,又不會更新梯度。

import torch as t
 
a = t.ones(3,4,requires_grad=True)
b = t.rand(3,4,requires_grad=True)
 
a.data.requires_grad
#輸出:False. a.data獨立于計算圖之外
 
c = a.data * b.data
d = c.sum()
d.backward()
#輸出:RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
#因為獨立于計算圖之外,requires_grad = False所以不能backward()

當tensor.data被修改的時候,tensor也會同步的被修改,此時用該tensor進行計算并backward的時候梯度的值就不再準確了,因為tensor已經被修改了!

import torch as t
 
a = t.ones(3,4,requires_grad=True)
b = t.rand(3,4,requires_grad=True)
c = a*b
d = c.sum()
a.data.sigmoid_()
#輸出:tensor([[0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311]])
#雖然對a.data進行sigmoid操作,但是a的值已經被修改了.
d.backward()
b.grad
#輸出:tensor([[0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311]])
#b的grad不準了,本來應該都是1!

為了避免因為對tensor.data修改導致grad變化的情況,可以利用tensor.detach,同樣可以保證tensor不參與到計算圖當中,但是當tensor的值被改變的時候,再進行backward就會報錯而不會有先前的因為tensor的值被改變而導致不準的情況了。

import torch as t
 
a = t.ones(3,4,requires_grad=True)
b = t.rand(3,4,requires_grad=True)
c = a * b
d = c.sum()
a_ = a.detach()
a_.sigmoid_()
a
#輸出:tensor([[0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311],
#        [0.7311, 0.7311, 0.7311, 0.7311]], requires_grad=True)
#a的值已經發生了改變
d.backward()
#報錯:RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation
#因為a的值被修改了,所以不能再進行backward

推薦用tensor.detach的方式而不是tensor.data的方式,因為這樣更保險!

autograd.grad和hook

在計算的時候有時候我們可能會用到非葉節點的grad,但是非葉節點的grad在backward之后就會被自動清空:

import torch as t
 
a = t.ones(3,4,requires_grad=True)
b = t.rand(3,4,requires_grad=True)
c = a*b
d = c.sum()
d.backward()
a.grad
#輸出:tensor([[0.3114, 0.3017, 0.8461, 0.6899],
#        [0.3878, 0.8712, 0.2406, 0.7396],
#        [0.6369, 0.0907, 0.4984, 0.5058]])
c.grad
#輸出:None
#c為非葉子節點,計算后被清空

可以用autograd.grad和hook來處理這種情況:

#利用autograd.grad獲取中間節點梯度
t.autograd.grad(d,c)
#輸出:(tensor([[1., 1., 1., 1.],
#        [1., 1., 1., 1.],
#        [1., 1., 1., 1.]]),)
#利用hook獲取中間節點梯度
import torch as t
 
a = t.ones(3,4,requires_grad=True)
b = t.rand(3,4,requires_grad=True)
c = a*b
d = c.sum()
 
def print_grad(grad):
    print(grad)
 
#給c注冊hook
c_hook = c.register_hook(print_grad)
 
d.backward()
#輸出:tensor([[1., 1., 1., 1.],
#        [1., 1., 1., 1.],
#        [1., 1., 1., 1.]])
 
#移除鉤子
c_hook.remove()

補充:關于Pytorch中autograd和backward的一些筆記

1 Tensor

Pytorch中所有的計算其實都可以回歸到Tensor上,所以有必要重新認識一下Tensor。

如果我們需要計算某個Tensor的導數,那么我們需要設置其.requires_grad屬性為True。為方便說明,在本文中對于這種我們自己定義的變量,我們稱之為葉子節點(leaf nodes),而基于葉子節點得到的中間或最終變量則可稱之為結果節點。

另外一個Tensor中通常會記錄如下圖中所示的屬性:

data: 即存儲的數據信息

requires_grad: 設置為True則表示該 Tensor 需要求導

grad: 該 Tensor 的梯度值,每次在計算 backward 時都需要將前一時刻的梯度歸零,否則梯度值會一直累加,這個會在后面講到。

grad_fn: 葉子節點通常為 None,只有結果節點的 grad_fn 才有效,用于指示梯度函數是哪種類型。

is_leaf: 用來指示該 Tensor 是否是葉子節點。

舉例:

x = torch.rand(3, requires_grad=True)
y = x ** 2
z = x + x
print(
    'x requires grad: {},  is leaf: {},  grad: {},  grad_fn: {}.'
        .format(x.requires_grad, x.is_leaf, x.grad, x.grad_fn)
)
print(
    'y requires grad: {},  is leaf: {},  grad: {},  grad_fn: {}.'
        .format(y.requires_grad, y.is_leaf, y.grad, y.grad_fn)
)
print(
    'z requires grad: {},  is leaf: {},  grad: {},  grad_fn: {}.'
        .format(z.requires_grad, z.is_leaf, z.grad, z.grad_fn)
)

運行結果:

x requires grad: True, is leaf: True, grad: None, grad_fn: None.

y requires grad: True, is leaf: False, grad: None, grad_fn: PowBackward0 object at 0x0000021A3002CD88>.

z requires grad: True, is leaf: False, grad: None, grad_fn: AddBackward0 object at 0x0000021A3002CD88>.

2 torch.autograd.backward

如下代碼:

x = torch.tensor(1.0, requires_grad=True)
y = torch.tensor(2.0, requires_grad=True)
z = x**2+y
z.backward()
print(z, x.grad, y.grad)
>>> tensor(3., grad_fn=AddBackward0>) tensor(2.) tensor(1.)

當 z 是一個標量,當調用它的 backward 方法后會根據鏈式法則自動計算出葉子節點的梯度值。

但是如果遇到 z 是一個向量或者是一個矩陣的情況,這個時候又該怎么計算梯度呢?這種情況我們需要定義grad_tensor來計算矩陣的梯度。

在介紹為什么使用之前我們先看一下源代碼中backward的接口是如何定義的:

torch.autograd.backward(
        tensors, 
        grad_tensors=None, 
        retain_graph=None, 
        create_graph=False, 
        grad_variables=None)

tensor: 用于計算梯度的 tensor。也就是說這兩種方式是等價的:torch.autograd.backward(z) == z.backward()

grad_tensors: 在計算非標量的梯度時會用到。他其實也是一個tensor,它的shape一般需要和前面的tensor保持一致。

retain_graph: 通常在調用一次 backward 后,pytorch 會自動把計算圖銷毀,所以要想對某個變量重復調用 backward,則需要將該參數設置為True

create_graph: 當設置為True的時候可以用來計算更高階的梯度

grad_variables: 這個官方說法是 grad_variables' is deprecated. Use 'grad_tensors' instead. 也就是說這個參數后面版本中應該會丟棄,直接使用grad_tensors就好了。

pytorch設計了grad_tensors這么一個參數。它的作用相當于“權重”。

先看一個例子:

x = torch.ones(2,requires_grad=True)
z = x + 2
z.backward()
>>> ...
RuntimeError: grad can be implicitly created only for scalar outputs

上面的報錯信息意思是只有對標量輸出它才會計算梯度,而求一個矩陣對另一矩陣的導數束手無策。

x = torch.ones(2,requires_grad=True)
z = x + 2
z.sum().backward()
print(x.grad)
>>> tensor([1., 1.])

而grad_tensors這個參數就扮演了幫助求和的作用。

換句話說,就是對 Z 和一個權重張量grad_tensors進行 hadamard product 后求和。這也是 grad_tensors 需要與傳入的 tensor 大小一致的原因。

x = torch.ones(2,requires_grad=True)
z = x + 2
z.backward(torch.ones_like(z)) # grad_tensors需要與輸入tensor大小一致
print(x.grad)
>>> tensor([1., 1.])

3 torch.autograd.grad

torch.autograd.grad(
        outputs, 
        inputs, 
        grad_outputs=None, 
        retain_graph=None, 
        create_graph=False, 
        only_inputs=True, 
        allow_unused=False)

看了前面的內容后再看這個函數就很好理解了,各參數作用如下:

outputs: 結果節點,即被求導數

inputs: 葉子節點

grad_outputs: 類似于backward方法中的grad_tensors

retain_graph: 同上

create_graph: 同上

only_inputs: 默認為True,如果為True,則只會返回指定input的梯度值。 若為False,則會計算所有葉子節點的梯度,并且將計算得到的梯度累加到各自的.grad屬性上去。

allow_unused: 默認為False, 即必須要指定input,如果沒有指定的話則報錯。

注意該函數返回的是 tuple 類型。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • pytorch-autograde-計算圖的特點說明
  • pytorch 中autograd.grad()函數的用法說明
  • PyTorch一小時掌握之autograd機制篇

標簽:上海 四川 惠州 黑龍江 鷹潭 黔西 常德 益陽

巨人網絡通訊聲明:本文標題《淺談Pytorch中autograd的若干(踩坑)總結》,本文關鍵詞  淺談,Pytorch,中,autograd,的,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《淺談Pytorch中autograd的若干(踩坑)總結》相關的同類信息!
  • 本頁收集關于淺談Pytorch中autograd的若干(踩坑)總結的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    日韩二区三区四区| 99精品视频免费在线观看| 国内成人免费视频| 日韩欧美在线网站| 午夜精品一区二区三区免费视频 | 蜜桃av一区二区在线观看| 在线观看91精品国产入口| 国产肉丝袜一区二区| 国产成人免费视频网站高清观看视频 | 蜜桃视频一区二区三区| 91精品国产欧美一区二区18| 蜜桃精品在线观看| 久久久久久久久久久电影| 国产一二精品视频| 国产欧美日韩精品a在线观看| bt7086福利一区国产| 成人免费一区二区三区视频| 欧美三电影在线| 黄色小说综合网站| 亚洲色图.com| 欧美mv和日韩mv国产网站| 成人免费av网站| 天天色综合天天| 国产精品色在线| 欧美日韩一区不卡| 一区二区三区免费在线观看| 欧美一级xxx| 92国产精品观看| 免费成人你懂的| 亚洲少妇屁股交4| 精品国产青草久久久久福利| av日韩在线网站| 免费在线成人网| 亚洲四区在线观看| www激情久久| 欧美网站一区二区| 国产一区二区三区视频在线播放| 国产色产综合产在线视频| 欧亚一区二区三区| 国内精品写真在线观看| 亚洲女子a中天字幕| 国产日本欧洲亚洲| 精品动漫一区二区三区在线观看| 日本韩国一区二区三区视频| 国产成人精品一区二| 亚洲mv大片欧洲mv大片精品| 亚洲女人小视频在线观看| 国产午夜精品福利| 精品欧美黑人一区二区三区| 欧美日韩久久久久久| 99国产精品国产精品毛片| 国产一区二区三区不卡在线观看| 午夜电影久久久| 亚洲免费观看高清完整版在线 | 国产精品亚洲综合一区在线观看| 亚洲最色的网站| 亚洲免费观看高清完整版在线观看熊| 久久婷婷一区二区三区| 7777精品伊人久久久大香线蕉经典版下载| 99精品视频在线免费观看| 成人白浆超碰人人人人| 懂色av一区二区三区蜜臀| 国产剧情一区在线| 国产成人aaa| 成人免费三级在线| 91在线你懂得| 在线亚洲一区观看| 欧美综合天天夜夜久久| 欧美视频一区二区在线观看| 欧美三级午夜理伦三级中视频| 在线亚洲欧美专区二区| 欧美日韩视频第一区| 欧美久久婷婷综合色| 7777精品伊人久久久大香线蕉经典版下载| 欧美性色综合网| 日韩欧美国产成人一区二区| xnxx国产精品| 国产精品传媒在线| 亚洲人成电影网站色mp4| 亚洲免费av在线| 日韩精品一级中文字幕精品视频免费观看 | 一本久久a久久精品亚洲| 色天天综合久久久久综合片| 欧美日韩视频在线第一区| 欧美成人猛片aaaaaaa| 久久精品男人天堂av| 亚洲三级在线免费| 美腿丝袜亚洲色图| av一区二区三区在线| 欧美精品久久久久久久多人混战 | 国产精一区二区三区| 成人激情黄色小说| 欧美亚洲综合在线| 2021国产精品久久精品| 亚洲色图欧洲色图婷婷| 美女视频一区二区| 91麻豆精品视频| 精品盗摄一区二区三区| 亚洲乱码中文字幕| 国产酒店精品激情| 欧美久久久久免费| 国产精品国产自产拍在线| 日韩综合在线视频| 99久久精品免费观看| 欧美一区二区三区小说| 中文字幕第一区综合| 日韩精品欧美精品| 一本色道亚洲精品aⅴ| 欧美成人a∨高清免费观看| 亚洲色图清纯唯美| 国产1区2区3区精品美女| 制服丝袜亚洲播放| 亚洲国产sm捆绑调教视频| 国产成人8x视频一区二区| 欧美精品久久天天躁| 自拍偷拍国产亚洲| 国产999精品久久久久久| 欧美v国产在线一区二区三区| 亚洲精品日韩一| 国产剧情一区二区三区| 精品区一区二区| 午夜精品免费在线观看| 国产激情视频一区二区在线观看| 色偷偷一区二区三区| 国产精品乱码久久久久久| 卡一卡二国产精品 | 精品99999| 日本亚洲三级在线| 在线一区二区观看| 亚洲最大成人网4388xx| 从欧美一区二区三区| 精品国产一区二区精华| 日本一不卡视频| 欧美性色黄大片| 亚洲一区二区三区四区五区中文| 99re热这里只有精品免费视频| 国产精品三级av在线播放| 国产高清在线精品| 欧美激情综合五月色丁香小说| 精品系列免费在线观看| 2欧美一区二区三区在线观看视频| 视频在线观看一区二区三区| 91在线精品一区二区| 国产精品水嫩水嫩| 一本大道久久a久久综合婷婷| 日本一区二区三区dvd视频在线| 国产一区二区三区日韩| 中文字幕av一区二区三区| 成人午夜激情片| 一区二区三区日韩在线观看| 色婷婷av一区二区三区gif| 亚洲18影院在线观看| 日韩一区二区三区在线观看| 国产一区二三区| 亚洲人精品一区| 欧美精选一区二区| 国产自产高清不卡| 亚洲欧美一区二区三区久本道91 | 最新日韩在线视频| 欧美三电影在线| 国产乱子伦视频一区二区三区| 日本一区二区三区在线不卡| 成人黄色av电影| 亚洲国产日韩综合久久精品| 51精品视频一区二区三区| 日本一区中文字幕| 国产女主播视频一区二区| 成人动漫一区二区| 亚洲v日本v欧美v久久精品| 17c精品麻豆一区二区免费| 欧美性猛交一区二区三区精品| 另类专区欧美蜜桃臀第一页| 中文字幕精品综合| 欧美精品三级日韩久久| 懂色av一区二区三区免费观看| 亚洲成人1区2区| 日本一区二区三区免费乱视频| 欧美日本在线一区| 成人av中文字幕| 久久99精品久久久久久动态图 | 亚洲欧美日韩国产成人精品影院| 91.麻豆视频| 91在线精品一区二区三区| 激情六月婷婷久久| 五月婷婷欧美视频| 综合久久久久久久| 久久综合色天天久久综合图片| 欧美日韩一级视频| 色狠狠色狠狠综合| 成人在线一区二区三区| 六月婷婷色综合| 日韩国产欧美视频| 亚洲午夜免费电影| 中文字幕一区二区在线播放| 欧美成人一区二区三区在线观看| 91网址在线看| 成人动漫一区二区三区| 国产精品一区二区x88av| 麻豆成人综合网| 午夜欧美在线一二页|