최근 딥러닝 개발을 진행할때 사용하는 현대의 딥러닝 라이브러리에서는 대부분 가중치 초기화 과정을 자동으로 제공하도록
라이브러리 자체에 기능을 내장하고 있다.
대표적으로 Pytorch에서 제공하는 linear layer(nn.Linear)는 내부에 가중치 초기화 기능을 내장하고 있다.
(물론, torch.nn.init 모듈 내에서 default 가중치 초기화 방식을 변경할 수 있다)
그래서, 딥러닝 개발과정에서 가중치 초기화 과정에 대해 전혀 관여하지 않고 모델을 개발하는 경우가 많다.
다만, 그렇다고 가중치 초기화 작업이 중요하지 않다는 것은 아니다.
딥러닝 라이브러리의 버전이나 종류에 따라서 가중치 초기화는 각각 다른 방법을 채택하고 있을 수 있고,
데이터의 특성 또는 과제의 특성에 따라 이에 적합한 가중치 초기화 방법을 직접 구축하고 테스트하는것은
모델, 데이터, 과제에 따라 매우 중요하게 고려되어야할 요소일 수 있다.
오늘은 '가중치 초기화(Weight initialization)'의 개념과 필요성에 대해서 살펴보도록 하자.
가중치 초기화는 말 그대로, 딥러닝 모델을 학습하기 전 초기 weight값을 특정 값으로 초기화하는 방법을 의미한다.
적합한 가중치 초기화 방법의 선택 여부에 따라서, 모델의 최종 학습 성능이 달라질 수 있고, 학습 과정에서 gradient vanishing, exploding과 같은 문제로 인해 local minimum에 빠지는 문제도 예방할 수 있게된다.
아래 표는 가중치초기화 여부 또는 방식에 따라 모델의 최종 성능이 얼마나 달라질 수 있는지를 잘 보여준다.
먼저, 가중치 초기화의 안 좋은 예시를 몇가지를 살펴보자.
# weight 초기값을 모두 0으로 설정한 경우
만약 가중치를 0으로 초기화한 후 학습을 진행한다면, 모든 뉴런들이 같은 값을 가지게 되고, Back propagation 진행 시, 각 뉴런이 loss에 미친 영향도는 같으므로, 모두 동일한 값으로 가중치가 update된다.
이렇게 모든 레이어가 동일한 값으로 update된다는 것은 레이어를 여러개의 층으로 나눈 의미를 퇴색되게끔한다.
즉, 모든 노드들이 같은 값을 가지게되어 다양한 의미의 학습이 되지않고, 거기에 값이 모두 0이기때문에 연산이 무효화 되어 학습이 진행되지않는 것이다.
# weight 초기값을 너무 크게 or 작게 설정한 경우
예를들어 초기화 값이 너무 크게 설정된 경우, gradient가 기하급수적으로 커지며, weight도 비정상적으로 커지면서 학습 양상이 발산하게 된다. 반대로 초기값을 너무 작게 설정한 경우에도 역전파과정에서 입력층으로 연산이 진행될 수록 gradient가 작아지면서 weight가 제대로 업데이트되지 않게 된다.
따라서, 역전파과정에서 다양한 의미를 학습하여, 복수의 depth로 이루어진 layer를 통해 효과적으로 가중치를 오래 update할 수 있도록
최초 가중치 설정이 매우 중요한것이다.
그렇다면, 이제 대표적으로 활용되는 가중치 초기화 방법에는 어떤 것들이 있는지 한번 살펴보도록 하자!
1) LeCun
98년도에 Yann LeCun이 제기한 방법으로 최근에는 Xavier나 He 방식에 비해 덜 사용된다고 한다.
LeCun은 주로 sigmoid activate function과 함께 사용될 때, 신경망이 효율적으로 학습할 수 있도록 설계되어 있다.
이 방식은 입력 차원의 수(n_in)를 기반으로 가중치의 분산을 조정해서, 네트워크의 각 레이어를 통과할때,
입력 신호의 분산이 유지되도록 하는 방법이다.
다만, 시그모이드나 하이퍼볼릭 탄젠트와 같은 S자형 활성함수와 사용하게 될 경우 gradient vanishing문제를 완화하는데 도움을 주지만,
ReLU와 같은 비선형 활성함수와 함께 사용할 경우 gradient vanishing, exploding 문제를 해결하기에 충분하지 않을 수 있다.
입력 차원이 10인 레이어의 경우 가중치를 초기화할 표준편차를 구하는 방법은, 아래와 같이 계산된다.
2) Xavier (Glorot)
이 방법은 입력 노드와 출력 노드에 따라 초기 가중치의 스케일을 조정하는 방법이다.
위 공식에서 n-in은 입력 차원의 수, n-out은 출력차원의 수를 의미한다.
이는 feedforward방향과 backpropagation 방향에서 정보(신호)가 적절히 전파될 수 있도록 입력차원과 출력차원의 고려하여
가중치가 분산된 값을 가질 수 있도록 고안된 방법이다.
해당 방식은 하이퍼볼릭 탄젠트와 같이 중심값이 0인 활성함수와 함께 활용하기 적합한 초기화 방식이다.
다만, ReLU와 같은 비선형 활성함수와 함께 활용될 경우 gradient vanishing 문제를 해결하기 어렵다는 단점을 가지고 있다.
이는 Xavier의 초기화가 가중치의 분산을 he초기화에 비해 작게 가져가게 되는데, ReLU를 사용할때는 초기 가중치가
너무 작으면, 네트워크의 초기 단계에서 많은 뉴런이 0을 출력하게 되어 네트워크 학습이 제대로 이루어지지 않을 수 있기때문이다.
이는 결국 깊은 네트워크에서 정보의 학습이 제대로 진행되지않는 문제로 이어지게 된다.
3) He (Kaiming)
ReLU 활성화 함수와 그를 변형한 활성함수를 사용하는 네트워크를 위해 개발된 초기화 방식이다.
ReLU는 음수 입력에 대해 0을 출력하기 때문에, Xavier 초기화 방식이 제공하는 분산 조정은 ReLU를 사용하는 데 적합하지 않다.
He 초기화는 이를 고려하여 입력 유닛의 수를 기반으로 가중치의 분산을 결정하며, 아래의 *공식을 활용해서 ReLU의 음수 입력시,
0을 출력하는 문제로 발생하는 neuron dying문제를 완화하기 위해 더 큰 분산을 사용하여 가중치를 초기화 하는 방식을 선택한다.
계산 방식은 아래와 같다.
예를들어, 입력차원이 10인 경우 계산된 가중치의 표준편차는 아래와 같이 계산된다.
He 초기화 방식은 위 설명과 같이 ReLU 활성함수와는 궁합이 잘 맞지만, 반대로 Sigmoid나, tanh과 같은 S형 활성함수를
사용하는 네트워크에는 적합하지 않은데, He초기화 방식이 Xavier과 같은 초기화 방식에 비해 큰 분산을 사용하여 가중치를
초기화하기때문에, 네트워크 초기에 너무 큰 가중치 값으로, tanh나 sigmoid함수가 빠르게 포화 상태에 도달하게 되어
gradient vanishing문제를 악화시킬 수 있기 때문이다.
# 모델을 학습할때, 가중치 초기화 방식에 문제가 있다는 것은 어떻게 탐지할 수 있을까?
가중치 초기화가 매우 중요하다는 것은 충분히 이해했지만, 모델 학습과정에서 가중치 초기화가 문제가 있다는것을 구체적으로
어떻게 탐지할 수 있을까?
사실, 몇가지 징후를 포착할수는 있지만, 문제의 원인이 꼭 초기화에 있다고 단정짓기는 쉽지않으므로,
아래의 현상이 발생할 경우, 모델자체의 문제인지, activation function 문제인지, 데이터의 문제인지는 자세히 살펴봐야 알 수 있다.
어쨌든 아래의 현상이 있을 경우 '가중치 초기화'의 문제를 예상되는 원인의 하나로 보고 접근해볼 수 있다.
# 학습이 매우 느리게 진행되는 경우
적절한 가중치 초기화가 이루어지지 않으면, 신경망은 매우 작은 그라디언트 값을 가질 수 있다.
이는 가중치 업데이트가 충분히 이루어지지 않아 학습이 느리게 진행될 수 있음을 의미한다.
# 학습이 전혀 진행되지 않는 경우
가중치가 너무 크게 초기화되어 그라디언트 폭발이 발생하거나, 너무 작게 초기화되어 그라디언트 소실이 발생할 수 있습니다.
이는 손실 함수의 값이 줄어들지 않고 변동성이 크거나, 전혀 개선되지 않는 현상으로 나타날 수 있다.
# 손실 함수의 값이 NaN이나 무한대로 발산하는 경우
가중치가 너무 크게 초기화되어 오버플로를 일으키거나, 계산 중에 불안정한 수치 문제가 발생할 수 있다.
이는 학습 과정에서 손실 함수의 값이 NaN(Not a Number)이나 무한대로 발산하는 현상으로 관찰될 수 있다.
# 검증 성능이 개선되지 않거나 과적합이 심해지는 경우
가중치 초기화가 모델의 학습 능력에 부적절하게 영향을 미쳐, 학습 데이터에는 빠르게 적응하지만 검증 데이터셋에서는 성능이 개선되지 않거나, 과적합이 발생할 수 있다.
Reference
https://blog.naver.com/handuelly/221831940317
'DEVELOP_NOTE > ML' 카테고리의 다른 글
Vector DB란 무엇일까? 그리고 어떤 Vector DB를 사용해야할까? (1) (0) | 2024.02.27 |
---|---|
이제 Tabular Data는 MLP 대신 FT-Transformer를 써야하는 이유! (0) | 2024.02.23 |
Pytorch의 'AutoGrad' 과정을 하나하나 뜯어보자! (0) | 2024.02.07 |
[Norm] L2 Norm? L1 Norm? 이제 제대로 알고 사용하자! (0) | 2024.01.19 |
[Imbalance Data] 불균형데이터를 극복하고 모델을 학습하는 방법 (0) | 2024.01.17 |