딥러닝 개요 - 과적합

김민석·2022년 4월 29일

과적합 : 훈련데이터에 대한 정확도는 높아지지만 새로운 데이터에선 정확하게 동작하지 않는 상태

이를 막는 방법

  1. 데이터 양 늘리기

데이터 양이 적을 때 데이터의 특정 패턴이나 노이즈까지 쉽게 암기하므로 과적합 발생이 쉽다.

만약 데이터의 양이 적다면 의도적으로 기존 데이터를 조금씩 변형하거나 추가하는 데이터 증식(또는 증강)을 사용하기도 한다. 이미지의 경우 데이터 증식이 많이 사용되는데 이미지를 돌리거나 노이즈를 추가하고 일부분을 수정하는 방식으로 증식, 텍스트의 경우 번역 후 재번역을 통해 새로운 데이터를 만들어내는 역변역의 방법이 있다.

  1. 모델의 복잡도 줄이기

은닉층의 수나 매개변수의 수로 결정되는 복잡도를 줄인다.

  1. 가중치 규제 적용하기(Regularization)

복잡한 모델을 간단하게 하는 방법으로 가중치 규제가 있다.
L1 규제 : 가중체 w들의 절대값 합계를 비용 함수에 추가.
L2 규제 : 모든 가중치 w들의 제곱합을 비용 함수에 추가.

L1 규제는 기존 비용함수에 모든 가중치에 대해 λw\lambda \mid w \mid를 더 한 값
L2 규제는 기존 비용함수에 모든 가중치에 대해 12λw2\frac{1}{2} \lambda w^2를 더 한 값

λ\lambda는 규제 강도를 정하는 하이퍼 파라미터이고 클 수록 매개 변수를 찾는 것보다 규제를 위해 추가된 항들을 작게 유지하는 것을 우선시한다는 의미.

이 두 식 모두 비용 함수를 최소화하기 위해서는 가중치 w들의 값이 작아져야 한다는 특징이 있다.

  • L1 규제로 예를 들어봅시다.
    L1 규제를 사용하면 비용 함수가 최소가 되게 하는 가중치와 편향을 찾는 동시에 가중치들의 절대값의 합도 최소가 되어야 한다. 이렇게 되면, 가중치 w의 값들은 0 또는 0에 가까이 작아져야 하므로 어떤 특성들은 모델을 만들 때 거의 사용되지 않게 된다.

H(X)=w1x1+w2x2+w3x3+w4x4H(X) = w_{1}x_{1} + w_{2}x_{2} + w_{3}x_{3} + w_{4}x_{4} 라는 수식이 있을 때 L1 규제를 사용하니 w3w_{3}가 0이 되었다면 이는 사실 모델의 결과에 별 영향을 주지 못하는 특성임을 의미.

L2 규제는 가중치들의 제곱을 최소화하므로 w의 값이 완전히 0이 되기보다는 0에 가까워지기는 경향을 띈다.
L1 규제는 어떤 특성들이 모델에 영향을 주고 있는지를 정확히 판단하고자 할 때 유용합니다.
만약, 이런 판단이 필요없다면 경험적으로는 L2 규제가 더 잘 동작하므로 L2 규제를 더 권장
인공 신경망에서 L2 규제는 가중치 감쇠(weight decay)라고도 부릅니다.

  1. 드롭아웃(Dropout)
    https://wikidocs.net/images/page/61374/드롭아웃.PNG![](https://velog.velcdn.com/images/dkdlwlswk/post/0d729dc1-9897-4125-b1c8-9db94476bbcf/image.png)

랜덤으로 뉴런의 일부를 사용하지 않는 경우.
케라스에선 아래의 방식으로 드롭아웃 사용

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dropout, Dense

max_words = 10000
num_classes = 46

model = Sequential()
model.add(Dense(256, input_shape=(max_words,), activation='relu'))
model.add(Dropout(0.5)) # 드롭아웃 추가. 비율은 50%
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5)) # 드롭아웃 추가. 비율은 50%
model.add(Dense(num_classes, activation='softmax'))

기울기 소실과 폭주

소실 : 역전파 과정에서 기울기가 점차 작아져 가중치가 업데이트 되지 않는 상태
폭주 : 반대로 기울기가 점차 커져 비정상적으로 큰 값이 되며 발산하는 상태

