# 自動求導機制
# 自動求導機制
本說明將概述Autograd如何工作并記錄操作。了解這些并不是絕對必要的,但我們建議您熟悉它,因為它將幫助您編寫更高效,更簡潔的程序,并可幫助您進行調試。
## 從后向中排除子圖
每個變量都有兩個標志:`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
```
這個標志特別有用,當您想要凍結部分模型時,或者您事先知道不會使用某些參數的梯度。例如,如果要對預先訓練的CNN進行優化,只要切換凍結模型中的`requires_grad`標志就足夠了,直到計算到最后一層才會保存中間緩沖區,其中的仿射變換將使用需要梯度的權重并且網絡的輸出也將需要它們。
```
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)
```
### `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`。然后,通過跟蹤從任何變量到葉節點的路徑,可以重建創建數據的操作序列,并自動計算梯度。
需要注意的一點是,整個圖在每次迭代時都是從頭開始重新創建的,這就允許使用任意的Python控制流語句,這樣可以在每次迭代時改變圖的整體形狀和大小。在啟動訓練之前不必對所有可能的路徑進行編碼—— what you run is what you differentiate.
## Variable上的In-place操作
在自動求導中支持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 中文文檔
- 主頁
- 自動求導機制
- CUDA語義
- 擴展PyTorch
- 多進程最佳實踐
- 序列化語義
- torch
- torch.Tensor
- torch.Storage
- torch.nn
- torch.nn.functional
- torch.autograd
- torch.optim
- torch.nn.init
- torch.multiprocessing
- torch.legacy
- torch.cuda
- torch.utils.ffi
- torch.utils.data
- torch.utils.model_zoo
- torchvision
- torchvision.datasets
- torchvision.models
- torchvision.transforms
- torchvision.utils
- 致謝