国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

PyTorch 的 Autograd 機制和使用

深度學(xué)習(xí)自然語言處理 ? 來源:深度學(xué)習(xí)自然語言處理 ? 作者:深度學(xué)習(xí)自然語言 ? 2022-08-15 09:37 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

PyTorch 作為一個深度學(xué)習(xí)平臺,在深度學(xué)習(xí)任務(wù)中比 NumPy 這個科學(xué)計算庫強在哪里呢?我覺得一是 PyTorch 提供了自動求導(dǎo)機制,二是對 GPU 的支持。由此可見,自動求導(dǎo) (autograd) 是 PyTorch,乃至其他大部分深度學(xué)習(xí)框架中的重要組成部分。

了解自動求導(dǎo)背后的原理和規(guī)則,對我們寫出一個更干凈整潔甚至更高效的 PyTorch 代碼是十分重要的。但是,現(xiàn)在已經(jīng)有了很多封裝好的 API,我們在寫一個自己的網(wǎng)絡(luò)的時候,可能幾乎都不用去注意求導(dǎo)這些問題,因為這些 API 已經(jīng)在私底下處理好了這些事情。現(xiàn)在我們往往只需要,搭建個想要的模型,處理好數(shù)據(jù)的載入,調(diào)用現(xiàn)成的 optimizer 和 loss function,直接開始訓(xùn)練就好了。仔細一想,好像連需要設(shè)置 requires_grad=True 的地方好像都沒有。有人可能會問,那我們?nèi)チ私庾詣忧髮?dǎo)還有什么用啊?

原因有很多,可以幫我們更深入地了解 PyTorch 這些寬泛的理由我就不說了,我舉一個例子:當(dāng)我們想使用一個 PyTorch 默認中并沒有的 loss function 的時候,比如目標檢測模型 YOLO 的 loss,我們可能就得自己去實現(xiàn)。如果我們不熟悉基本的 PyTorch 求導(dǎo)機制的話,對于實現(xiàn)過程中比如 tensor 的 in-place 操作等很容易出錯,導(dǎo)致需要話很長時間去 debug,有的時候即使定位到了錯誤的位置,也不知道如何去修改。相反,如果我們理清楚了背后的原理,我們就能很快地修改這些錯誤,甚至根本不會去犯這些錯誤。鑒于現(xiàn)在官方支持的 loss function 并不多,而且深度學(xué)習(xí)領(lǐng)域日新月異,很多新的效果很好的 loss function 層出不窮,如果要用的話可能需要我們自己來實現(xiàn)。基于這個原因,我們了解一下自動求導(dǎo)機制還是很有必要的。

本文所有代碼例子都基于 Python3 和 PyTorch 1.1, 也就是不會涉及 0.4 版本以前的 Variable 這個數(shù)據(jù)結(jié)構(gòu)。在文章中我們不會去分析一些非常底層的代碼,而是通過一系列實例來理解自動求導(dǎo)機制。在舉例的過程中我盡量保持場景的一致性,不用每個例子都需要重新了解假定的變量。另外,本文篇幅比較長。如果發(fā)現(xiàn)文章中有錯誤或者沒有講清楚的地方,歡迎大家在評論區(qū)指正和討論。

目錄

計算圖

一個具體的例子

葉子張量

inplace 操作

動態(tài)圖,靜態(tài)圖

計算圖

首先,我們先簡單地介紹一下什么是計算圖(Computational Graphs),以方便后邊的講解。假設(shè)我們有一個復(fù)雜的神經(jīng)網(wǎng)絡(luò)模型,我們把它想象成一個錯綜復(fù)雜的管道結(jié)構(gòu),不同的管道之間通過節(jié)點連接起來,我們有一個注水口,一個出水口。我們在入口注入數(shù)據(jù)的之后,數(shù)據(jù)就沿著設(shè)定好的管道路線緩緩流動到出水口,這時候我們就完成了一次正向傳播。想象一下輸入的 tensor 數(shù)據(jù)在管道中緩緩流動的場景,這就是為什么 TensorFlow 叫 TensorFlow 的原因!emmm,好像走錯片場了,不過計算圖在 PyTorch 中也是類似的。至于這兩個非常有代表性的深度學(xué)習(xí)框架在計算圖上有什么區(qū)別,我們稍后再談。

