[딥러닝] DNN의 고질적 문제와 해결 방안

김대웅·2024년 4월 10일

Deep Learning

목록 보기
5/16
post-thumbnail

목표

면접에서 내기 딱 좋은 DNN의 고질적 문제와 이에 대한 해결 방안에 대해 알아보자!

이 강의는 혁펜하임님의 AI DEEP DIVE 강의를 기반으로 작성함.

직관적으로 이해하는 Vanishing Gradient

DNN을 무턱대고 깊게 깊게 만들면 다음과 같은 문제들이 발생한다고 한다!

  1. Vanishing Gradient 문제가 발생할 것.
  2. loss landscape가 꼬불꼬불해지는 문제가 발생. (loss landscape는 loss 함수가 생긴 개형을 의미.)
  3. Overfitting 문제가 발생할 것.

위 문제들에 대해 자세히 차근차근 알아가보자!

Vanishing Gradient

그라디언트가 사라진다는 의미이다..! 그라디언트가 사라진다는 의미를 바로 설명해보겠다!
다음 그림을 보자.
위와 같은 DNN을 MSE로 loss 함수를 삼고 가중치 업데이트를 한다고 하면 웨이트만 존재한다고 했을 때, 21개의 웨이트만 편미분해서 업데이트 해주면 된다!

그러나, 위의 과정 중에 입력값 부분에서 미분을 하면 미분값이 0에 수렴하게 된다..!
즉, layer가 많으면 입력 층에 가까울수록 미분이 사라진다..!
그 이유는 다음과 같다.
위의 미분을 구하는 것은 backpropagation으로 '액웨액웨액엔'의 과정을 거친다!
그리고 여기서 '액'이라는 f(x)f'(x)가 vanishing gradient 문제를 야기한다.
f(x)f(x)가 sigmoid인 이 상황에서 f(x)=(11+ex)f'(x) = (\frac{1}{1+e^x})'의 미분값은 가장 커봐야 14\frac{1}{4}이다.
물론 최고로 클 때가 그렇고, 실제로는 더 작은 값이라 '액'이 많이 곱해질수록 편미분값은 더더욱 작아진다.
(출력층과 가까운 부분은 '액엔'이지만, 입력층과 가까운 부분은 '액'이 무려 세 번 들어간다..!)
그리고 이러한 Vanishing Gradient의 주범'sigmoid'이다..

Vanishing Gradient의 문제 상황은 다음과 같이 발생한다.
Gradient가 0에 수렴 \rightarrow Update X \rightarrow 앞단에 이상한 weight 발생
이것이 깊은게 오히려 독이 된다는 것이다.

직관적으로 말하자면, 앞의 데이터를 망쳐놓으면... 뒤에서 손 쓸 방법이 없다는 것..!
이것은 오히려 underfitting 된다고 말할 수 있다.


Vanishing Gradient 문제 해결 방안인 ReLU

그렇다면 위의 글을 읽었을 때, Vanishing Gradient를 해결할 수 있는 가장 확실한 방법이 무엇일까?
바로 '액'을 sigmoid가 아닌 다른 것으로 바꾸는 것이다!
그리고 이 바꾸는 대상은 ReLU (Rectified Linear Unit)이다!!
ReLU 그래프를 보면 다음과 같다.
위와 같이 들어가는 축, 나가는 축이 있을 때, 양수쪽은 Linear처럼 들어간 값이 그대로 나가고, 음수쪽은 0이 나가는 함수이다!
이 함수를 사용했을 때, 미분하면 양수 쪽은 1, 음수 쪽은 0이 나온다.
그러기에 항상 14\frac{1}{4}보단 크므로 Vanishing Gradient 문제가 야기되지 않는다!

하지만.. ReLU도 문제점이 보이는데,
만약 들어가는 값이 음수이면 미분값은 0이 되어 해당 편미분 값은 사라질 수 있다..!
(물론 노드와 layer가 많기에 편미분을 할 때, 고려해야 할 Path가 많으므로 그런 상황이 안 나올 때도 있음.)
위와 같은 문제를 해결하기 위해 다음과 같은 ReLU의 변형 함수가 있다!
위 함수에서 Reaky ReLU는 기울기를 0.01로 잡은 함수이고,
Parametric ReLU는 기울기 a를 파라미터로 삼아 학습시킨다!!
그리고 기울기 a의 경우 미분이 되기 때문에 당연히 학습이 가능한 파라미터라고 할 수 있다.
이렇게 음수 쪽의 기울기도 0에서 바꾸면서 위의 문제점을 해결할 수 있었다!!

