가중치 초기화
가중치 초기화는 굉장히 중요하다.
가중치 초기화는 딥러닝 모델의 학습 속도와 성능에 큰 영향을 미친다. 잘못된 초기화는 활성화 함수에 의해 데이터 분포가 한쪽으로 쏠리거나, 전역 최솟값에 도달하는 데 어려움을 겪게 할 수 있다. 특히, 층이 깊어질수록 데이터가 활성화 함수를 거치며 왜곡되기 때문에 가중치 초기화는 필수적인 과정이다.
가중치 초기화가 필요한 이유
(1) 데이터 분포 왜곡 방지
딥러닝을 쓰다 보면 레이어가 많아지는데 이게 무슨 의미냐면 활성화 함수를 계속 거쳐가면서 데이터가 뒤로 넘어간다는 뜻이다. 그 말은 활성함수를 시그모이드를 쓰던, ReLU를 쓰던, 하이퍼볼릭 탄젠트를 쓰던, 입출력 관계의 분포를 보면 한쪽으로 쏠리게 되어있다.
- 시그모이드는 입력 신호 범위가 마이너스 무한대부터 무한대까지 되더라도 실제 출력은 0에서 1 사이의 값이 된다. 이게 몇 번씩 반복하게 되면 점점 데이터가 한쪽으로 쏠리는 경향이 생긴다.
- ReLU를 보더라도 음수 영역은 다 날려버리기 때문에 극단적으로는 아예 출력 신호가 없게 되어버릴 수도 있다.
- 하이퍼볼릭 탄젠트도 시그모이드랑 비슷하게 활성함수의 출력의 범위가 제한되어 있다 보니까 데이터의 분포가 한쪽으로(중간값으로) 쏠릴 수가 있다.
그래서 이게 너무 한쪽으로 쏠리거나 0의 값이 되는 경우에는 학습이 원활하게 진행되지 않는다.
실제로 한 5개 레이어에 활성화 함수 이후에 데이터를 쭉 뿌려봐도 처음에는 괜찮은 것 같지만 점점 뭔가 한쪽으로 쏠려가고 있다.
기본적으로 이런 성향을 가지고 있기 때문에 모델이 자유롭게 데이터 분포를 찾아가면서, 맞춰가면서 학습이 되는 데에는 분명히 방해가 된다.
💡 요약: 가중치 초기화(Weight Initialization)를 진행하지 않으면 모델의 층이 깊어질수록 활성화 함수 이후 데이터의 분포가 한쪽으로 쏠릴 수 있다. 이러한 현상은 효율적이고 원활한 모델 학습을 방해한다.
(2) 최적화 과정에 미치는 영향
딥러닝의 목표는 비용 함수를 최소화하는 것이다. 최적화 알고리즘은 처음 시작할 때 가중치 값을 기반으로 방향을 찾아가면서 최적의 값을 찾아나간다. 이때 초기 가중치 값이 어디서 시작하느냐에 따라 전체 학습 성능이 크게 달라진다.
그래서 가능하면 전역 최소 지점 근방에서 파라미터 값이 초기화가 되면 아주 빠르게 학습이 될 수 있다. 이런 걸 목표로 삼는 게 가중치 초기화 방법이 추구하는 방향이다.
💡 요약: 이러한 가중치 초기화는 전역 최솟값을 나아가는 과정에서 가장 중요한 부분이기도 하다. Plateau와 같은 지점에서 초기화가 된다면 모델 학습이 비효율적으로 이뤄질 수 있다.
(3) Gradient vanising 및 exploding 문제 해결
모델을 학습할 때, 가중치를 업데이트하기 위해서는 손실 함수를 미분하여 기울기를 계산하고 이를 바탕으로 가중치를 조정한다. 여기서 중요한 부분은 활성화 함수가 등장한다는 점이다.
활성화 함수는 각 레이어에서 데이터를 변환하는 역할을 하는데, 이를 미분한 값(기울기)이 가중치 업데이트에 직접적으로 영향을 미친다. 활성화 함수에 따라 기울기가 0에 가까워지거나 지나치게 커질 수 있다.
이 활성함수 값에 미분값이 곱해지는 건 피할 수 없지만 이 값의 역량이 그래도 너무 작지 않도록 만드는 건 결국 어느 위치에서 미분이 되느냐다.
그래서 그 위치를 잘 정해지기 위해서는 가중치를 적절하게 초기화가 잘 되면 처음 시작에는 적어도 이 부분이 어느 정도 영향이 덜 할 수 있도록 만들어 줄 수가 있다. 그래서 학습 속도가 초반에 너무 떨어지지 않게 만들어 줄 수 있는 것이다.
💡 요약: 모델의 층이 깊어질수록 손실 함수로부터의 기울기 값이 점점 작아지거나 커질 수 있다. 이러한 현상은 오차역전파로 가중치를 갱신해야 하는 모델의 학습을 효율적으로 진행되지 않게 만들 수 있다.
Xavier 초기화
Xavier 초기화는 다음과 같은 직관을 갖고 있다.
Xavier 초기화는 특정 노드와 연결된 다른 노드들의 수를 기반으로 가중치를 초기화하는 방법이다. 예를 들어, 보라색 노드(아래 사진에서 오른쪽 두 번째 보라색)가 있다고 하면, 이 노드와 연결된 다른 노드들의 수를 먼저 센 후, 그 수에 따라 가중치를 정규분포로 초기화한다. 이때, 노드와 연결된 개수가 많을수록 가중치의 값이 너무 크지 않게 표준편차를 작게 조정한다.
결국 이 방법을 사용하면, 가중치 분포가 너무 넓거나 한쪽으로 치우치지 않고, 출력도 안정적으로 유지된다. 즉, 학습 과정에서 데이터가 안정적으로 흐르며 학습이 잘 이루어진다는 것이다.
💡 요약: Xavier 초기화(Xavier initialization)는 대표적인 가중치 초기화 전략 중 하나로, 시그모이드(Sigmoid)나 하이퍼볼릭 탄젠트 (Tanh) 같은 선형 활성화 함수 또는 이들의 근사를 사용할 때 효과적이다. 이 방법은 초기에 너무 큰 가중치 값을 설정하면 기울기가 너무 커지거나 작아져서 학습이 어렵게 될 수 있는 문제를 해결할 수 있다. 또한, 이전 레이어의 노드 수에 비례하여 가중치를 초기화한다. 이를 통해 이전 레이어의 노드 수가 많을수록 각 가중치의 크기는 작아지게 된다.
Xavier 초기화는 초기에는 시그모이드와 같은 활성화 함수에서 좋은 성과를 냈지만, ReLU 함수와 결합했을 때는 문제가 발생했다.
ReLU는 입력값이 양수일 때 미분값이 1이므로, 역전파가 발생할 때 신호가 약해지지 않는다. 따라서 ReLU는 학습에 자주 사용된다. 그러나 ReLU와 Xavier 초기화를 함께 사용하면, ReLU의 특성 때문에 출력값이 불안정해질 수 있다. 왜냐하면 ReLU가 음수 값을 모두 0으로 만들어버리기 때문에, 학습이 진행될수록 출력값이 불균형하게 변할 수 있기 때문이다.
💡 요약: Xavier 초기화는 시그모이드와 같은 활성화 함수에선 효과가 좋았지만, 특정한 활성화 함수에선 여전히 문제를 해결할 수 없었다. 예를 들면, ReLU 활성화 함수의 미분값은 음수일 때 출력이 0이므로, 여전히 레이어가 깊어질수록 기울기가 소실될 수 있다.
He 초기화(He Initialization)는 이러한 치명적인 문제를 완화시키려는 목적으로 제안되었다.
He 초기화
이 문제를 해결하기 위해 등장한 방법이 He 초기화다. He 초기화는 Xavier 초기화와 비슷하지만, ReLU의 특성에 맞게 가중치를 초기화한다. ReLU는 음수 영역을 모두 0으로 만들기 때문에, Xavier 초기화보다 더 큰 표준편차를 사용하여 가중치를 초기화해야 한다. He 초기화는 이 문제를 해결하기 위해 표준편차를 더 크게 설정하여 2/n을 사용한다. 이는 ReLU와 잘 맞아떨어지며, 출력의 불안정성을 완화시켜 주었다.
💡 요약: He 초기화도 Xavier 초기화와 동일하게 이전 레이어의 노드 수에 비례하여 가중치를 초기화한다. 하지만 He 초기화는 ReLU 활성화 함수의 특성 때문에 더 큰 스케일을 사용한다. 이는 ReLU 활성화 함수가 음수일 때 0을 출력하므로, 더 큰 가중치로 시작하여 기울기 소실 문제를 완화하는 데 도움이 된다.
파이썬 코드
class Net:
def _init_(self,
# (중략)
def _init_weight(self, weight_init_std):
# 전체 네트워크의 각 층의 뉴런 수를 리스트로 구성
all_size_list = [self.input_sizel + self.hidden_size_list + [self.output_size]
# 모든 층을 순회하며 가중치를 초기화
for idx in range(1, len(all_size_list)):
scale = weight_init_std
# ReLU 활성화 함수들 사용할 경우 He 초기화 방법 사용
if str(weight_init_std). lower() in ('relu', 'he'):
scale = np.sart(2.0 / all_size_list[idx - 1])
# Sigmold 활성화 함수를 사용할 경우 Xavier 초기화 방법 사용
elif str(weight_init_std). lower() in ('sigmoid', 'xavier'):
scale = np.sqrt(1.0 / all_size_list[idx - 1])
# 가중지와 편향 조기화
self-params[f'W{idx}'] = scale * np. random.randn(all_size_list[idx-1], all_size_list[idx])
self-params[f'b{idx}'] = np.zeros(all_size_list[idx])
어떤 가중치 초기화 방법을 선택해야 할까?
가중치 초기화를 선택할 때, 결국 어떤 활성화 함수를 선택하느냐에 달려있다.
👉 시그모이드와 같은 활성화 함수를 사용한다면, Xavier 초기화 방법을 써보자.
👉 ReLU와 같은 활성화 함수를 사용한다면, He 초기화 방법을 사용해 보자.
그러나 위 방법이 또 무조건 맞다고는 못하기 때문에 다양한 방법을 시도해 보는 것이 중요하다.
가중치 초기화와 배치 정규화와의 비교
가중치 초기화와 배치 정규화는 모두 학습을 안정적으로 만들기 위한 방법이지만, 사용하는 시기와 방식에서 큰 차이가 있다.
가중치 초기화
- 언제 사용되는가?
- 학습이 시작되기 전에 가중치 값을 한 번 설정하는 과정이다.
- 학습 과정에서 가중치가 너무 크거나 작아지지 않도록 초기 상태를 잘 설정하는 것이 목적
- 사용 빈도
- 한 번만 수행된다. 학습 시작 전에 가중치를 한 번 설정하고, 이후에는 그 값을 사용하여 학습을 진행한다.
- 주요 역할
- 처음 학습할 때 기울기 vanishing이나 exploding 문제를 방지하고, 학습이 안정적으로 시작될 수 있게 도와준다.
- Xavier 초기화, He 초기화 등이 대표적인 가중치 초기화 방법이다.
배치 정규화 (Batch Normalization)
- 언제 사용되는가?
- 매번 학습할 때마다 사용된다. 특히, 각 미니 배치(batch)가 지나갈 때마다 출력을 정규화한다.
- 학습 도중에도 출력값을 일정하게 유지하기 위해 계속해서 적용된다.
- 사용 빈도
- 계속적으로 사용된다. 학습 시 매번, 그리고 추론 시에도 running mean과 running variance 값을 사용하여 활성화 함수 이후의 출력을 정규화한다.
- 주요 역할
- 학습 과정에서 출력값을 정규화하여, 각 층에서 출력되는 값이 너무 크거나 작지 않게 유지한다.
- 이는 모델이 학습을 더 안정적이고 빠르게 할 수 있도록 도와준다.
💡 요약:
• 가중치 초기화는 학습 전에 한 번만 수행되는 초기 설정
• 배치 정규화는 학습 중 매번 수행되어, 출력이 일정하게 유지되도록 도움
'Deep Learning' 카테고리의 다른 글
텍스트 데이터 전처리 방법 (토큰화, 정제, 정규화, Stemming, Lemmatization 등) (2) | 2024.11.12 |
---|---|
딥러닝 모델 구현에서 PyTorch의 쓰임 (2) | 2024.10.28 |
[Pytorch] tensor shape 변경에서 -1과 1 쓰임 그리고 슬라이싱 (1) | 2024.10.23 |
손실 함수, 활성화 함수, 최적화 함수 등 순서, 쓰임, 역할 (1) | 2024.10.23 |
딥러닝에서 손실 함수의 선택: Maximum Likelihood와 확률적 해석 (MSE, Cross-Entropy) (1) | 2024.10.16 |