回想一下2.4 節(jié),計算導數(shù)是我們將用于訓練深度網(wǎng)絡的所有優(yōu)化算法中的關(guān)鍵步驟。雖然計算很簡單,但手工計算可能很乏味且容易出錯,而且這個問題只會隨著我們的模型變得更加復雜而增長。
幸運的是,所有現(xiàn)代深度學習框架都通過提供自動微分(通常簡稱為 autograd )來解決我們的工作。當我們通過每個連續(xù)的函數(shù)傳遞數(shù)據(jù)時,該框架會構(gòu)建一個計算圖來跟蹤每個值如何依賴于其他值。為了計算導數(shù),自動微分通過應用鏈式法則通過該圖向后工作。以這種方式應用鏈式法則的計算算法稱為反向傳播。
雖然 autograd 庫在過去十年中成為熱門話題,但它們的歷史悠久。事實上,對 autograd 的最早引用可以追溯到半個多世紀以前(Wengert,1964 年)。現(xiàn)代反向傳播背后的核心思想可以追溯到 1980 年的一篇博士論文 ( Speelpenning, 1980 ),并在 80 年代后期得到進一步發(fā)展 ( Griewank, 1989 )。雖然反向傳播已成為計算梯度的默認方法,但它并不是唯一的選擇。例如,Julia 編程語言采用前向傳播 (Revels等人,2016 年). 在探索方法之前,我們先來掌握autograd這個包。
import tensorflow as tf
2.5.1. 一個簡單的函數(shù)
假設我們有興趣區(qū)分函數(shù) y=2x?x關(guān)于列向量x. 首先,我們分配x
一個初始值。
在我們計算梯度之前y關(guān)于 x,我們需要一個地方來存放它。通常,我們避免每次求導時都分配新內(nèi)存,因為深度學習需要針對相同參數(shù)連續(xù)計算導數(shù)數(shù)千或數(shù)百萬次,并且我們可能會面臨內(nèi)存耗盡的風險。請注意,標量值函數(shù)相對于向量的梯度x是向量值的并且具有相同的形狀x.
# Can also create x = torch.arange(4.0, requires_grad=True)
x.requires_grad_(True)
x.grad # The gradient is None by default
array([0., 1., 2., 3.])
Before we calculate the gradient of y with respect to x, we need a place to store it. In general, we avoid allocating new memory every time we take a derivative because deep learning requires successively computing derivatives with respect to the same parameters thousands or millions of times, and we might risk running out of memory. Note that the gradient of a scalar-valued function with respect to a vector x is vector-valued and has the same shape as x.
array([0., 0., 0., 0.])
Array([0., 1., 2., 3.], dtype=float32)
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 1., 2., 3.], dtype=float32)>
Before we calculate the gradient of y with respect to x, we need a place to store it. In general, we avoid allocating new memory every time we take a derivative because deep learning requires successively computing derivatives with respect to the same parameters thousands or millions of times, and we might risk running out of memory. Note that the gradient of a scalar-valued function with respect to a vector x is vector-valued and has the same shape as x.
我們現(xiàn)在計算我們的函數(shù)x
并將結(jié)果分配給y
。
tensor(28., grad_fn=<MulBackward0>)
我們現(xiàn)在可以通過調(diào)用它的方法來獲取y
關(guān)于的梯度。接下來,我們可以通過的 屬性訪問漸變。x
backward
x
grad
tensor([ 0., 4., 8., 12.])
array(28.)
We can now take the gradient of y
with respect to x
by calling its backward
method. Next, we can access the gradient via x
’s grad
attribute.
[09:38:36] src/base.cc:49: GPU context requested, but no GPUs found.
array([ 0., 4., 8., 12.])
Array(28., dtype=float32)
We can now take the gradient of y
with respect to x
by passing through the grad
transform.
from jax import grad
# The `grad` transform returns a Python function that
# computes the gradient of the original function
x_grad = grad(y)(x)
x_grad
Array([ 0., 4., 8., 12.], dtype=float32)
<tf.Tensor: shape=(), dtype=float32, numpy=28.0>
We can now calculate the gradient of y
with respect to x
by calling the gradient
method.
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([
評論
查看更多