딥러닝 이론에 대해서 공부 해 보신 분들은, 딥러닝의 핵심은 미분을 통해서 **손실 함수(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 이나, 댓글을 통해 알려주세요!