計算圖通常包含兩種元素,一個是 tensor,另一個是 Function。張量 tensor 不必多說,但是大家可能對 Function 比較陌生。這里 Function 指的是在計算圖中某個節(jié)點(node)所進行的運算,比如加減乘除卷積等等之類的,F(xiàn)unction 內(nèi)部有 forward() 和 backward() 兩個方法,分別應(yīng)用于正向、反向傳播。

a=torch.tensor(2.0,requires_grad=True)
b=a.exp()
print(b)
#tensor(7.3891,grad_fn=)

在我們做正向傳播的過程中,除了執(zhí)行 forward() 操作之外,還會同時會為反向傳播做一些準備,為反向計算圖添加 Function 節(jié)點。在上邊這個例子中,變量 b 在反向傳播中所需要進行的操作是

一個具體的例子

了解了基礎(chǔ)知識之后,現(xiàn)在我們來看一個具體的計算例子,并畫出它的正向和反向計算圖。假如我們需要計算這么一個模型:

l1 = input x w1
l2 = l1 + w2
l3 = l1 x w3
l4 = l2 x l3
loss = mean(l4)

這個例子比較簡單,涉及的最復(fù)雜的操作是求平均,但是如果我們把其中的加法和乘法操作換成卷積,那么其實和神經(jīng)網(wǎng)絡(luò)類似。我們可以簡單地畫一下它的計算圖:

91f886d4-1c2d-11ed-ba43-dac502259ad0.png

圖1:正向計算圖

下面給出了對應(yīng)的代碼,我們定義了input,w1,w2,w3 這三個變量,其中 input 不需要求導(dǎo)結(jié)果。根據(jù) PyTorch 默認的求導(dǎo)規(guī)則,對于 l1 來說,因為有一個輸入需要求導(dǎo)(也就是 w1 需要),所以它自己默認也需要求導(dǎo),即 requires_grad=True(如果對這個規(guī)則不熟悉,歡迎參考 我上一篇博文的第一部分 或者直接查看 官方 Tutorial 相關(guān)部分)。在整張計算圖中,只有 input 一個變量是 requires_grad=False 的。正向傳播過程的具體代碼如下:

input=torch.ones([2,2],requires_grad=False)
w1=torch.tensor(2.0,requires_grad=True)
w2=torch.tensor(3.0,requires_grad=True)
w3=torch.tensor(4.0,requires_grad=True)

l1=input*w1
l2=l1+w2
l3=l1*w3
l4=l2*l3
loss=l4.mean()


print(w1.data,w1.grad,w1.grad_fn)
#tensor(2.)NoneNone

print(l1.data,l1.grad,l1.grad_fn)
#tensor([[2.,2.],
#[2.,2.]])None

print(loss.data,loss.grad,loss.grad_fn)
#tensor(40.)None

正向傳播的結(jié)果基本符合我們的預(yù)期。我們可以看到,變量 l1 的 grad_fn 儲存著乘法操作符 ,用于在反向傳播中指導(dǎo)導(dǎo)數(shù)的計算。而 w1 是用戶自己定義的,不是通過計算得來的,所以其 grad_fn 為空;同時因為還沒有進行反向傳播,grad 的值也為空。接下來,我們看一下如果要繼續(xù)進行反向傳播,計算圖應(yīng)該是什么樣子:

920ee3b6-1c2d-11ed-ba43-dac502259ad0.png

圖2:反向計算圖

反向圖也比較簡單,從 loss 這個變量開始,通過鏈式法則,依次計算出各部分的導(dǎo)數(shù)。說到這里,我們不妨先自己手動推導(dǎo)一下求導(dǎo)的結(jié)果,再與程序運行結(jié)果作對比。如果對這部分不感興趣的讀者,可以直接跳過。

再擺一下公式:

input = [1.0, 1.0, 1.0, 1.0]
w1 = [2.0, 2.0, 2.0, 2.0]
w2 = [3.0, 3.0, 3.0, 3.0]
w3 = [4.0, 4.0, 4.0, 4.0]

