본 글은 네이버 부스트 캠프 AI Tech 기간동안
개인적으로 배운 내용들을 주단위로 정리한 글입니다
본 글의 내용은 새롭게 알게 된 내용을 중심으로 정리하였고
복습 중요도를 선정해서 정리하였습니다
✅ Week 6
- autograd
- backward()
- grad
- zero()
- no_grad()
1. autograd
오늘은 모델 학습을 위해서 간단하게 알아보는 '알두면 쓸데가많은 신기한 잡학사전' pytorch Autograd에 대한 내용이다
많은 모델을 학습하다보면 맹목적으로 .backward()를 통해서 배치마다 모델의 역전파를 계산해서 가중치를 업데이트해주는 행동을 할때가 있다
이런경우 대부분 원리를 이해하기보다 원래 그런갑다 하는 마인드로 모델을 학습하게 될 수 있다
따라서 오늘은 이러한 부분에서 조금은 빠져나와서
근원적으로 Pytorch의 autograd가 어떠한 원리로 돌아가는지를
이해해보려고 한다
오히려 이러한 방법은 학습을 이해하는 것에 큰 도움을 줄 것이다
Pytorch는 Autograd를 지원해주는 프레임워크 or 라이브러리이다
쉽게 말해서 자동미분 즉, gradient를 계산해주는 기능을 갖고 있다
1.1 Backward()
자동미분을 계산하는 방법은 too easy하다 앞에서 언급했듯이 .backward()메소드를 활용해주기만하면된다
물론 직접 계산하는 방법도 구현할 수 있다
두 방법을 한번 비교해보자
#f(x) 식
y' = A*x + B
#1. error 및 loss 계산 (loss fn = MSE)
error = y - y' #실제값 - 예측값
loss = (error**2).mean() #MSE
#2. A와 B에 대한 gradient 계산
B_grad = -2 * error.mean()
A_grad = -2 * (x * error).mean()
## 이런 방법으로 직접 gradient를 계산할 수 있다
하지만 위의 방법은 매우 불편하다
모델이 깊어지거나 복잡해지면 수식을 직접 구현하는 것은 너무 어려운 일이기 때문이다
따라서 우리는 마법같은 한 문장으로 위를 수정할 수 있다
#앞에서 구한 loss에 .backward()메소드 사용
loss.backward()
여기서 한가지 참고할 만한 것은 .backward()를 사용하기 위해서는 일단 A와 B가 미분가능한 tensor여야한다
즉, tensor를 생성할 때 requires_grad = True로 설정되어 있어야한다
또한 단순히 .backward()를 사용할때는 사용하는 객체의 값이 scalar값이어야한다
만약 matrix객체에 backward를 사용하고 싶다면 scalar의 값으로 변환해주거나
x = torch.randn(2, 2, requires_grad=True)
y = x + 2
z = (y * y)
y.backward(z)
위의 식처럼 tensor.backward의 인자로 객체를 넣어주어야한다
backward의 작동원리는 간단하게 연결된 그래프 식을 따라가면서 미분가능한 대상의 tensor의 gradient를 계산해준다
물론 여기에는 chain rule를 사용하기 때문에 하나의 식으로 정리될 수 있다
1.2 grad
이렇게 계산된 gradient의 경우 우리가 지정했던 tensor에 저장되게 된다.
따라서 이를 확인하기 위해서는 .grad라는 메소드를 통해서 출력할 수 있다
A.grad
B.grad
#backward()된 gradient의 저장값이 출력된다
만약 위에서 정의한 식의 과정을 다시한번더 반복하면 어떻게 될까?
당연하게도 저장된 gradient가 증가하게 된다
지금의 상황에서는 x의 값에 변화를 주지 않기 때문에 저장된 gradient는 2배로 증가할 것이다
이말은 pytorch에서 gradient는 축적되는 원리로 구현되어 있다는 것이다
즉, 위의 과정을 반복하면 하는 만큼 계산되는 gradient는 축적되게 된다
이방법을 활용해서 적은 미니 배치를 활용하더라도 큰 크기의 미니 배치를 사용할 때의 성능을 낼 수 있다
즉, 가중치를 업데이트 해주는 과정을 매번의 batch마다 수행하는 것이 아니라
축적했다가 원하는 배치 만큼 돌았을 때 업데이트를 해주는 것이다
업데이는 방법은 뒤에서 나온다
1.3 zero()
앞에서 말했듯이 pytorch에서 grad는 계속해서 축적되게 된다
하지만 우리가 가중치를 grad를 통해서 업데이트를 하려면
새로운 배치에 들어갔을 때 이전의 배치의 결과가 영향을 주어서는 안된다
- 물론 이를 활용해서 앞에서 말한 작은 배치로 큰 배치 효과를 낼 때를 제외하고 말하는 것이다
따라서 새로운 배치에 들어갈때 이전 gradient를 초기화 해주어야한다
이럴때 사용되는 메소드가 zero()이다
tensor.grad.zero()를 통해서 gradient를 0으로 만들어주는 방법이 있을 수 있고
실제 모델의 학습 과정에서는 우리가 활용하는 optimizer에 .zero_grad()를 사용하는 방법이 있다
대부분의 학습에서는 optim.zero_grad()방법을 각 배치 마다 처음에 수행해준다
여기서 추가적으로 가중치 업데이트에 대해서 알아보자
앞에서 구한 loss와 gradient를 통해서 가중치를 업데이트 해주는 간단하다
실제 학습에서 우리가 사용하는 optimizer.step()을 활용하면 되기 때문이다
optimzer.step()
위에서 계사한 loss에대한 gradient를 업데이트 해준다
1.4 no_grad()
validation과정에서는 우리의 계산이 gradient에 영향을 주어서는 안된다
즉, 평가모드일 때는 모든 미분을 꺼두어야한 한다
이때 활용하는 방법이 no_grad()이다
with torch.no_grad():
##val
이방법을 사용하게 되면 autograd의 기능을 잠시 꺼두게 된다
따라서 연산속도와 메모리의 사용량도 증가한다
1.5 eval()
그리고 no_grad()와 함께 validation과정에서 자주 사용되는 코드가 eval()이다
이는 model.eval()로 활용되는데
model.eval()
쉽게 말하자면 normalization - bn, ln 등과 Dropout과 같이 학습과정에서만 사용되어야할 기능을 끄는 기능이다
즉, train mode에서 추론 mode로 변형시켜주는 것이다
오늘은 간단하게 pytorch의 autograd에 대해서 알아보았다
설명이 자세하지 않은 부분도 많았기 때문에 조금더 이해하고 싶은 신 분은
아래 레퍼런스 링크를 이용하길 바란다
Reference
'네이버 부스트캠프 🔗 > ⭐주간 학습 정리' 카테고리의 다른 글
[부스트 캠프]Week 6 회고 및 Week 7 목표정리 (0) | 2023.04.19 |
---|---|
[네이버 부스트 캠프 AI Tech]Focal Loss 그리고 Label Smoothing Loss, F1 Loss (0) | 2023.04.13 |
[부스트 캠프]Week 5 회고 및 Week 6 목표 정리 (0) | 2023.04.10 |
[네이버 부스트 캠프 AI Tech]3D Understanding (0) | 2023.04.06 |
[네이버 부스트 캠프 AI Tech]Multi Modal (0) | 2023.04.05 |