動手學深度學習v2-08-自動求導
阿新 • • 發佈:2021-10-05
自動求導
- 深度學習框架通過自動計算導數,即自動求導(automatic differentiation),來加快這項工作。
- 根據我們設計的模型,系統會構建一個計算圖,來跟蹤計算是哪些資料通過哪些操作組合起來產生輸出。
- 自動求導使系統能夠隨後反向傳播梯度
- 反向傳播只是意味著跟蹤整個計算圖,填充關於每個引數的偏導數。
1 向量鏈式法則
2 自動求導
2.1 自動求導的兩種模式
2.2 例子
- 建立變數x併為其分配一個初始值
import torch
x = torch.arange(4.0)
x
- x.grad來儲存梯度
標量函式關於向量 x 的梯度是向量,並且與 x 具有相同的形狀。
x.requires_grad_(True) # 等價於 `x = torch.arange(4.0, requires_grad=True)`
x.grad # 預設值是None
- 計算Y值
y = 2 * torch.dot(x, x)
y
- 呼叫反向傳播函式來自動計算y關於x每個分量的梯度,並列印這些梯度。
x是一個長度為4的向量
y.backward()
x.grad
- 我們知道關於x的梯度為4x,我們想要驗證梯度是否正確。
x.grad == 4 * x
2.3 非標量變數的反向傳播
- 計算批量中每個樣本單獨計算的偏導數之和
# 對非標量呼叫`backward`需要傳入一個`gradient`引數,該引數指定微分函式關於`self`的梯度。在我們的例子中,我們只想求偏導數的和,所以傳遞一個1的梯度是合適的 x.grad.zero_() y = x * x # 等價於y.backward(torch.ones(len(x))) y.sum().backward() x.grad
2.4 分離計算
- 我們可以分離y來返回一個新變數u,該變數與y具有相同的值,但丟棄計算圖中如何計算y的任何資訊。
下面的反向傳播函式計算z=u*x關於x的偏導數,同時將u作為常數處理,而不是z=x * x * x關於x的偏導數。
x.grad.zero_()
y = x * x
u = y.detach()
z = u * x
z.sum().backward()
x.grad == u
2.5 Python控制流的梯度計算
使用自動求導的一個好處是,即使構建函式的計算圖需要通過Python控制流(例如,條件、迴圈或任意函式呼叫),我們仍然可以計算得到的變數的梯度。
下面的程式碼中,while迴圈的迭代次數和if語句的結果都取決於輸入a的值
def f(a):
b = a * 2
while b.norm() < 1000:
b = b * 2
if b.sum() > 0:
c = b
else:
c = 100 * b
return c
- 計算梯度
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
- 驗證梯度是否正確
a.grad == d / a
3 小結
我們首先將梯度附加到想要對其計算偏導數的變數上。然後我們記錄目標值的計算,執行它的反向傳播函式,並訪問得到的梯度。