l1 = input x w1 = [2.0, 2.0, 2.0, 2.0] l2 = l1 + w2 = [5.0, 5.0, 5.0, 5.0] l3 = l1 x w3 = [8.0, 8.0, 8.0, 8.0] l4 = l2 x l3 = [40.0, 40.0, 40.0, 40.0] loss = mean(l4) = 40.0

首先 , 所以 對 的偏導(dǎo)分別為 ;

接著 , 同時 ;

現(xiàn)在看 對它的兩個變量的偏導(dǎo): ,

因此 , 其和為 10 ;

同理,再看一下求 導(dǎo)數(shù)的過程:

,其和為 8。

其他的導(dǎo)數(shù)計算基本上都類似,因為過程太多,這里就不全寫出來了,如果有興趣的話大家不妨自己繼續(xù)算一下。

接下來我們繼續(xù)運行代碼,并檢查一下結(jié)果和自己算的是否一致:

loss.backward()

print(w1.grad,w2.grad,w3.grad)
#tensor(28.)tensor(8.)tensor(10.)
print(l1.grad,l2.grad,l3.grad,l4.grad,loss.grad)
#NoneNoneNoneNoneNone

首先我們需要注意一下的是,在之前寫程序的時候我們給定的 w 們都是一個常數(shù),利用了廣播的機制實現(xiàn)和常數(shù)和矩陣的加法乘法,比如 w2 + l1,實際上我們的程序會自動把 w2 擴展成 [[3.0, 3.0], [3.0, 3.0]],和 l1 的形狀一樣之后,再進行加法計算,計算的導(dǎo)數(shù)結(jié)果實際上為 [[2.0, 2.0], [2.0, 2.0]],為了對應(yīng)常數(shù)輸入,所以最后 w2 的梯度返回為矩陣之和 8 。另外還有一個問題,雖然 w 開頭的那些和我們的計算結(jié)果相符,但是為什么 l1,l2,l3,甚至其他的部分的求導(dǎo)結(jié)果都為空呢?想要解答這個問題,我們得明白什么是葉子張量。

葉子張量

對于任意一個張量來說,我們可以用 tensor.is_leaf 來判斷它是否是葉子張量(leaf tensor)。在反向傳播過程中,只有 is_leaf=True 的時候,需要求導(dǎo)的張量的導(dǎo)數(shù)結(jié)果才會被最后保留下來。

對于 requires_grad=False 的 tensor 來說,我們約定俗成地把它們歸為葉子張量。但其實無論如何劃分都沒有影響,因為張量的 is_leaf 屬性只有在需要求導(dǎo)的時候才有意義。

我們真正需要注意的是當(dāng) requires_grad=True 的時候,如何判斷是否是葉子張量:當(dāng)這個 tensor 是用戶創(chuàng)建的時候,它是一個葉子節(jié)點,當(dāng)這個 tensor 是由其他運算操作產(chǎn)生的時候,它就不是一個葉子節(jié)點。我們來看個例子:

a=torch.ones([2,2],requires_grad=True)
print(a.is_leaf)
#True

b=a+2
print(b.is_leaf)
#False
#因為b不是用戶創(chuàng)建的,是通過計算生成的

這時有同學(xué)可能會問了,為什么要搞出這么個葉子張量的概念出來?原因是為了節(jié)省內(nèi)存(或顯存)。我們來想一下,那些非葉子結(jié)點,是通過用戶所定義的葉子節(jié)點的一系列運算生成的,也就是這些非葉子節(jié)點都是中間變量,一般情況下,用戶不會去使用這些中間變量的導(dǎo)數(shù),所以為了節(jié)省內(nèi)存,它們在用完之后就被釋放了。

我們回頭看一下之前的反向傳播計算圖,在圖中的葉子節(jié)點我用綠色標出了。可以看出來,被叫做葉子,可能是因為游離在主干之外,沒有子節(jié)點,因為它們都是被用戶創(chuàng)建的,不是通過其他節(jié)點生成。對于葉子節(jié)點來說,它們的 grad_fn 屬性都為空;而對于非葉子結(jié)點來說,因為它們是通過一些操作生成的,所以它們的 grad_fn 不為空。