그리고 ReLU의 성능이 너무 좋았어서 그런가 아래 그림처럼 다른 변형 함수들도 많이 생겨났다! 위의 함수들은 너무 값이 작은 것들을 대비하여 변화를 준 것으로 확인할 수 있다.


Vanishing Gradient 문제 해결 방안인 BN( Batch Normalization )

Vanishing Gradient를 해결하는 방안 중 하나인 BN에 대해서 알아보자!
일단 Batch size를 node에 적용하면 다음과 같다.
위처럼 batch size가 5이면 입력으로 5개가 들어가고, 결과값으로 5개가 나올 것이다!
그리고 activation이 ReLU이면 다음과 같이 들어갈 것이다.
그런데, 여기서 만약 들어가는 값들이 모두 양수나 음수 쪽에 치우쳐져 있으면 어떻게 될까?
양수 쪽이면 미분 값이 1이기에 vanishing gradient가 일어나지는 않겠지만, non-linear하지 않아서 깊어지는 효과를 볼 수 없다.
음수 쪽은 더 심각한데, non-linear한 것은 물론이고, 미분 값이 0이기에 최적화가 되지 않아 ReLU임에도 vanishing gradient가 일어날 것이다.

그러므로 적절한 위치가 필요한데..! 이를 위해 '재배치'를 해주어서 해결해보는 것이다!
위 말은 재배치를 통해 입력값들의 순서와 입력값 사이사이의 비율은 건들지 않고 오로지 입력값들의 평균과 분산을 조절하여 vanishing gradient도 해결하고 non-linear하게 만들어 주도록 하자는 것이다!!

그렇다면 적절하게 평균이 0이고 분산이 1이게 Normalization하면?
위의 그림처럼 되고, non-linear한 것도 잘 있으면서, vanishing gradient도 적절하게 막아주게 된다.

[*] 여기서 입력값 집단인 XX를 평균을 0, 분산을 1로 만드는 방법은?
\rightarrow 평균은 XXˉX-\bar X (Xˉ\bar X는 X의 평균)을 해주면 0이 나오고, 분산은 XXˉσX\frac{X-\bar X}{\sigma_X}로 해주면 된다!!

다만 위와 같이 평균 0, 분산 1로 만들어주는 것은 ReLU에선 나쁘지 않을 수 있지만, sigmoid의 경우에선 0 부분에서 linear하기 때문에 깊어지는 효과를 보기 힘들다...

결국, 여러 activation에 대해 우리가 스스로 정확히 어디에, 어느 정도로 퍼뜨릴지 결정하기 어렵다..!

그렇기에! 방법으로 해당 node에 대해
non-linearity를 얼마나 살리면서, vanishing gradient를 얼마나 해결할지 AI한테 학습시키는 것이다!
그리고 이것이 Batch Normalization이다!

즉, 어디에(평균) 어느 정도로 퍼뜨릴지(분산) 학습하자는 것!!
방법은 다음과 같다.

위에서 XXˉσX\frac{X-\bar X}{\sigma_X}으로 하면 평균이 0, 분산이 1로 Normalization된다.
그리고 여기서 a(XXˉσX)+ba(\frac{X-\bar X}{\sigma_X})+b를 하면 평균이 bb이고, 분산이 a2a^2으로 Normalization이 된다!!
그리고 a(XXˉσX)+ba(\frac{X-\bar X}{\sigma_X})+b를 미분을 해보면 aabb가 나오기에 backpropagation으로 최적화가 가능하다..!
그러므로 위 행위를 내가 적용하고 싶은 layer에 BN 파라미터를 추가하는 식으로 적용하면 된다!
(만약 한 layer에 node가 3개이면 파라미터를 6개 추가하면 된다..!)
이것이 BN이다.

[*] layer normalization?
\rightarrow 이것은 해당 node가 아닌 layer에 대해서 적용하는 것이다! 만약 위처럼 node가 3개이면 결과값이 3개로 나올 것이고, 이에 대해 전체적인 관점에서 학습을 진행하는 것이다! 위의 경우에선 평균 1개, 분산 1개로 파라미터 2개만 추가하면 될 것이다.
보통 CNN에선 batch normalization을 많이 쓰고, RNN에선 layer normalization을 많이 쓴다고 한다.

https://kwonkai.tistory.com/144
위의 둘의 차이점을 잘 설명한 글이여서 참조하였다!

결국 vanishing gradient 문제를 해결하기 위한 방안은 다음과 같다.

  1. ReLU로 바꾼다.
  2. Batch Normalization
  3. Layer Normalization

loss-landscape가 꼬불해지는 문제

