hyeonzzz's Tech Blog

[Andrew Ng] 딥러닝 2단계 : 2. 신경망 네트워크의 정규화 본문

Deep Learning/Basics

[Andrew Ng] 딥러닝 2단계 : 2. 신경망 네트워크의 정규화

hyeonzzz 2024. 1. 25. 11:48

1. 정규화

정규화 : 과적합(overfitting)을 줄이고 모델의 성능을 향상시키기 위한 여러 기법

높은 분산으로 신경망이 과대적합하는 문제가 의심된다면 가장 처음 시도해야 할 것은 정규화이다.

더 많은 훈련 데이터를 얻는 것은 비용이 많이 들어가게 되므로 정규화를 시도한다.

<정규화 작동 방법>

L2 정규화를 훨씬 더 많이 사용한다

L2 정규화 - 로지스틱 회귀를 사용해 아이디어를 발전시켜 보겠다. 로지스틱 회귀는 비용 함수 J를 최소화하는 것이다. 즉, 훈련 샘플의 개별적인 예측의 손실에 관한 함수이다. 로지스틱 회귀에 정규화를 추가하기 위해서 정규화 매개변수라고 부르는 λ를 추가해야 한다. λ를 2m으로 나누고 w 제곱의 노름을 곱해준다. w 제곱의 노름은 j의 1부터 nx까지 wj^2의 값을 더한 것과 같다. w의 전치행렬 곱하기 w와도 같다. 매개변수 벡터 w의 유클리드 노름의 제곱이다.

b를 추가하지 않는 이유는 w는 많은 매개변수를 갖지만 b는 하나의 숫자이기 때문에 넣어도 실질적인 차이가 없기 때문이다.

L1 정규화 - L2 노름 대신에 λ를 2m으로 나눈 값에 |w|의 합을 더해준다. L1 정규화를 사용하게 되면 w는 희소해지는데 이는 w 벡터 안에 0이 많아진다는 의미이다. 특정 매개변수가 0일 경우 메모리가 적게 필요하기 때문에 어떤 사람들은 이것이 모델을 압축하는데 도움이 된다고 말한다. 그러나 모델을 희소하게 만들기 위해 L1 정규화를 사용하는 것은 큰 도움이 되지 않는다. 모델을 압축하겠다는 목표가 있지 않는 이상 이 정규화를 많이 사용하지 않는다. 

λ : 정규화 매개변수. 다양한 값을 시도해 과대적합을 막을 수 있는 최적의 값을 찾는다.

 

신경망은 어떨까?

신경망에는 비용 함수가 있다. 모든 파라미터 w^[1], b^[1]부터 w^[L], b^[L]까지의 매개변수를 갖는 함수이다. L은 신경망에 있는 층의 개수이다. 따라서 비용함수는 훈련 샘플의 m까지의 손실의 합을 m으로 나눈 값이다. 여기에 정규화를 더하기 위해 λ를 2m으로 나눈 값 곱하기 매개변수 w 노름 제곱의 모든 값을 더해준다. 즉 노름의 제곱은 i와 j에 해당하는 각각의 행렬의 원소를 제곱한 것을 모두 더해준 값이다. w는 (n^[l], n^[l-1]) 차원의 행렬이기 때문에 i는 1부터 n^[l]이고 j는 1부터 n^[l-1]까지로 한다. 이것은 해당 층 l-1과 l의 은닉 유닛의 개수를 나타낸다. 따라서 이 행렬의 노름은 프로베니우스 노름 (= 행렬의 원소 제곱의 합)이라고 부른다. 아래 첨자에 F를 표시해준다. 

이것으로 경사 하강법을 어떻게 구현할까?

전에는 역전파의 dw를 계산했다. 역전파는 w에 대응하는 J의 편미분 값을 제공했다. 그리고 w^[l]을 w^[l] 빼기 학습률 곱하기 dw^[l]로 업데이트했다. 여기에 정규화 항을 더해주면 dw^[l]에 λ 나누기 m 곱하기 w^[l]을 더해준다. 그리고 이 값을 전과 같은 방식으로 계산한다. 이 새로운 dw^[l]의 정의는 여전히 비용함수의 미분에 대한 올바른 정의이다. 