我們有辦法保留中間變量的導(dǎo)數(shù)嗎?當(dāng)然有,通過使用 tensor.retain_grad() 就可以:

#和前邊一樣
#...
loss=l4.mean()

l1.retain_grad()
l4.retain_grad()
loss.retain_grad()

loss.backward()

print(loss.grad)
#tensor(1.)
print(l4.grad)
#tensor([[0.2500,0.2500],
#[0.2500,0.2500]])
print(l1.grad)
#tensor([[7.,7.],
#[7.,7.]])

如果我們只是想進行 debug,只需要輸出中間變量的導(dǎo)數(shù)信息,而不需要保存它們,我們還可以使用 tensor.register_hook,例子如下:

#和前邊一樣
#...
loss=l4.mean()

l1.register_hook(lambdagrad:print('l1grad:',grad))
l4.register_hook(lambdagrad:print('l4grad:',grad))
loss.register_hook(lambdagrad:print('lossgrad:',grad))

loss.backward()

#lossgrad:tensor(1.)
#l4grad:tensor([[0.2500,0.2500],
#[0.2500,0.2500]])
#l1grad:tensor([[7.,7.],
#[7.,7.]])

print(loss.grad)
#None
#loss的grad在print完之后就被清除掉了

這個函數(shù)的功能遠遠不止打印導(dǎo)數(shù)信息用以 debug,但是一般很少用,所以這里就不擴展了,

到此為止,我們已經(jīng)討論完了這個實例中的正向傳播和反向傳播的有關(guān)內(nèi)容了。回過頭來看, input 其實很像神經(jīng)網(wǎng)絡(luò)輸入的圖像,w1, w2, w3 則類似卷積核的參數(shù),而 l1, l2, l3, l4 可以表示4個卷積層輸出,如果我們把節(jié)點上的加法乘法換成卷積操作的話。實際上這個簡單的模型,很像我們平時的神經(jīng)網(wǎng)絡(luò)的簡化版,通過這個例子,相信大家多少也能對神經(jīng)網(wǎng)絡(luò)的正向和反向傳播過程有個大致的了解了吧。

inplace 操作

現(xiàn)在我們來看一下本篇的重點,inplace operation。可以說,我們求導(dǎo)時候大部分的 bug,都出在使用了 inplace 操作上。現(xiàn)在我們以 PyTorch 不同的報錯信息作為驅(qū)動,來講一講 inplace 操作吧。第一個報錯信息:

RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: balabala...

不少人可能會感到很熟悉,沒錯,我就是其中之一。之前寫代碼的時候竟經(jīng)常報這個錯,原因是對 inplace 操作不了解。要搞清楚為什么會報錯,我們先來了解一下什么是 inplace 操作:inplace 指的是在不更改變量的內(nèi)存地址的情況下,直接修改變量的值。我們來看兩種情況,大家覺得這兩種情況哪個是 inplace 操作,哪個不是?或者兩個都是 inplace?

#情景1
a=a.exp()

#情景2
a[0]=10

答案是:情景1不是 inplace,類似 Python 中的 i=i+1, 而情景2是 inplace 操作,類似 i+=1。依稀記得當(dāng)時做機器學(xué)習(xí)的大作業(yè),很多人都被其中一個 i+=1 和 i=i+1 問題給坑了好長時間。那我們來實際測試一下:

#我們要用到id()這個函數(shù),其返回值是對象的內(nèi)存地址
#情景1
a=torch.tensor([3.0,1.0])
print(id(a))#2112716404344
a=a.exp()
print(id(a))#2112715008904
#在這個過程中a.exp()生成了一個新的對象,然后再讓a
#指向它的地址,所以這不是個inplace操作

#情景2
a=torch.tensor([3.0,1.0])
print(id(a))#2112716403840
a[0]=10
print(id(a),a)#2112716403840tensor([10.,1.])
#inplace操作,內(nèi)存地址沒變

PyTorch 是怎么檢測 tensor 發(fā)生了 inplace 操作呢?答案是通過 tensor._version 來檢測的。我們還是來看個例子:

a=torch.tensor([1.0,3.0],requires_grad=True)
b=a+2
print(b._version)#0