위에서처럼 ReLU와 BN을 사용하면 vanishing gradient는 사라지고 적절한 크기의 gradient가 있게 된다..!
그러나.. 층을 깊게 만들면 또 underfitting 문제가 발생하게 되는데..!
(층이 깊을 수록 loss 함수 모양이 복잡해지면서 underfitting이 일어나게 되는 것!)
위의 논문을 보면 층이 깊어질수록 error가 줄어드는 한계점이 높아지는 것을 볼 수 있다. 그리고 논문에서는 이에 대해 vanishing gradient 문제는 아니라고 한다..!

그래서 위의 문제를 해결하기 위해 대표적인 해결 방안으로 나온 것이
바로 Resnet의 skip-connection이다!

바로 알아보자면 다음 그림과 같다.
위처럼 layer를 하나 skip하면서 다다음 layer로 출력을 전달해주고, 다음 layer의 출력과 합한다.
그리고 이를 계속 반복하는 것이다!
(이는 위의 모양처럼 반복이 되고, 중간에 끼인 것은 skip-connection이 되지 않는다.)
그리고 이렇게 했을 때, 아래의 그림의 효과가 있다!

왼쪽을 보면 landscape가 너무 꼬불꼬불해서 잘못된 길로 빠지기 쉬운데, skip-connection을 사용하면 오른쪽처럼 편안한 landscape로 나타낼 수 있다!! 그리고 이를 통해 underfitting이 개선된다!

[*] 그런데 위의 개형은 어떻게 나타낸걸까..?
\rightarrow 이 질문이 나온 이유는 웨이트가 엄청나게 많은데 이를 단 3차원으로 어떻게 표현했을까에 대한 질문이다!
이를 간단히 설명하자면 다음과 같은 방법으로 표현한 것이다!
일단 웨이트들을 한 행렬로 모아 wˉ\bar w를 만들고, 가우시안 랜덤으로 bˉ1\bar b_1, bˉ2\bar b_2를 만들었다.
그리고 이를 wˉ+abˉ1+bbˉ2\bar w + a \cdot\bar b_1 + b \cdot\bar b_2 (a,ba, b는 임의의 수)로 loss 함수를 만들어서 aabb에 따른 wˉ\bar w의 개형으로 나타낸 것이다!


Overfitting 문제

Overfitting 문제는 다음 키 몸무게 그래프로 잘 설명할 수 있다.
트레이닝을 진행할 때, 데이터에 대해 선형적으로 보자면 파란색으로 나오고 깊은 DNN으로 loss를 0으로 만든다면 빨간색으로 나올 것이다.
그리고 이에 대해 노란색 데이터로 테스트를 진행하면 깊은 DNN으로 만든 함수가 오히려 더 큰 loss를 보이는 것을 알 수 있다.
결국 overfitting 문제는 Training 때는 잘하지만 Test 때는 못하는 것을 의미한다!
그렇다면 이를 해결할 방법은 무엇이 있을까?

  • 모델 경량화

모델을 복잡하지 않도록 경량화시키는 방법이 있다. 위의 경우 DNN을 사용하지 않고 선형 함수를 사용하면 해결이 될 수 있다!!

  • Data augmentation

Overfitting 문제는 데이터가 많아지면 해결이 되는데, 우리가 학습시킬 데이터가 한정적일 때,
Data augmentation을 사용할 수 있다!
Data augmentation은 한 데이터를 편집하여 여러 개의 데이터로 만드는 것을 말하는데, 예를 들자면 강아지 고양이 판별 학습에 대해 강아지 사진을 자르고.. 키우고.. 색깔 바꾸고.. 채도 바꾸고.. 돌리고.. 좌우 반전 상하 반전하고.. 등등 방법으로 여러 개의 데이터로 확장하는 것을 의미한다!

  • Dropout

Dropout는 랜덤하게 노드를 가리면서 학습하는 것을 의미한다.
이는 서로 다른 thinned network 여러 개를 사용해서 학습하는 것이다.
그리고 테스트 때에는 이를 평균내서 사용한다.

실제 사용 방법은 다음과 같다.
내가 dropout를 적용시키고 싶은 layer에 hyperparameter로 존재 확률 pp를 둔다. (이 pp는 layer마다 상이.)
그리고 데이터를 네트워크를 통과시킬 때마다 살릴(on) 노드를 다시 고른다.
(결국 데이터마다 다른 네트워크로 학습시키는 것.)

이렇게 트레이닝을 진행하고, 실제 테스트 때에는 모든 노드를 살리고 웨이트에 pp를 곱해서 테스트를 진행한다!!

Dropout은 위와 같은 방법으로 overfitting 문제를 해결하면서 각 노드에 대한 역할 분담을 잘하도록 만들어준다! (노는 노드가 없도록 한다!)