L2 정규화는 가중치 감쇠라고 불리기도 한다. 1보다 살짝 작은 값을 가중치 행렬에 곱해준다는 이유에서 나온 이름이다. 이유를 자세히 알아보면 

dw^[l]의 정의를 아래에 적용시키면 w^[l]은 w^[l]에 학습률 α 곱하기 역전파에서 온 것들 더하기 λ를 m으로 나눈 값 곱하기 w^[l]이 된다. 이 값은 w^[l] 빼기 αλ 나누기 m 곱하기 w^[l] 빼기 α 곱하기 역전파에서 얻은 값들이다. 이 항은 행렬 w^[l]이 어떤 값이든 값이 약간 더 작아진다는 것을 보여준다. w^[l] 행렬의 값에 (1 -αλ/m)을 곱해준 것과 같다. 따라서 행렬 w^[l]의 값보다 더 작아지게 된다. 

 

 

2. 왜 정규화는 과대적합을 줄일 수 있을까?

왜 정규화가 과대적합을 해결하고 분산을 줄이는데 도움이 될까?

직관 1)

과대적합 문제가 있는 신경망을 생각해보자. w와 b에 대한 비용함수 J는 1부터 m까지 손실의 합과 같다. 가중치 행렬이 너무 커지지 않도록 정규화를 위해 추가적인 항을 더해주었다. 이것을 프로베니우스 노름이라고 부른다. 매개변수의 L2 혹은 프로베니우스 노름을 줄이는 것이 왜 과대적합을 줄일 수 있을까?

정규화에서 λ를 크게 만들어서 가중치 행렬 w를 0에 상당히 가깝게 설정할 수 있다. 따라서 많은 은닉 유닛을 0에 가까운 값으로 설정해서 은닉 유닛의 영향력을 줄이게된다. 그런 경우에 훨씬 더 간단하고 작은 신경망이 될 것이다. 로지스틱 회귀 유닛에 가까워진다.  중간의 딱 맞는 경우와 가깝게 하는 적절한 λ값을 찾는게 좋다. 간단한 네트워크는 과대적합 문제가 덜 일어난다. 

직관 2)

tanh 활성화 함수를 사용한다고 가정해보자. z가 아주 작은 경우에는 tanh 함수의 선형 영역을 사용하게 된다. z의 값이 더 작아지거나 커지면 활성화 함수는 선형을 벗어나게 된다. 여기서 얻어낼 수 있는 직관은 정규화 매개변수인 λ가 커질 때 비용 함수가 커지지 않으려면 상대적으로 w가 작아질 것이다. 가중치 w^[l]이 작으면 z^[l] = w^[l]a^[l-1]+b^[l]과 같기 때문에 w가 작으면 z도 상대적으로 작은 값을 가지게 된다. z가 상대적으로 작은 값을 갖게 되면 g(z)는 거의 1차원 함수가 된다. 따라서 모든 층은 선형 회귀처럼 거의 직선의 함수를 갖게 된다. 강의 1에서 봤듯이 모든 층이 선형이면 전체 네트워크도 선형이다. 따라서 매우 복잡한 결정, 비선형 결정의 경계에 맞추기는 불가능하다. 높은 분산의 경우처럼 과대적합된 데이터 세트까지 맞추기는 어렵다.

정리하자면 λ가 매우 크면 w는 매우 작다. 또한 z의 값도 상대적으로 작아져 tanh의 경우 활성화 함수는 선형이 된다. 따라서 과대적합의 가능성이 줄어든다. 

 

 

3. 드롭아웃 정규화

<드롭아웃 작동 방법>

왼쪽처럼 과적합한 신경망을 훈련시키는 경우를 생각해보자. 드롭아웃의 방식은 신경망의 각각의 층에 대해 노드를 삭제하는 확률을 설정하는 것이다. 

각각의 층에 대해 각각의 노드마다 동전을 던지면 0.5의 확률로 해당 노드를 유지하고 0.5의 확률로 노드를 삭제하게 된다. 동전을 던진 후 다음과 같이 노드를 삭제했다고 해보자. 그 후 삭제된 노드의 들어가는 링크와 나가는 링크를 모두 삭제한다. 그럼 더 작고 간소화된 네트워크가 된다. 그럼 이 감소된 네트워크에서 하나의 샘플을 역전파로 훈련시킨다.