loss=(b*b).mean()
b[0]=1000.0
print(b._version)#1

loss.backward()
#RuntimeError:oneofthevariablesneededforgradientcomputationhasbeenmodifiedbyaninplaceoperation...

每次 tensor 在進行 inplace 操作時,變量 _version 就會加1,其初始值為0。在正向傳播過程中,求導(dǎo)系統(tǒng)記錄的 b 的 version 是0,但是在進行反向傳播的過程中,求導(dǎo)系統(tǒng)發(fā)現(xiàn) b 的 version 變成1了,所以就會報錯了。但是還有一種特殊情況不會報錯,就是反向傳播求導(dǎo)的時候如果沒用到 b 的值(比如 y=x+1, y 關(guān)于 x 的導(dǎo)數(shù)是1,和 x 無關(guān)),自然就不會去對比 b 前后的 version 了,所以不會報錯。

上邊我們所說的情況是針對非葉子節(jié)點的,對于 requires_grad=True 的葉子節(jié)點來說,要求更加嚴格了,甚至在葉子節(jié)點被使用之前修改它的值都不行。我們來看一個報錯信息:

RuntimeError: leaf variable has been moved into the graph interior

這個意思通俗一點說就是你的一頓 inplace 操作把一個葉子節(jié)點變成了非葉子節(jié)點了。我們知道,非葉子節(jié)點的導(dǎo)數(shù)在默認情況下是不會被保存的,這樣就會出問題了。舉個小例子:

a=torch.tensor([10.,5.,2.,3.],requires_grad=True)
print(a,a.is_leaf)
#tensor([10.,5.,2.,3.],requires_grad=True)True

a[:]=0
print(a,a.is_leaf)
#tensor([0.,0.,0.,0.],grad_fn=)False

loss=(a*a).mean()
loss.backward()
#RuntimeError:leafvariablehasbeenmovedintothegraphinterior

我們看到,在進行對 a 的重新 inplace 賦值之后,表示了 a 是通過 copy operation 生成的,grad_fn 都有了,所以自然而然不是葉子節(jié)點了。本來是該有導(dǎo)數(shù)值保留的變量,現(xiàn)在成了導(dǎo)數(shù)會被自動釋放的中間變量了,所以 PyTorch 就給你報錯了。還有另外一種情況:

a=torch.tensor([10.,5.,2.,3.],requires_grad=True)
a.add_(10.)#或者a+=10.
#RuntimeError:aleafVariablethatrequiresgradhasbeenusedinanin-placeoperation.

這個更厲害了,不等到你調(diào)用 backward,只要你對需要求導(dǎo)的葉子張量使用了這些操作,馬上就會報錯。那是不是需要求導(dǎo)的葉子節(jié)點一旦被初始化賦值之后,就不能修改它們的值了呢?我們?nèi)绻谀撤N情況下需要重新對葉子變量賦值該怎么辦呢?有辦法!

#方法一
a=torch.tensor([10.,5.,2.,3.],requires_grad=True)
print(a,a.is_leaf,id(a))
#tensor([10.,5.,2.,3.],requires_grad=True)True2501274822696

a.data.fill_(10.)
#或者a.detach().fill_(10.)
print(a,a.is_leaf,id(a))
#tensor([10.,10.,10.,10.],requires_grad=True)True2501274822696

loss=(a*a).mean()
loss.backward()
print(a.grad)
#tensor([5.,5.,5.,5.])

#方法二
a=torch.tensor([10.,5.,2.,3.],requires_grad=True)
print(a,a.is_leaf)
#tensor([10.,5.,2.,3.],requires_grad=True)True

withtorch.no_grad():
a[:]=10.
print(a,a.is_leaf)
#tensor([10.,10.,10.,10.],requires_grad=True)True

loss=(a*a).mean()
loss.backward()
print(a.grad)
#tensor([5.,5.,5.,5.])

修改的方法有很多種,核心就是修改那個和變量共享內(nèi)存,但 requires_grad=False 的版本的值,比如通過 tensor.data 或者 tensor.detach()(至于這二者更詳細的介紹與比較,歡迎參照我上一篇文章的第四部分)。我們需要注意的是,要在變量被使用之前修改,不然等計算完之后再修改,還會造成求導(dǎo)上的問題,會報錯的。

