---
# System prepended metadata

title: 'Pytorch 筆記 : 偏微分 ( 自動微分 )'
tags: [Pytorch 筆記]

---

###### tags: `Pytorch 筆記`
{%hackmd @kk6333/theme-sty1 %}
# Pytorch 筆記 : 偏微分 ( 自動微分 )

我們知道要更新神經網路參數時，
權重 $w$ 對 Loss 的偏微分是我們更新權重時的依據，也稱為梯度 grad
所以 pytorch 給了我們很方便的方法，來做偏微分，也稱為自動微分 Automatic Differentiation


```python=
y.backward()
```
只要用 backward 就可以對 y 中的變數進行偏微分
直接講很抽象，這邊利用兩個範例說明 pytorch 如何偏微分
<br>

---

### Example 1

我們要實作對以下公式做偏微分

:::info
$$y=x^2$$
偏微分後會變以下式
$$y=2x$$
:::

```python=
# 定義公式
def func(x):
    return x**2
    
x = torch.tensor( 3.0, requires_grad=True)
y = func(x)

# 對 y=x**2 進行 x 偏微分
y.backward()

print( y )         # 印出原 y
print( x.grad )    # 印出 x 的偏微分後的 y
```
會輸出
```
tensor(9., grad_fn=<PowBackward0>)    # 原 y      (3*3=9)
tensor(6.)                            # 偏微分後 y (3*2=6)
```

:warning: 記得在定義 tensor 時，要啟用 requires_grad 才能做偏微分

---
<br>

### Example 2

這次用比較複雜的公式，並將 x 換成 w 表示
:::info
$$y=2w_1w_2 + w_2*cos(w_1)$$

要分別對 $w_1, w_2$ 做偏微分

- $w_1$ 偏微分
$$y = 2w_2 - w_2*sin(w_1)$$

- $w_2$ 偏微分
$$y = 2w_1+cos(w_1)$$
:::

```python=
# 定義公式
def func(w):
    return 2*w[0]*w[1] + w[1]*torch.cos(w[0])

# 分別對 w[0], w[1] 偏微分後的公式
def g_func(w):
    return torch.tensor( [2*w[1]-w[1]*torch.sin(w[0]), 2*w[0]+torch.cos(w[0])] )

# w,y
w = torch.tensor([1.,1.], requires_grad=True)
y = func(w)


y.backward()     # 偏微分
print(y)         # 印出原 y
print(g_func(w)) # 印出理論上的偏微分 y
print(w.grad)    # 印出 torch 計算的偏微分 y
```
output
```
tensor(2.5403, grad_fn=<AddBackward0>)
tensor([1.1585, 2.5403])
tensor([1.1585, 2.5403])
```