다른 샘플에 대해서도 다른 세트의 노드들을 삭제하게 된다. 그럼 각각의 훈련 샘플에 대해서 감소된 네트워크를 사용해 훈련시키게 된다. 

정방향 전파와 역방향 전파시 같은 뉴런이 드롭아웃되는가?
정방향 전파 시 특정 뉴런 A가 드롭아웃 마스크에 의해 0으로 설정되었다면, 역방향 전파에서도 동일한 마스크가 적용되어 뉴런 A의 그래디언트는 계산되지 않는다. 이 과정은 동일한 샘플에 대해 정방향과 역방향 전파에서 일관성을 유지하기 위해 필요하다.

훈련샘플마다 동일한 뉴런이 드롭아웃 되는가?
훈련 샘플마다 동일한 뉴런이 드롭아웃 되는 것은 아니다. 각 훈련 샘플이 정방향 전파를 통과할 때마다 새로운 드롭아웃 마스크가 생성된다.

테스트 시에는 드롭아웃이 적용되지 않는가?
테스트 시에는 드롭아웃이 적용되지 않는다. 대신, 훈련 시 드롭아웃으로 인해 뉴런 출력이 낮아진 것을 보정하기 위해 각 뉴런의 출력에 드롭아웃 확률 p를 곱한 값이 사용된다. 예를 들어, p=0.5인 경우 테스트 시에는 각 뉴런의 출력이 0.5를 곱한 값으로 조정된다.

 

 

<역 드롭아웃>

층이 3인 경우를 예시로 들겠다.

먼저 층 3에 대한 드롭아웃 벡터인 벡터 d3를 설정한다. np.random.rand a3와 같은 모양을 가진다. 이 값이 keep_prob이라는 숫자보다 작은지 비교한다. 여기서는 0.8로 설정하겠다. 이 수는 주어진 은닉 유닛이 유지될 확률이다. keep_prob이 0.8이라는 것은 어떤 은닉 유닛이 삭제될 확률이 0.2라는 것이다. 따라서 d3는 각각의 샘플과 각각의 은닉 유닛에 대해 0.8의 확률로 대응하는 d3가 1(0.8보다 작음)의 값을 가지고 0.2의 확률로 0(0.8보다 작지않음) 의 값을 가지는 행렬이 된다. 

다음은 3번째 층의 활성화인 a3에 관한 코드를 작성하겠다. a3의 값은 예전 a3의 값에 요소별 곱셈으로 d3를 곱해준 것이다. a3 *= d3로 써줘도 된다. 모든 원소에 대해 20퍼센트의 확률로 0이 되는 d3의 원소를 곱해 대응되는 a3의 원소를 0으로 만들게 된다. 이것을 파이썬으로 구현한다면 d3는 True와 False의 값을 갖는 불 타입의 행렬이 된다. 그러나 0과 1이 아닌 불 타입의 값은 곱셈을 할 수 없게 된다. 

(역 드롭아웃 )최종적으로 얻은 a3를 0.8 keep_prob 매개변수로 나눠준다. 마지막 단계에 대한 설명을 하기 위해 세 번째 은닉 층에 50개의 유닛, 즉 50개의 뉴런이 있다고 해보자. 그럼 a3는 (50, 1) 차원이고 벡터화한다면 (50, m) 차원이다. 80퍼센트의 확률로 유지하고 20퍼센트의 확률로 삭제한다면 평균적으로 10개의 유닛이 삭제된다는 뜻이다. 즉, 0의 값을 갖게 된다. z^[4] = w^[4]*a^[3]+b^[4] 이다. 예상대로 이 값은 20퍼센트만큼 줄어들 것이다. 즉 a^[3] 원소의 20퍼센트가 0이 된다는 의미이다.

z^[4]의 기대값을 줄이지 않기 위해 이 값을 0.8로 나눠줘야 한다. 왜냐하면 필요한 20퍼센트 정도의 값을 다시 원래대로 만들 수 있기 때문이다. 이를 통해 a3의 기대값을 유지할 수 있다.   