為什么 PyTorch 的求導(dǎo)不支持絕大部分 inplace 操作呢?從上邊我們也看出來了,因為真的很 tricky。比如有的時候在一個變量已經(jīng)參與了正向傳播的計算,之后它的值被修改了,在做反向傳播的時候如果還需要這個變量的值的話,我們肯定不能用那個后來修改的值吧,但沒修改之前的原始值已經(jīng)被釋放掉了,我們怎么辦?一種可行的辦法就是我們在 Function 做 forward 的時候每次都開辟一片空間儲存當(dāng)時輸入變量的值,這樣無論之后它們怎么修改,都不會影響了,反正我們有備份在存著。但這樣有什么問題?這樣會導(dǎo)致內(nèi)存(或顯存)使用量大大增加。因為我們不確定哪個變量可能之后會做 inplace 操作,所以我們每個變量在做完 forward 之后都要儲存一個備份,成本太高了。除此之外,inplace operation 還可能造成很多其他求導(dǎo)上的問題。

總之,我們在實際寫代碼的過程中,沒有必須要用 inplace operation 的情況,而且支持它會帶來很大的性能上的犧牲,所以 PyTorch 不推薦使用 inplace 操作,當(dāng)求導(dǎo)過程中發(fā)現(xiàn)有 inplace 操作影響求導(dǎo)正確性的時候,會采用報錯的方式提醒。但這句話反過來說就是,因為只要有 inplace 操作不當(dāng)就會報錯,所以如果我們在程序中使用了 inplace 操作卻沒報錯,那么說明我們最后求導(dǎo)的結(jié)果是正確的,沒問題的。這就是我們常聽見的沒報錯就沒有問題

動態(tài)圖,靜態(tài)圖

可能大家都聽說過,PyTorch 使用的是動態(tài)圖(Dynamic Computational Graphs)的方式,而 TensorFlow 使用的是靜態(tài)圖(Static Computational Graphs)。所以二者究竟有什么區(qū)別呢,我們本節(jié)來就來討論這個事情。

所謂動態(tài)圖,就是每次當(dāng)我們搭建完一個計算圖,然后在反向傳播結(jié)束之后,整個計算圖就在內(nèi)存中被釋放了。如果想再次使用的話,必須從頭再搭一遍,參見下邊這個例子。而以 TensorFlow 為代表的靜態(tài)圖,每次都先設(shè)計好計算圖,需要的時候?qū)嵗@個圖,然后送入各種輸入,重復(fù)使用,只有當(dāng)會話結(jié)束的時候創(chuàng)建的圖才會被釋放(不知道這里我對 tf.Session 的理解對不對,如果有錯誤希望大佬們能指正一下),就像我們之前舉的那個水管的例子一樣,設(shè)計好水管布局之后,需要用的時候就開始搭,搭好了就往入口加水,什么時候不需要了,再把管道都給拆了。

#這是一個關(guān)于 PyTorch 是動態(tài)圖的例子:
a=torch.tensor([3.0,1.0],requires_grad=True)
b=a*a
loss=b.mean()

loss.backward()#正常
loss.backward()#RuntimeError

#第二次:從頭再來一遍
a=torch.tensor([3.0,1.0],requires_grad=True)
b=a*a
loss=b.mean()
loss.backward()#正常

從描述中我們可以看到,理論上來說,靜態(tài)圖在效率上比動態(tài)圖要高。因為首先,靜態(tài)圖只用構(gòu)建一次,然后之后重復(fù)使用就可以了;其次靜態(tài)圖因為是固定不需要改變的,所以在設(shè)計完了計算圖之后,可以進一步的優(yōu)化,比如可以將用戶原本定義的 Conv 層和 ReLU 層合并成 ConvReLU 層,提高效率。

但是,深度學(xué)習(xí)框架的速度不僅僅取決于圖的類型,還很其他很多因素,比如底層代碼質(zhì)量,所使用的底層 BLAS 庫等等等都有關(guān)。從實際測試結(jié)果來說,至少在主流的模型的訓(xùn)練時間上,PyTorch 有著至少不遜于靜態(tài)圖框架 Caffe,TensorFlow 的表現(xiàn)。具體對比數(shù)據(jù)可以參考:

https://github.com/ilkarman/DeepLearningFrameworks

大家不要急著糾正我,我知道,我現(xiàn)在就說:當(dāng)然,在 9102 年的今天,動態(tài)圖和靜態(tài)圖直接的界限已經(jīng)開始慢慢模糊。PyTorch 模型轉(zhuǎn)成 Caffe 模型越來越方便,而 TensorFlow 也加入了一些動態(tài)圖機制。

除了動態(tài)圖之外,PyTorch 還有一個特性,叫 eager execution。意思就是當(dāng)遇到 tensor 計算的時候,馬上就回去執(zhí)行計算,也就是,實際上 PyTorch 根本不會去構(gòu)建正向計算圖,而是遇到操作就執(zhí)行。真正意義上的正向計算圖是把所有的操作都添加完,構(gòu)建好了之后,再運行神經(jīng)網(wǎng)絡(luò)的正向傳播。

正是因為 PyTorch 的兩大特性:動態(tài)圖和 eager execution,所以它用起來才這么順手,簡直就和寫 Python 程序一樣舒服,debug 也非常方便。除此之外,我們從之前的描述也可以看出,PyTorch 十分注重占用內(nèi)存(或顯存)大小,沒有用的空間釋放很及時,可以很有效地利用有限的內(nèi)存。

總結(jié)

本篇文章主要討論了 PyTorch 的 Autograd 機制和使用 inplace 操作不當(dāng)可能會導(dǎo)致的各種報錯。在實際寫代碼的過程中,涉及需要求導(dǎo)的部分,不建議大家使用 inplace 操作。除此之外我們還比較了動態(tài)圖和靜態(tài)圖框架,PyTorch 作為動態(tài)圖框架的代表之一,對初學(xué)者非常友好,而且運行速度上不遜于靜態(tài)圖框架,再加上現(xiàn)在通過 ONNX 轉(zhuǎn)換為其他框架的模型用以部署也越來越方便,我覺得是一個非常稱手的深度學(xué)習(xí)工具。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4417

    瀏覽量

    67509
  • 模型
    +關(guān)注

    關(guān)注

    1

    文章

    3752

    瀏覽量

    52109
  • 深度學(xué)習(xí)
    +關(guān)注

    關(guān)注

    73

    文章

    5599

    瀏覽量

    124398
  • pytorch
    +關(guān)注

    關(guān)注

    2

    文章

    813

    瀏覽量

    14852

原文標題:PyTorch 的 Autograd詳解

