中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PyTorch 中自動求導機制的原理是什么

發布時間:2021-06-17 16:59:18 來源:億速云 閱讀:405 作者:Leah 欄目:開發技術

這篇文章給大家介紹PyTorch 中自動求導機制的原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

自動求導機制

從后向中排除子圖

每個變量都有兩個標志:requires_grad和volatile。它們都允許從梯度計算中精細地排除子圖,并可以提高效率。

requires_grad

如果有一個單一的輸入操作需要梯度,它的輸出也需要梯度。相反,只有所有輸入都不需要梯度,輸出才不需要。如果其中所有的變量都不需要梯度進行,后向計算不會在子圖中執行。

>>> x = Variable(torch.randn(5, 5))
>>> y = Variable(torch.randn(5, 5))
>>> z = Variable(torch.randn(5, 5), requires_grad=True)
>>> a = x + y
>>> a.requires_grad
False
>>> b = a + z
>>> b.requires_grad
True

這個標志特別有用,當您想要凍結部分模型時,或者您事先知道不會使用某些參數的梯度。

autograd是專門為了BP算法設計的,所以這autograd只對輸出值為標量的有用,因為損失函數的輸出是一個標量。如果y是一個向量,那么backward()函數就會失效。

model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():
  param.requires_grad = False
# Replace the last fully-connected layer
# Parameters of newly constructed modules have requires_grad=True by default
model.fc = nn.Linear(512, 100)

# Optimize only the classifier
optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)

上面的optim.SGD()只需要傳入需要優化的參數即可。

volatile

純粹的inference模式(可以理解為只需要進行前向)下推薦使用volatile,當你確定你甚至不會調用.backward()時。它比任何其他自動求導的設置更有效——它將使用絕對最小的內存來評估模型。volatile也決定了require_grad is False。

volatile不同于require_grad的傳遞。如果一個操作甚至只有有一個volatile的輸入,它的輸出也將是volatile。Volatility比“不需要梯度”更容易傳遞——只需要一個volatile的輸入即可得到一個volatile的輸出,相對的,需要所有的輸入“不需要梯度”才能得到不需要梯度的輸出。使用volatile標志,您不需要更改模型參數的任何設置來用于inference。創建一個volatile的輸入就夠了,這將保證不會保存中間狀態。

>>> regular_input = Variable(torch.randn(5, 5))
>>> volatile_input = Variable(torch.randn(5, 5), volatile=True)
>>> model = torchvision.models.resnet18(pretrained=True)
>>> model(regular_input).requires_grad
True
>>> model(volatile_input).requires_grad
False
>>> model(volatile_input).volatile
True
>>> model(volatile_input).creator is None
True

自動求導如何編碼歷史信息

每個變量都有一個.creator屬性,它指向把它作為輸出的函數。這是一個由Function對象作為節點組成的有向無環圖(DAG)的入口點,它們之間的引用就是圖的邊。每次執行一個操作時,一個表示它的新Function就被實例化,它的forward()方法被調用,并且它輸出的Variable的創建者被設置為這個Function。然后,通過跟蹤從任何變量到葉節點的路徑,可以重建創建數據的操作序列,并自動計算梯度。

variable和function它們是彼此不分開的,先上圖:

PyTorch 中自動求導機制的原理是什么

如圖,假設我們有一個輸入變量input(數據類型為Variable)input是用戶輸入的,所以其創造者creator為null值,input經過第一個數據操作operation1(比如加減乘除運算)得到output1變量(數據類型仍為Variable),這個過程中會自動生成一個function1的變量(數據類型為Function的一個實例),而output1的創造者就是這個function1。隨后,output1再經過一個數據操作生成output2,這個過程也會生成另外一個實例function2,output2的創造者creator為function2。

在這個向前傳播的過程中,function1和function2記錄了數據input的所有操作歷史,當output2運行其backward函數時,會使得function2和function1自動反向計算input的導數值并存儲在grad屬性中。