[*] dropconnect
\rightarrow dropconnect는 노드에 대한 연결들을 가려서 학습하는 것을 의미하는데, 이는 노드에 대한 연결들이 골고루 잘 학습에 도움을 주도록 한다!!

  • Regularization

웨이트에 크기가 너무 크면 함수가 과도하게 구불구불하게 나오게 되고, 이는 새로운 데이터에 대해 loss를 크게 만드는 overfitting 문제의 원인이 된다. 그래서 모델 경량화를 시키는 의의에서 Regularization을 한다.
그러므로 loss에 weight의 크기를 더해서 같이 고려하는 것이 Regularization이다!!
즉, Loss에 L+λzppL + \lambda\cdot\lVert z \rVert^p_p를 쓴다!
여기서 pp가 1이면 I1 - regularization( w1+w2+w3\vert w_1 \vert + \vert w_2 \vert + \vert w_3 \vert )이고, pp가 2이면 I2 - regularization ( sqrt(w1)2+(w2)2+(w3)2sqrt{(w_1)^2 + (w_2)^2 + (w_3)^2} )이다.
(그리고 pp에 대해 Ipp - regularization은 ((w1)p+(w2)p+(w3)p)1p)((\vert w_1 \vert)^p + (\vert w_2\vert)^p + (\vert w_3\vert)^p)^{1 \over p})로 나온다!)

여기서 λ\lambda가 너무 크면 LL이 줄어드는 것이 영향을 줄 수 없고, 너무 작으면 weight의 크기들이 줄어드는 것에 대해 영향을 줄 수 없기에 hyperparameter로 두어 적절한 크기의 양수값으로 λ\lambda를 조절해야 한다.

Regularization의 과정은 일단 처음엔 L을 많이 고려하다가 L을 어느정도 줄였으면 L이 너무 커지지 않는 선에서 w의 크기를 줄이게 된다. 이는 다음 그림과 같다.
그리고 Regularization을 직관적으로 설명하자면 쓸데없이 큰 애들을 망치도 두들겨 준다고 설명할 수 있다.
위처럼 웨이트의 크기가 있을 때, 이를 망치로 두들겨서 크기를 줄인다는 의미이다.
이는 I1인가 I2인가에 따라 학습의 차이를 보이는데, 이 차이는 다음과 같다.
1. I2의 경우
제곱이 되어있기에 웨이트를 편미분하여 업데이트를 하면 작은 값은 살살 때리고, 큰 값들은 팍팍 때린다! \rightarrow 이는 weight의 크기가 비슷비슷하게 만들어 주고, 결과적으로 node들이 편향되지 않고 골고루 사용되도록 만들어준다! (편식 X)
2. I1의 경우
I1은 절댓값으로 되어있어 편미분시 기울기가 1 or -1이다. 즉, 기울기가 일정하므로 작은 값이든 큰 값이든 똑같이 골고루 때린다.
\rightarrow 이는 몇개의 connect를 없애는 효과가 있다! 위의 예시 같은 경우 w2와 w4는 없어질 확률이 크다.
(이는 중요한 connect만 챙긴다는 마인드)
[*] 수학적으로 보면 MAP(Maximum A Posteriori)로 해석 가능하다.
(I2의 경우 Gaussian, I1의 경우 Laplacian으로 나온다.)

  • Validation data 기준, 가장 성능이 좋을 때의 모델을 저장한다.

Val loss는 train loss와 다르게 다시 loss가 올라가는 부분이 있는데, 이것이 바로 overfitting이 되는 부분이다. 그러므로 val loss가 가장 작을 때의 모델을 사용하는 것이 overfitting을 피하는 방법이 될 수 있다.


정리

  1. DNN을 무턱대고 깊게 만들면 Vanishing Gradient, Loss landscape, Overfitting 문제가 발생한다.
  2. Vanishing Gradient는 활성화 함수에서 미분값이 작아 입력층에 가면 그라디언트가 사라지는 문제이다. 이를 해결하는 방법은 ReLU, BN, LN이 있다.
  3. Loss landscape는 loss 함수에서 너무 길이 험해 잘못된 길에 빠지는 경우가 생겨 loss가 줄어드는 한계점이 생긴다는 문제이다. 이를 해결하는 방법은 resnet의 skip-connection이다.
  4. Overfitting은 Training은 잘하는데 Test를 못하는 것이다. 이것의 해결 방법은 모델 경량화, Data augmentation, dropout, dropconnect, regularization, Val loss가 최저일 때의 성능 쓰는 것이 있다.
profile
글쓰기에 미쳐보자

0개의 댓글