Last Updated on 2021-04-13 by Clay
自動求導的重要性,相信精通 Machine Learning 的大家想必一清二楚吧!我在此只簡單地說明,當然,如果我的說明有誤的那是一點兒也不奇怪的,就請各路大神不吝指導一下我吧。
基本上,建構深度學習模型分成 Forward propagation 以及 Backward propagation 兩部分。
在 PyTorch 中,forward propagation (正向傳播) 需要由使用者自己設置,好用來建構我們的模型層。計算到最後比較 Training data 的標準解答,我們會得到所謂的 Loss function (損失函數)。
而所謂的 Backward propagation (反向傳播),也就是通過向我們的 Loss function 求導,利用『梯度下降法』來更新我們模型的權重。
這樣一來,能夠讓我們的模型『自動求導』是一件多麼重要的事,想必就不言可喻了吧?
以下,我們就來看看該怎麼做來讓 PyTorch 自動求導吧?
我的筆記基本上與 PyTorch 官方的 Tutorial 相去不遠,應該說我就是照他們官往的教學下去學習的,在此強力推薦,真的寫得清楚明瞭: https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py
Autograd
首先,建立一個簡單地、只有 1 的 2x2 矩陣,設定『可以求導』(Default 是不能求導的)。
import torch a = torch.ones(2, 2, requires_grad=True) print('a:\n', a)
Output:
a:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
緊接著,我們將 a + 5,並賦值給 b 這個變數。
b = a + 5 print('b:\n', b) print('b grad:\n', b.grad_fn)
Output:
b:
tensor([[6., 6.],
[6., 6.]], grad_fn=<AddBackward0>)
b grad:
<AddBackward0 object at 0x7f7ae5fde80>
然後我們再繼續下一層的傳遞:將 b*b*2 賦值給變數 c:
c = b*b*2 out = c.mean() print('c:\n', c) print('c out:\n', out)
Output:
c:
tensor([[72., 72.],
[72., 72.]], grad_fn=<MulBackward0>)
c out:
tensor(72., grad_fn=<MeanBackward0>)
mean()
為求平均的 function,這裡我們可以看到 4 個值全部都是 72 的平均值還是 72。
接下來終於可以求導啦。假設變數 out 就是我們最後的輸出、並且 out 只包含一個數值:
print('a grad:\n', a.grad) out.backward() print('a grad:\n', a.grad)
Output:
a grad:
None
a grad:
tensor([[6., 6.],
[6., 6.]])
由於我們的 out 只有一個數值,故我們可以直接寫:
out.backward()
這個指令等同於:
out.backward(torch.tensor(1.))
最後我們為什麼會得到 a grad = [[6., 6.], [6., 6.]] 這樣的答案呢?
由於每個變數裡頭的數值都是固定的,所以我們可以簡化問題:
a = 1
b = a + 5
c = 2b^2
=> 1/4 * c' = 4b
=> c' = b
=> c' = a + 5
=> c' = 1 + 5 = 6
這基本上是比較簡單的求導,複雜點的,我們還是交給工具來計算吧!