이를 막는 방법

  1. ReLU와 그 변형들
    기울기 소실을 완화하는 가장 간단한 방법은 은닉층의 활성화 함수로 시그모이드나 하이퍼볼릭탄젠트 함수 대신에 ReLU나 ReLU의 변형 함수와 같은 Leaky ReLU를 사용하는 것
  • 은닉층에서는 시그모이드 함수를 사용하지 마세요.
  • Leaky ReLU를 사용하면 모든 입력값에 대해서 기울기가 0에 수렴하지 않아 죽은 ReLU 문제를 해결합니다.
  • 은닉층에서는 ReLU나 Leaky ReLU와 같은 ReLU 함수의 변형들을 사용하세요.
  1. 그래디언트 클리핑(Gradient Clipping)
    기울기 값을 자르는 것. 기울기 폭주를 막기 위해 임계치만큼 크기를 감소(RNN에서 유용)
from tensorflow.keras import optimizers

Adam = optimizers.Adam(lr=0.0001, clipnorm=1.)
  1. 가중치 초기화(Weight initialization)

1) 세이비어 초기화(Xavier Initialization)

균등분포 또는 정규분포로 초기화 할 때 두 가지 경우로 나뉘며 이전 층 뉴런 개수와 다음 층 뉴런 개수를 가지고 식ㅇ을 세운다.

균등 분포를 사용하여 가중치를 초기화할 경우 다음과 같은 균등 분포 범위를 사용

WUniform(6nin+nout,+6nin+nout)W \sim Uniform(-\sqrt{\frac{6}{ {n}_{in} + {n}_{out} }}, +\sqrt{\frac{6}{ {n}_{in} + {n}_{out} }})

정규 분포로 초기화할 경우에는 평균이 0이고, 표준 편차 σ가 다음을 만족하도록 한다.
σ=2nin+noutσ=\sqrt{\frac { 2 }{ { n }_{ in }+{ n }_{ out } } }

세이비어 초기화는 여러 층의 기울기 분산 사이에 균형을 맞춰서 특정 층이 너무 주목을 받거나 다른 층이 뒤쳐지는 것을 막는다
세이비어 초기화는 시그모이드 함수나 하이퍼볼릭 탄젠트 함수와 같은 S자 형태인 활성화 함수와 함께 사용할 경우에는 좋은 성능을 보이지만, ReLU와 함께 사용할 경우에는 성능이 좋지 않음
ReLU 함수 또는 ReLU의 변형 함수들을 활성화 함수로 사용할 경우에는 다른 초기화 방법을 사용하는 것이 좋은데, 이를 He 초기화(He initialization)라고 한다.

2) He 초기화(He initialization)

He 초기화(He initialization)는 세이비어 초기화와 유사하게 정규 분포와 균등 분포 두 가지 경우로 나뉩니다. 다만, He 초기화는 세이비어 초기화와 다르게 다음 층의 뉴런의 수를 반영하지 않습니다. 전과 같이 이전 층의 뉴런의 개수를 ninn_{in} 이라고 해보자

He 초기화는 균등 분포로 초기화 할 경우에는 다음과 같은 균등 분포 범위를 가지도록 한다.
WUniform(6nin,  +6nin)W\sim Uniform(- \sqrt{\frac { 6 }{ { n }_{ in } } } , \space\space + \sqrt{\frac { 6 }{ { n }_{ in } } } )

정규 분포로 초기화할 경우에는 표준 편차 σ가 다음을 만족하도록 한다.
σ=2ninσ=\sqrt{\frac { 2 }{ { n }_{ in } } }

  • 시그모이드 함수나 하이퍼볼릭탄젠트 함수를 사용할 경우에는 세이비어 초기화 방법이 효율적입니다.
  • ReLU 계열 함수를 사용할 경우에는 He 초기화 방법이 효율적입니다.
  • ReLU + He 초기화 방법이 좀 더 보편적입니다.
  1. 배치 정규화(Batch Normalization)
    인공 신경망의 각 층에 들어가는 입력ㅇ을 평균과 분산으로 정규화하여 학습을 효율적으로 만든다.

