1. 程式人生 > 其它 >動手學深度學習v2-08-自動求導

動手學深度學習v2-08-自動求導

自動求導

  • 深度學習框架通過自動計算導數,即自動求導(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 小結

我們首先將梯度附加到想要對其計算偏導數的變數上。然後我們記錄目標值的計算,執行它的反向傳播函式,並訪問得到的梯度。