keep_prob을 다시 나눠줌으로써 a3의 기대값을 같게 유지한다

 

d 벡터를 사용해 서로 다른 훈련 샘플마다 다른 은닉 유닛들을 0으로 만들게 된다. 같은 훈련 세트를 통해 여러 번 반복하면 그 반복마다 0이 되는 은닉 유닛은 무작위로 달라져야 한다. 따라서 하나의 샘플에서 계속 같은 은닉 유닛을 0으로 만드는 것이 아닌 경사 하강법의 하나의 반복마다 0이 되는 은닉 유닛들이 달라진다. 

 

<알고리즘의 훈련 후 테스트 시간에 하는 일>

예측을 하고 싶은 x = a^[0]라는 샘플이 주어진다. 테스트에서는 드롭아웃을 사용하지 않는다. 

z^[1] = w^[1]a^[0]+b^[1]

a^[1] = g^[1](z^[1])

z^[2] = w^[2]a^[1]+b^[2]

a^[2]도 같은 방식으로 설정한다. 마지막 층에 이르면 y의 예측값을 얻는다.

그러나 테스트에서는 드롭아웃을 사용하지 않는다. 왜냐하면 테스트에서는 예측을 하는 것이므로 결과가 무작위로 나오는 것을 원하지 않기 때문이다. 테스트에 드롭아웃을 구현하는 것은 노이즈만 증가시킬뿐이다. 

 

 

4. 드롭아웃의 이해

<드롭아웃이 잘 작동하는 이유>

단일 유닛의 관점에서 유닛이 해야 하는 일은 입력을 받아 의미있는 출력을 생성하는 것이다. 드롭아웃을 통해 입력은 무작위로 삭제될 수 있다. 따라서 왼쪽의 보라색 유닛은 어떤 특성에도 의존할 수 없다. 그 특성이 무작위로 바뀌거나 특성의 고유한 입력이 무작위로 바뀔 수 있기 때문이다. 즉 특정 입력에 유난히 큰 가중치를 부여하기가 꺼려지는 상황이다. 따라서 이 네 개의 입력 각각에 가중치를 분산시키는 편이 낫다. 가중치를 분산시킴으로써 가중치의 노름의 제곱값이 줄어들게 된다.

드롭아웃의 효과는 가중치를 줄이는 것이고 과대적합을 막는데 도움이 된다. L2 정규화는 모든 훈련 샘플에 대해 가중치를 조절하므로 각각의 샘플에 대한 영향이 크게 변하지 않는다. 반면 드롭아웃은 무작위로 선택된 노드를 삭제하므로 각 노드에 대한 페널티가 다르다. 

 

<드롭아웃을 구현할 때 세부사항>

keep_prob : 각 층에 해당 유닛을 유지할 확률

층마다 keep_prob을 바꾸는 것도 가능하다. 

첫 번째 층의 가중치 행렬 w^[1]은 (3, 7) 행렬이다. 두 번째 가중치 행렬은 (7, 7) 행렬이다. w^[3]는 (7, 3) 행렬이다. w^[2]가 (7, 7)으로 가장 많은 매개변수를 갖기 때문에 가장 큰 가중치 행렬이다. 따라서 이 행렬의 과대적합을 줄이기 위해 층 2는 상대적으로 낮은 keep_prob을 가져야 한다. 0.5로 설정하겠다. 반면에 과대적합의 우려가 적은 층에서는 더 높은 keep_prob을 설정해도 된다. 0.7로 설정하겠다. 과대적합의 우려가 없는 층은 드롭아웃을 사용하지 않으므로 keep_prob을 1로 설정해도 된다. 

입력 층에 대해서는 1.0의 keep_prob이 가장 흔한 값이다. 0.9의 값을 사용하기도 한다. 

 

<구현 팁>

컴퓨터 비전은 충분한 데이터가 없기 때문에 거의 대부분 과대적합이 일어나고 드롭아웃을 많이 사용한다. 하지만  네트워크에 과대적합의 문제가 생기기 전까지는 드롭아웃을 사용하지 않아야 한다. 

 

