No Limitation
[Deep Learning] Gradient Exploding Debugging 맨 땅에 헤딩하기 본문
참고했던 블로그들
도움 주셔서 감사합니다..!
https://sanghyu.tistory.com/87
https://eehoeskrap.tistory.com/582
https://programs.wiki/wiki/loss-is-always-nan-and-accuracy-is-always-a-fixed-number.html
https://www.dlology.com/blog/how-to-deal-with-vanishingexploding-gradients-in-keras/
https://whiteglass.tistory.com/1
https://randomwalk.tistory.com/14
https://bo-10000.tistory.com/113
현재 진행하고 있는 프로젝트에서
Anomaly Detection을 수행하기 위해 DeepSAD 모형을 열심히 돌리고 있었다.
DeepSAD을 돌리기 위해서는 Transfer learning을 통해 c를 도출하고 학습된 파라미터를 사용하게 된다.
열심히 하루 동안 pre-training을 시킨 모형을 바탕으로 Training을 다음과 같이 수행하려고 하는데 왠걸
log를 찍어보니 다음과 같이 loss가 nan이 되는 상황이 발생했다.
위 사진처럼 loss가 nan이 되는 경우도 있었고 아예 feature representation이 nan이 되는 경우도 있었다.
처음에는 뭐가 원인인지 막막해 이것저것 구글링을 통해 원인을 찾아보니 대부분 언급하는 내용이
- Batch Size를 줄여야 한다
- Learning Rate가 너무 높아서 그런다
였다. 물론 저 부분도 문제를 극복하는 데 사용될 수 있지만 본질적인 문제를 해결하기는 어려웠다.
구체적으로 필자가 사용한 코드는 다음과 같은데,
바로 저 feature 부분에서 nan이 발생하거나
loss에서 nan이 발생하는 경우였다.
처음에는 optimizer 자체가 SGD를 사용해서 발생하는 문제였겠다 싶어
Adam으로 바꾸고 실행을 했을 때 조금은 개선되는 듯 했으나 train_loader의 1만번째가 넘어가면서부터 (전체는 5만개) 다시 nan이 발생하기 시작했다.
뭐가 원인일까 조금 더 찬찬히 뜯어보니
가중치의 큰 변화가 있음을 확인할 수 있었다.
즉 초반에는 안정적인 가중치를 갖다가
나중에는 가중치가 너무 큰 값이 생기거나 (절대값), loss도 너무 커지는 문제가 발생하였다.
그래서 문제의 원인을 'Gradient Exploding'으로 보고
이를 적용해서 문제를 풀어보고자 하였다.
처음에 적용한 gradient clipping이다. max_norm은 5로 적용하였다.
하지만 다음과 같이 오히려 기울기가 소실하는 문제가 발생하였다.
그래서 평균적으로 형성되는 기울기 값을 바탕으로 max_norm을 100으로 주어서 계산하였다.
이 max_norm이 중요한 이유가 PyTorch의 경우 (-max_norm, max_norm)의 범위로 gradient를 clip해주기 때문이다.
이러한 것을 바탕으로 진행을 하고 보니
처음부터
마지막 5만번째까지 안정적으로 학습이 진행됨을 확인할 수 있었다..!
이렇게 직접 프로젝트를 하면서 이론으로만 가볍게 알았던 Gradient Clipping을 직접 적용하게 되어 기쁘기도 했고 문제를 스스로 풀게 되어서 더 기뻤던 것 같다..!
그러면 이제 이렇게 실제 문제를 풀 수 있는 이러한 Gradient Clipping은 어떠한 개념일지에 대해 살펴보자
일반적인 신경망 연산에서는 깊은 layer가 쌓일수록 가중치의 곱을 많이 수행하게 되는데 이런 경우 다음과 같이 가파른 지역에 다다르게 될 경우 역전파 시 update가 굉장히 크게 움직일 수 있다. 바로 위 그림처럼 갑자기 저렇게 급격하게 가중치가 업데이트 되는 경우가 존재할 수 있다. 마치 위 필자의 사례처럼 말이다.
이러한 경우는 특히 신경망이 반복되서 진행되는 RNN의 경우가 더 자주 발생하게 된다.
보통 이런 문제를 극복하기 위해 위에서 언급했든 learning rate을 조절하는 것인데 사실 계속해서 학습율을 낮추게 되면 local minima에 빠지게 되기 때문에 온전한 해결책이라고는 보기는 어렵다.
이런 경우 바로 Gradient Clipping이라는 것을 사용한다!
이 방법은 역전파를 수행할 때 gradient가 일정 임계값을 넘어서지 못하게 기울기 값을 자르는 방법이다.
구체적인 방법은 다음과 같이 수행된다.
즉 일반적으로 gradient를 구하게 되는데 만약 gradient가 일정 threshold를 넘게 되면 (필자가 위에서 이야기한 max_norm) gradient는 threshold*gradient/L2(gradient) 형태로 대체되게 된다. 즉 기울기가 폭주하는 것을 멈추게 해주는 방법이다.
필자의 경우도 이 gradient clipping과 adam 그리고 learning rate과 batch size를 조절하여 문제를 해결할 수 있었다.
비슷한 문제를 겪으시는 분들이 계시다면 이 포스팅이 도움이 되었으면 좋겠다.
긴 글 읽어주셔서 감사합니다!
'ML & DL & RL' 카테고리의 다른 글
[Deep learning] Generative Adversarial Networks (1) - GAN Intro, Wasserstein GAN (0) | 2022.05.19 |
---|---|
[Deep Learning] Variational Autoencoder (0) | 2022.05.18 |
[Deep Learning] Basic Algorithms for Gradient-based Optimization (0) | 2022.04.18 |
[Pytorch] Torchtext 튜토리얼 - '영어' (0) | 2022.03.04 |
[Pytorch] 자연어 처리 intro - 토큰화와 정수 인코딩 (0) | 2022.03.04 |