Skip to content

[PyTorch] Getting Start: 自動求導

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

這基本上是比較簡單的求導,複雜點的,我們還是交給工具來計算吧!


Read More

Leave a Reply