creator為null的變量才能被返回導數,比如input,若把整個操作流看成是一張圖(Graph),那么像input這種creator為null的被稱之為圖的葉子(graph leaf)。而creator非null的變量比如output1和output2,是不能被返回導數的,它們的grad均為0。所以只有葉子節點才能被autograd。

>>> from torch.autograd import Variable
>>> import torch
>>> x = Variable(torch.ones(2), requires_grad = >>> True)
>>> z=4*x*x
>>> y=z.norm()
>>> y
Variable containing:
 5.6569
[torch.FloatTensor of size 1]
>>> y.backward()
>>> x.grad
Variable containing:
 5.6569
 5.6569
[torch.FloatTensor of size 2]
>>> z.grad

>>> y.grad

Variable上的In-place操作

in-place計算,類似'+='運算,表示內部直接替換,in-place操作都使用_作為后綴。例如,x.copy_(y)

>>> a = torch.Tensor(3,4)
>>> a
 0 0 0 0
 0 0 0 0
 0 0 0 0
[torch.FloatTensor of size 3x4]
>>> a.fill_(2.5)  
 2.5000 2.5000 2.5000 2.5000
 2.5000 2.5000 2.5000 2.5000
 2.5000 2.5000 2.5000 2.5000
[torch.FloatTensor of size 3x4]
>>> b = a.add(4.0) 
>>> b
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
[torch.FloatTensor of size 3x4]
>>> a
 2.5000 2.5000 2.5000 2.5000
 2.5000 2.5000 2.5000 2.5000
 2.5000 2.5000 2.5000 2.5000
[torch.FloatTensor of size 3x4]
>>> c = a.add_(4.0) 
>>> c
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
[torch.FloatTensor of size 3x4]
>>> a
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
 6.5000 6.5000 6.5000 6.5000
[torch.FloatTensor of size 3x4]

在自動求導中支持in-place操作是一件很困難的事情,我們在大多數情況下都不鼓勵使用它們。Autograd的緩沖區釋放和重用非常高效,并且很少場合下in-place操作能實際上明顯降低內存的使用量。除非您在內存壓力很大的情況下,否則您可能永遠不需要使用它們。

限制in-place操作適用性主要有兩個原因:

1.覆蓋梯度計算所需的值。這就是為什么變量不支持log_。它的梯度公式需要原始輸入,而雖然通過計算反向操作可以重新創建它,但在數值上是不穩定的,并且需要額外的工作,這往往會與使用這些功能的目的相悖。

2.每個in-place操作實際上需要實現重寫計算圖。不合適的版本只需分配新對象并保留對舊圖的引用,而in-place操作則需要將所有輸入的creator更改為表示此操作的Function。這就比較棘手,特別是如果有許多變量引用相同的存儲(例如通過索引或轉置創建的),并且如果被修改輸入的存儲被任何其他Variable引用,則in-place函數實際上會拋出錯誤。

In-place正確性檢查

每個變量保留有version counter,它每次都會遞增,當在任何操作中被使用時。當Function保存任何用于后向的tensor時,還會保存其包含變量的version counter。一旦訪問self.saved_tensors,它將被檢查,如果它大于保存的值,則會引起錯誤。

關于PyTorch 中自動求導機制的原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乡宁县| 衡山县| 融水| 彭泽县| 措勤县| 承德市| 博罗县| 申扎县| 屏东市| 靖远县| 富锦市| 大荔县| 南木林县| 西盟| 乐业县| 象山县| 腾冲县| 团风县| 临安市| 塘沽区| 泌阳县| 大宁县| 衡东县| 安新县| 临颍县| 阳城县| 阳江市| 青海省| 宣化县| 明光市| 开江县| 平利县| 怀来县| 翼城县| 连城县| 从化市| 宜昌市| 新绛县| 武清区| 刚察县| 富蕴县|