딥러닝 이론에 대해서 공부 해 보신 분들은, 딥러닝의 핵심은 미분을 통해서 **손실 함수(loss function)**의 값을 최소화 하는 것을 알고 계실 겁니다. 그렇기 때문에 Deep Learning 연구 플랫폼인 Pytorch
에선, 당연하게도 행렬 미분을 위한 기능들을 Tensor
객체에 내장 시켜 놓았습니다. 한 번 알아볼까요?
첫 번째 방법은, Tensor
를 생성하기 위해 사용하는 함수들의 파라미터로 requires_grad=True
를 넘겨 주는 것 입니다.
입력
x = torch.ones(2, 2, requires_grad=True)
print(x)
출력
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
두 번째 방법은, 이미 생성된 Tensor
의 멤버 함수인 requires_grad_
를 이용하여 autograd
를 활성화 시키는 것입니다.
입력
x = torch.ones(2, 2)
x.requires_grad_(True)
print(x)
출력
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
**역전파 (Back Propagation)**를 시키는 방법은 생각보다 간단합니다. 최종 연산 된 Tensor
객체의 backward()
함수만 호출해 주면 됩니다.
그렇다면, 역전파를 시킨 후, 미분한 값을 알기 위해선, 어떻게 하면 될까요?
Tensor
객체로 연산을 끝낸 후, 마지막 연산 결과로 나온 Tensor
의 backward()
함수를 호출해 줍니다. backward()
함수의 파라미터 값으로는 d(최종결과 전 행렬)/d(최종결과 직전 행렬) 을 삽입해 줍니다. backward()
함수는 야코비안 행렬과 연쇄 법칙을 이용, 역전파를 통해 경사 하강법을 시도 하기 위해 사용합니다.Tensor
를 최초에 requires_grad=True
를 설정해준 Tensor
로 미분한 값을 알고 싶다면, 최초 Tensor
객체의 grad
속성을 통해 알 수 있습니다.입력
x = torch.ones(2, 2, requires_grad=True) # 최초 Tensor 객체
y = x + 2
z = y * y * 3
out = z.mean() # 미분 대상
out.backward() # out.backward(torch.tensor(1.)) 과 동일
print(x.grad) # dout/dx
출력
tensor([[4.5000, 4.5000],
[4.5000, 4.5000]])
out = z/4 = y * y * 3/4 = (x + 2)^2 * 3 / 4
이고, 이를 x에 대해서 미분하면
dout/dx = 3(2x + 4) / 4
입니다. x = 1일 경우 18 / 4 = 4.5 가 정답이므로, 잘 작동 하고 있다고 볼 수 있습니다.
주의: out에 한 연산은 스칼라 연산입니다. 행렬 곱등을 사용하지 않았습니다.
입력
x = torch.ones(2, 3, requires_grad=True) # 최초 Tensor 객체
y = torch.ones(3, 6)
z = x @ y # x @ y 행렬 곱, 더 이상 스칼라 값이 아니다.
out = z * 2
print(out)
out.backward(torch.ones(2, 6) * 2) # dout/dz
print(x.grad) # dout/dx
출력
tensor([[6., 6., 6., 6., 6., 6.],
[6., 6., 6., 6., 6., 6.]], grad_fn=<MulBackward0>)
tensor([[24., 24., 24.],
[24., 24., 24.]])
행렬 미분에 대해서 궁금한 점이 있다면, 해당 링크의 글을 참고 해 주시기 바랍니다.
autograd
연산과 별개로, 다른 연산을 통해서 테스트를 하고 싶을 때가 있을 수 있습니다. 이럴 때에는 두가지 방법이 있습니다.
torch.no_grad()
를 이용하여 연산하기.Tensor.detech()
를 이용하여, autograd
연산을 하지 않은 Tensor
복사하기.입력
x = torch.ones(2, 2, requires_grad=True)
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad(): # autograd 연산 생략
print((x ** 2).requires_grad)
print('')
y = x.detach() # autograd가 없이 내용물만 복사.
print(y.requires_grad)
print(x.eq(y).all()) # x와 y의 내용물은 같다.
출력
True
True
False
False
tensor(True)
다음 시간에는, 신경망 학습을 위한, torch.nn
모듈에 대해서 알아보겠습니다. 잘못된 내용이 있다면, 이메일 justkode@kakao.com 이나, 댓글을 통해 알려주세요!