[PyTorch] Autograd-01 : 기초사용법

olxtar·2022년 3월 17일
0

[PyTorch] Autograd

목록 보기
1/5
post-thumbnail


Autograd 기초개념 및 사용(1)

g=g(x)=2x3g = g(x) = 2x^3
h=h(x)=112xh = h(x) = \frac{1}{12}x

위와 같은 두 함수가 있음, 그리고 zz를 다음과 같이 정의한다면

z=h(g(x))z=h(g(x))

zzxx에 대하여 미분하면 Chain Rule에 의하여 아래와 같이 된다.

zx=zggx\frac{\partial z}{\partial x}={\color{red}\frac{\partial z}{\partial g}}\cdot{\color{blue}\frac{\partial g}{\partial x}}

zg=gh(g)=g112g=112{\color{red}\frac{\partial z}{\partial g}} = \frac{\partial}{\partial g}\cdot h(g)=\frac{\partial}{\partial g}\cdot\frac{1}{12}g=\frac{1}{12}
gx=xg(x)=x2x3=6x2{\color{blue}\frac{\partial g}{\partial x}}=\frac{\partial}{\partial x}\cdot g(x)=\frac{\partial}{\partial x}2x^3=6x^2

zx=1126x2=12x2\therefore\frac{\partial z}{\partial x}=\frac{1}{12}\cdot6x^2=\frac{1}{2}x^2



이를 PyTorch로 구현해보면 아래와 같다. (function들의 Operation은 다름)

# Settings
import torch

# Make input x
x = torch.randn(3,3, requires_grad=True)
print(x)

tensor([[ 0.4490, -0.7287, -1.2367],
        [ 1.0262,  0.3886, -1.2934],
        [ 0.2356, -1.5048,  0.1285]], requires_grad=True)

먼저 xx에 임의의 값을 가진 Tensor를 할당한다. requires_grad=True를 통해 해당 Tensor의 Gradient를 구할 준비를 한다.

[!] requires_grad=True를 통해 생성한 Tensor에 다른 Operation을 한 뒤 xx 변수에 할당하고 추후에 x.grad를 통해 Gradient를 불러올라고하면 오류난다.

[+] Tensor를 출력해보면 마지막에 requires_grad=True를 확인할 수 있다.





# Make function g
g = 2*(x**3)
print(g)
print(g.grad_fn)

tensor([[ 1.8108e-01, -7.7389e-01, -3.7829e+00],
        [ 2.1612e+00,  1.1733e-01, -4.3271e+00],
        [ 2.6150e-02, -6.8144e+00,  4.2403e-03]], grad_fn=<MulBackward0>)
<MulBackward0 object at 0x000001C028EE13D0>

gg function을 생성한다.

[+] gg function의 operation이 진행된 Tensor에 grad_fn을 붙이면 Multiply 연산이 진행되었다고 알려준다. MulBackward0 object




z = g/12
z.backward()

RuntimeError: grad can be implicitly created only for scalar outputs

[!] 최종으로 Gradient를 구할 값은 Scalar output이어야 한다. lossloss값!




z = g.sum()/12
print(z)

tensor(-1.1007, grad_fn=<DivBackward0>)
z.backward()
print(x.grad)
print( (x**2)/2 )

tensor([[0.1008, 0.2655, 0.7647],
        [0.5265, 0.0755, 0.8364],
        [0.0278, 1.1321, 0.0083]])
        
tensor([[0.1008, 0.2655, 0.7647],
        [0.5265, 0.0755, 0.8364],
        [0.0278, 1.1321, 0.0083]], grad_fn=<DivBackward0>)
g(x)=2x3g(x)=2x^3
                h(x)=112x\;\;\;\;\;\;\;\;h(x)=\frac{1}{12}\sum x
z=h(x)z = h(x)

zx=12x2\therefore\frac{\partial z}{\partial x}=\frac{1}{2}x^2

위의 코드와 수식처럼 z.backward()를 실행시키면 x.grad를 통해서 쉽게 gradient를 구할 수 있다. (zzxx에 대해 편미분한거)

Gradient는 기울기 값!
Gradient는 기울기 값!
Gradient는 기울기 값!







Autograd 기초개념 및 사용(2)

2022.03.25(Fri)

.backward()에 scalar 값 or 자기자신과 같은 shape의 gradient를 넘겨줘야하는가?


[+] arbitrary : adj. 임의의
[+] w.r.t : with respect to

torch.autograd provides classes and functions implementing automatic differentiation of arbitrary scalar valued functions. It requires minimal changes to the existing code - you only need to declare Tensor for which gradients should be computed with the requires_grad=True keyword.

.backward() : Computes the sum of gradients of given tensors with respect to graph leaves.

.grad() : Computes and returns the sum of gradients of outputs with respect to the inputs.

Keypoint : "Weight에 대한 Loss의 Gradient를 구해준다."

  Loss  weight\frac{\partial \;Loss}{\partial \;weight}


Code : .backward(gradient) 예시

import torch

x = torch.tensor( [[1,2,3,4]], dtype=torch.float32, requires_grad=True)
print(x)
>>>
tensor([[1., 2., 3., 4.]], requires_grad=True)


xx = x**2
print(xx)
>>>
tensor([[ 1.,  4.,  9., 16.]], grad_fn=<PowBackward0>)


xx2 = xx*2
print(xx2)
>>>
tensor([[ 2.,  8., 18., 32.]], grad_fn=<MulBackward0>)


xx2.backward( gradient = torch.tensor( [[1,0,0,0]] )
x.grad
>>>
tensor([[4., 0., 0., 0.]])


x.grad.data.zero_()             # gradient가 누적되므로 초기화! (안되는데?)



xx2.backward( gradient = torch.tensor( [[0,1,0,0]] )
x.grad
>>>
tensor([[0., 8., 0., 0.]])


...
...
...

[?]loss.backward()에서 loss는 Scalar 값이어야 할까?
[?] 또는 .backward( gradient = torch.tensor)와 같이 이러한 Tensor(vector)가 들어가면 왜 되는걸까?

\rightarrow 이어서... [Pytorch] Autograd - 02 : With Jacobian

profile
예술과 기술

0개의 댓글