1) 내부 공변량 변화(Internal Covariate Shift)
층 별로 입력 데이터 분포가 달라지는 형상

  • 공변량 변화는 훈련 데이터의 분포와 테스트 데이터의 분포가 다른 경우를 의미합니다.
  • 내부 공변량 변화는 신경망 층 사이에서 발생하는 입력 데이터의 분포 변화를 의미합니다.

2) 배치 정규화(Batch Normalization)

한 번에 들어오는 배치 단위로 정규화.
배치 정규화는 각 층에서 활성화 함수를 통과하기 전에 수행
요약하면 입력에 대해 평균을 0으로 만들고, 정규화를 합니다.
그리고 정규화 된 데이터에 대해서 스케일과 시프트를 수행합니다.
이때 두 개의 매개변수 γ와 β를 사용하는데, γ는 스케일을 위해 사용하고, β는 시프트를 하는 것에 사용하며 다음 레이어에 일정한 범위의 값들만 전달되게 합니다.

Input : 미니 배치 B={x(1),x(2),...,x(m)}B = \{{x}^{(1)}, {x}^{(2)}, ..., {x}^{(m)}\}
Output : y(i)=BNγ,β(x(i))y^{(i)} = BN_{γ, β}(x^{(i)})

μ_{B} ← \frac{1}{m} \sum_{i=1}^{m} x^{(i)} \text{ # 미니 배치에 대한 평균 계산}
σ^{2}_{B} ← \frac{1}{m} \sum_{i=1}^{m} (x^{(i)} - μ_{B})^{2}\text{ # 미니 배치에 대한 분산 계산}
\hat{x}^{(i)} ← \frac{x^{(i)} - μ_{B}}{\sqrt{σ^{2}_{B}+ε}}\text{ # 정규화}
y^{(i)} ← γ\hat{x}^{(i)} + β = BN_{γ, β}(x^{(i)}) \text{ # 스케일 조정(γ)과 시프트(β)를 통한 선형 연산}

  • εεσ2σ^{2}가 0일때, 분모가 0이 되는 것을 막는 작은 양수. 보편적으로 10510^{-5}
  • γγ는 정규화 된 데이터에 대한 스케일 매개변수로 학습 대상
  • ββ는 정규화 된 데이터에 대한 시프트 매개변수로 학습 대상
  • y(i)y^{(i)}는 스케일과 시프트를 통해 조정한 BNBN의 최종 결과

배치 정규화는 학습 시 배치 단위의 평균과 분산들을 차례대로 받아 이동 평균과 이동 분산을 저장해놓았다가 테스트 할 때는 해당 배치의 평균과 분산을 구하지 않고 구해놓았던 평균과 분산으로 정규화

  • 배치 정규화를 사용하면 시그모이드 함수나 하이퍼볼릭탄젠트 함수를 사용하더라도 기울기 소실 문제가 크게 개선됩니다.
  • 가중치 초기화에 훨씬 덜 민감해집니다.
  • 훨씬 큰 학습률을 사용할 수 있어 학습 속도를 개선시킵니다.
  • 미니 배치마다 평균과 표준편차를 계산하여 사용하므로 훈련 데이터에 일종의 잡음 주입의 부수 효과로 과적합을 방지하는 효과도 냅니다. 다시 말해, 마치 드롭아웃과 비슷한 효과를 냅니다. 물론, 드롭 아웃과 함께 사용하는 것이 좋습니다.
  • 배치 정규화는 모델을 복잡하게 하며, 추가 계산을 하는 것이므로 테스트 데이터에 대한 예측 시에 실행 시간이 느려집니다. 그래서 서비스 속도를 고려하는 관점에서는 배치 정규화가 꼭 필요한지 고민이 필요합니다.
  • 배치 정규화의 효과는 굉장하지만 내부 공변량 변화때문은 아니라는 논문도 있습니다. : https://arxiv.org/pdf/1805.11604.pdf

3) 배치 정규화의 한계

(1) 미니 배치 크기에 의존적
너무 작은 배치 크기에서는 잘 동작하지 않을 수 있다.

(2) RNN에 적용 어렵다
RNN은 각 시점마다 다른 통계치를 가진다. 이를 해결하기 위해 층 정규화 사용

  1. 층 정규화 (Layer Normalization)

우선 배치 정규화를 시각화
mm이 3이고 특성의 수가 4일 때의 배치 정규화

반면 층 정규화는

profile
데이터 사이언스를 공부하는 커피쟁이

0개의 댓글