구현하면서 배우는 weight initialization(가중치 초기화) 중요성

가중치 초기화(weight initialization)은 모델을 만들고 훈련하기 전에 한번 수행을 한다

 

좋은 가중치 초기화는 모델이 optimal point에 더 빠르게 다가갈 수 있게 한다

 

 

1. 상수 가중치(all zero or one)

 

occam's razor(경제성의 원리)에 따르면 모든 가중치 값을 동일한 상수로 가정하는게 최적의 솔루션일 수 있다

 

모든 weight가 동일하다면, 각 layer의 뉴런이 동일한 output을 내놓기 때문에

 

모델이 어떤 weight를 바꿔야 최적해를 찾는지 결정하기 어려워서 training을 어렵게 한다

 

FashionMNIST 데이터셋에 동일한 MLP 모델을 training하는데 가중치를 모두 0으로 초기화하는거랑 1로 초기화하면...

 

 

 

2. random weight

 

따라서 좋은 가중치 초기화는 처음에 random하게 구성하는 것이다

 

uniform distribution에서 난수를 뽑아 weight로 구성하고 모델을 동일한 epoch으로 training하면..

 

모두 상수로 구성한 weight가 10%정도 정확도를 보인 반면에 40%의 정확도를 보임을 알 수 있다

 

 

 

3. general rule

 

uniform distribution도 어떤 구간 U(a,b)에서 수를 뽑아 weight를 구성하는지에 따라 다를 것인데..

 

일반적인 관례는 n이 layer의 input feature 수일때 $\frac{-1}{\sqrt{n}}, \frac{1}{\sqrt{n}}$의 구간에서 구성하는 것이다

 

다음은 단순히 [-1/2, 1/2]구간의 uniform 분포에서 구성한 weight로 training한 것과 일반적인 rule에 따른 구간에서 구성한 weight로 training한 성능 비교 결과이다.

 

 

 

4. normal distribution

 

random하게 weight를 구성하는 것이 분명 좋은데 uniform은 모든 수를 동일한 확률로 뽑으니 아쉽다고 생각한다면..

 

normal distribution에서 random하게 뽑은 수를 weight로 구성하는 방법도 있다

 

평균이 0이고 표준편차가 $\frac{1}{n}$으로 된 normal distribution과 위의 일반적인 rule을 따른 uniform 분포에서 성능을 비교해보면... 비슷한 결과를 보인다

 

 

 

 

모델이 매우 작아서 비슷한 성능을 보인 것으로 예상되며..

 

일반적으로 매우 큰 모델일수록 더 많은 weight를 random하게 뽑아 구성해야하므로..

 

이럴수록 normal distribution이 일반적으로 성능이 더 좋다고 함

 

 

5. pytorch 구현

 

pytorch에서 모델을 만들때 특별히 weight initialization을 수행하지 않고 training한다면.. 다음과 같은 형태를 보인다.

 

 

 

pytorch의 linear layer는 특별히 설정하지 않으면 자동으로 uniform distribution에서 weight initialization을 한다고함

 

직접 custom하고 싶다면 nn.init을 사용하거나..

 

https://deepdata.tistory.com/243

 

딥러닝 모델에서 가중치를 초기화하는 방법(weight initialization)

신경망을 학습할 때 가중치를 초기화하고 update해야하는데 어떻게 초기화해야 학습에 좋을까? 단순히 0으로 시작해버린다면 gradient가 0으로 계산되는 경우가 많을 것. 가장 많이 쓰는 방법으로 Xa

deepdata.tistory.com

 

 

다음처럼 모듈 name을 m으로 받아서 m이 특정 layer라면..

 

m.in_features로 모듈의 input feature 수를 구해서....

 

m weight data랑 m bias data로 weight, bias에 접근해서 normal_(mean,std)를 이용해 random하게 채우거나

 

fill_(c)로 동일하게 c로 채우거나...

 

# takes in a module and applies the specified weight initialization
def weights_init_normal(m):
    classname = m.__class__.__name__

    # for every Linear layer in a model..

    if classname.find('Linear') != -1:

        # get the number of the inputs
        n = m.in_features
        y = (1.0/np.sqrt(n))

        m.weight.data.normal_(0, y)
        m.bias.data.fill_(0)

 

 

잘 알려진 initialization은 He initialization, Xavier initialization이 있다

 

아래에서 다뤘으니 이걸 보도록 하고

 

https://deepdata.tistory.com/243

 

딥러닝 모델에서 가중치를 초기화하는 방법(weight initialization)

신경망을 학습할 때 가중치를 초기화하고 update해야하는데 어떻게 초기화해야 학습에 좋을까? 단순히 0으로 시작해버린다면 gradient가 0으로 계산되는 경우가 많을 것. 가장 많이 쓰는 방법으로 Xa

deepdata.tistory.com

 

 

핵심은 가중치 초기화를 동일하게 해주면.. 모델이 동일한 output을 내놓으니 어떤 weight를 바꿔야 최적해에 도달하는지 파악하기 어려워하고

 

random하게 해주는게 모델이 최적해에 도달하기 위해 어떤 weight를 바꿔야하는지 쉽게 파악할 수 있어서 모델 성능 향상에 분명히 도움이 된다

TAGS.

Comments