<드롭아웃의 단점>

비용함수 J가 더 이상 잘 정의되지 않는다는 것이다. 모든 반복마다 무작위로 한 뭉치의 노드들을 삭제하게 된다. 모든 반복에서 잘 정의된 비용함수 J가 하강하는지 확인하는게 어려워진다. 

따라서 교수님은 보통 keep_prob을 1로 설정해서 드롭아웃 효과를 멈추고 코드를 실행시켜 J가 단조감소하는지 확인한다. 그리고 드롭아웃 효과를 다시 주고 드롭아웃이 있을 때 코드를 바꾸지 않도록 한다. 

 

 

5. 다른 정규화 방법들

<데이터 어그멘테이션>

더 많은 데이터를 얻는 것은 많은 비용이 들어가거나 불가능한 경우가 있다. 대신 수평 방향으로 뒤집은 이미지를 훈련 세트에 추가시켜 훈련 세트를 2배로 늘린다. 이 방법 외에도 무작위로 이미지를 편집해 새로운 샘플을 얻을 수도 있다. 회전, 왜곡, 확대 등의 방법이 쓰인다. 여기서는 이미지를 회전시키고 무작위로 확대시켰다. 이런 추가적인 가짜 이미지들은 완전히 새로운 독립적인 고양이 샘플을 얻는 것보다 더 많은 정보를 추가해주지는 않는다. 하지만 컴퓨터적인 비용이 들지 않고 할 수 있다. 

 

<조기 종료>

경사 하강법을 실행하면서 훈련 세트에 대한 분류 오차, 즉 훈련 오차를 그리거나 최적화하는 비용함수 J를 그리게 된다. 훈련 오차나 비용함수 J는 다음과 같이 단조 감소하는 형태로 그려져야 한다. 조기 종료에서는 개발 세트 오차도 함께 그려준다. 여기서 발견할 수 있는 것은 개발 세트 오차가 아래로 내려가다가 증가한다는 것이다. 그 부분에서 신경망을 훈련시키는 것을 멈춘다. 

왜 이 방법이 작동할까? 신경망에서 많은 반복을 실행시키지 않은 경우 매개변수 w는 0에 가깝다. 반복을 실행할수록 w의 값은 계속 커진다. 조기 종료 기법에서 반복을 중간에 멈추면 w는 중간 크기의 값을 갖는 상태이다. L2 정규화와 비슷하게 매개변수 w에 대해 더 작은 노름을 갖는 신경망을 선택함으로써 신경망이 덜 과대적합하게 된다. 

 

<조기 종료의 단점>

머신러닝은 비용함수 J를 최적화하는 알고리즘을 원한다. 모멘텀, RMSProp, Adam과 같은 알고리즘들이 있다. 비용함수 J를 최적화하고 난 뒤에 과대적합되는 것을 막기 위한 도구들이 있다. 정규화, 데이터 추가하기 등의 방법이다. 머신러닝에서 이미 아주 많은 하이퍼파라미터들이 있고 여러 가능한 알고리즘 중 선택하는 것은 매우 복잡하다. 따라서 비용함수 J를 최적화하는 하나의 도구 세트만 있다면 머신러닝이 훨씬 간단해질 것이다. 

비용함수 J를 최적화할 때 집중하는 것은 w와 b를 찾는 것이다. J(w, b)가 가능한 작아지는 값을 찾는 것 외에는 신경쓰지 않는다. 과대적합을 막는 것, 즉 분산을 줄이는 것과는 완전히 다른 일이지만 조기 종료는 이 둘을 섞어버린다. 왜냐하면 경사 하강법을 일찍 멈춤으로써 비용함수 J를 최적화하는 것을 멈추게 되기 때문이다. 

 

<조기 종료의 장점>

조기 종료의 대안은 L2 정규화를 사용하는 것이지만 λ에 많은 값을 시도해야 하기 때문에 컴퓨터적으로 비용이 많이 든다. 반면 조기 종료는 경사 하강법 과정을 한번만 실행해서 작은 w, 중간 w, 큰 w의 값을 얻게 된다.