文章出處:【微信號:zenRRan,微信公眾號:深度學(xué)習(xí)自然語言處理】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Pytorch 與 Visionfive2 兼容嗎?

    Pytorch 與 Visionfive2 兼容嗎? $ pip3 install torch torchvision torchaudio --index-url https
    發(fā)表于 02-06 08:28

    PyTorch 中RuntimeError分析

    ? 錯誤原因 這個 RuntimeError 是因為在 PyTorch 中,upsample_nearest2d_out_frame(最近鄰2D上采樣)操作尚未對 BFloat16 數(shù)據(jù)類型提供
    發(fā)表于 03-06 06:02

    Pytorch模型訓(xùn)練實用PDF教程【中文】

    、模型權(quán)及損失函數(shù)的變化。本教程適用讀者:想熟悉 PyTorch 使用的朋友;想采用 PyTorch 進行模型訓(xùn)練的朋友;正采用 PyTorch,但無有效機制去診斷模型的朋友;
    發(fā)表于 12-21 09:18

    PyTorch如何入門

    PyTorch 入門實戰(zhàn)(一)——Tensor
    發(fā)表于 06-01 09:58

    Pytorch AI語音助手

    想做一個Pytorch AI語音助手,有沒有好的思路呀?
    發(fā)表于 03-06 13:00

    如何安裝TensorFlow2 Pytorch

    如何安裝TensorFlow2 Pytorch
    發(fā)表于 03-07 07:32

    一文解構(gòu)PyTorch:深入了解PyTorch內(nèi)部機制

    PyTorch是一個較新的深度學(xué)習(xí)框架,主打動態(tài)網(wǎng)絡(luò)模型。相比其他同類框架,PyTorch提供一種較低級別的方法,對于更具備數(shù)學(xué)背景的用戶來講靈活性更強。
    的頭像 發(fā)表于 03-01 08:47 ?4761次閱讀
    一文解構(gòu)<b class='flag-5'>PyTorch</b>:深入了解<b class='flag-5'>PyTorch</b>內(nèi)部<b class='flag-5'>機制</b>

    一篇非常新的介紹PyTorch內(nèi)部機制的文章

    譯者序:這篇博文是一篇非常新的介紹PyTorch內(nèi)部機制的文章,作者Edward Z Yang來自于Stanford大學(xué),是PyTorch的核心開發(fā)者之一。文章中介紹了如何閱讀PyTorch
    的頭像 發(fā)表于 12-26 10:17 ?3171次閱讀
    一篇非常新的介紹<b class='flag-5'>PyTorch</b>內(nèi)部<b class='flag-5'>機制</b>的文章

    基于PyTorch的深度學(xué)習(xí)入門教程之PyTorch簡單知識

    本文參考PyTorch官網(wǎng)的教程,分為五個基本模塊來介紹PyTorch。為了避免文章過長,這五個模塊分別在五篇博文中介紹。 Part1:PyTorch簡單知識 Part2:PyTorch
    的頭像 發(fā)表于 02-16 15:20 ?2959次閱讀

    基于PyTorch的深度學(xué)習(xí)入門教程之PyTorch的自動梯度計算

    計算 Part3:使用PyTorch構(gòu)建一個神經(jīng)網(wǎng)絡(luò) Part4:訓(xùn)練一個神經(jīng)網(wǎng)絡(luò)分類器 Part5:數(shù)據(jù)并行化 本文是關(guān)于Part2的內(nèi)容。 Part2:PyTorch的自動梯度計算 autograd
    的頭像 發(fā)表于 02-16 15:26 ?2625次閱讀

    基于PyTorch的深度學(xué)習(xí)入門教程之使用PyTorch構(gòu)建一個神經(jīng)網(wǎng)絡(luò)

    ? ? ? ? 前言 本文參考PyTorch官網(wǎng)的教程,分為五個基本模塊來介紹PyTorch。為了避免文章過長,這五個模塊分別在五篇博文中介紹。 Part1:PyTorch簡單知識 Part2
    的頭像 發(fā)表于 02-15 09:40 ?2667次閱讀

    基于PyTorch的深度學(xué)習(xí)入門教程之PyTorch重點綜合實踐

    實例。該網(wǎng)絡(luò)有一個隱含層,使用梯度下降來訓(xùn)練,目標是最小化網(wǎng)絡(luò)輸出和真實輸出之間的歐氏距離。 目錄 Tensors(張量) Warm-up:numpy PyTorch:Tensors Autograd
    的頭像 發(fā)表于 02-15 10:01 ?2603次閱讀

    神經(jīng)網(wǎng)絡(luò)原理簡述—卷積Op求導(dǎo)

    目前主流的CNN訓(xùn)練框架,如pytorch、mxnet、tensorflow2.0中都已經(jīng)集成了autograd機制,自動求導(dǎo)的機制相較于傳統(tǒng)訓(xùn)練框架如caffe、te...
    發(fā)表于 02-07 11:29 ?0次下載
    神經(jīng)網(wǎng)絡(luò)原理簡述—卷積Op求導(dǎo)

    PyTorch顯存機制分析

    在分析PyTorch的顯存時候,一定要使用torch.cuda里的顯存分析函數(shù),我用的最多的是torch.cuda.memory_allocated
    的頭像 發(fā)表于 04-06 09:57 ?2261次閱讀

    PyTorch教程11.4之Bahdanau注意力機制

    電子發(fā)燒友網(wǎng)站提供《PyTorch教程11.4之Bahdanau注意力機制.pdf》資料免費下載
    發(fā)表于 06-05 15:11 ?0次下載
    <b class='flag-5'>PyTorch</b>教程11.4之Bahdanau注意力<b class='flag-5'>機制</b>