가중치의 초깃값
은닉층의 활성화값 분포
가중치의 초깃값에 따라 은닉층의 활성화값들이 어떻게 변하는지 알아보자.
시그모이드 활성화 함수를 사용하는 5층 신경망에 무작위로 생성한 입력 데이터를 흘려 각 층의 활성화 값 분포를 히스토그램으로 그려보자.
- 각 층의 활성화 값들이 0과 1에 치우져 분포되어 있다.
- 시그모이드 함수는 출력이 0 또는 1에 가까워 질수록 gradient가 0에 다가간다. 그러면 역전파의 기울기가 점점 작아지다가 사라지게 된다. 이것이 gradient vanishing으로 알려진 문제이다.
표준편차를 0.01로 바꿔보자
- 0과 1에 치우치진 않아서 기울기 소실 문제가 일어나지는 않지만 0.5 부근에 집중되어 있다.
- 활성화 값들이 한 쪽으로 치우졌다는 것은 표현련 관점에서 문제가 있다. 다수의 뉴런이 같은 값을 출력하고 있으니 뉴런을 여러 개 둔 의미가 사라진다. 즉, 뉴런이 100개인 것과 10개인 것이 별반 차이가 없다.
각 층의 활성화 값은 적당히 고루 분포되어야 한다. 그래야 신경망 학습이 효율적으로 이루어지기 때문이다.
Xavier 초기값
앞 계층의 노드가 n개라면 표준편차가 $1/{\sqrt{n}}$인 정규분포를 사용
층이 깊어지면서 형태가 일그러지지만, 앞에서 본 방식보다는 확실히 고루 분포되어 있다. 사실 이 부분은 활성화 함수를 tanh로 바꿔주면 개선된다.
이것도 좀 치우친 것 같긴한데..
ReLU를 사용할 때의 가중치 초깃값
Xavier 초기값은 활성홤 함수가 선형인 것은 전제로 이끈 결과이다. 시그모이드와 tanh는 좌우 대칭이라 중앙 부근이 선형이라고 볼 수 있다.
ReLU를 사용할 때는 He 초기값을 사용하는 것이 좋다. 이는 표준편차가 $\sqrt{2/n}$이다.
- 표준편차가 0.01인 정규분포를 사용하는 경우 활성화값들이 매우 작다. 이는 역전파시 가중치의 기울기 역시 매우 작아진다는 뜻이고 실제로 학습이 거의 이뤄지지 않는다.
- He 초기값은 매우 균일한 분포를 이루고 있다.
배치 정규화
가중치의 초기값을 적절히 설정하면 각 층의 활성화값 분포가 적당히 퍼지면서 학습이 원활하게 수행된다고 배웠다. 배치 정규화는 각 층이 활성화를 적당히 퍼뜨리도록 강제하는 기법이다.
위와 같이 신경망에 배치 정규화 계층을 삽입하여 사용, 수식은 아래와 같다.
입력 데이터의 평균과 분산을 구해서 평균이 0, 분산이 1이 되도록 정규화 한다.
또 여기에다가 고유한 scale과 shift 변환을 수행한다. 수식은 다음과 같다.
감마와 베타는 학습되는 파라미터이다.
바른 학습을 위해
오버피팅
- 매개변수가 많고 표현력이 높은 모델
- 훈련 데이터가 적음
인 경우에 주로 발생한다. 이를 억제하는 방법을 알아보자
가중치 감소
학습 과정에서 큰 가중치에 대해서는 큰 페널티를 부과하여 오버피팅을 억제하는 방법이다.
구체적으로는 모든 계층에 대한 각각의 규제를 손실함수에 더하는 것이다. 규제는 L1, L2, Max norm이 있다.
def loss(self, x, t):
"""손실 함수를 구한다.
Parameters
----------
x : 입력 데이터
t : 정답 레이블
Returns
-------
손실 함수의 값
"""
y = self.predict(x)
weight_decay = 0
for idx in range(1, self.hidden_layer_num + 2):
W = self.params['W' + str(idx)]
weight_decay += 0.5 * self.weight_decay_lambda * np.sum(W ** 2)
return self.last_layer.forward(y, t) + weight_decay
드롭아웃
임의로 뉴런을 삭제하면서 학습하는 방법이다.
간단한 구현은 다음과 같다.
class Dropout:
def __init__(self, dropout_ratio=0.5):
self.dropout_ratio = dropout_ratio
self.mask = None
def forward(self, x, train_flg=True):
if train_flg:
self.mask = np.random.rand(*x.shape) > self.dropout_ratio # rand() 메서드는 [0, 1)에서 균일한 분포를 가짐
return x * self.mask
else:
return x * (1.0 - self.dropout_ratio)
def backward(self, dout):
return dout * self.mask
훈련 때는 mask의 값이 True인 부분만 통과한다. 역전파 때도 마찬가지
적절한 하이퍼파라미터 값 찾기
그리드 서치, 랜덤 서치, 베이지안 최적화 등이 있으며 나는 주로 랜덤 서치로 적당한 범위를 찾고 그 안에서 베이지안 최적화를 사용한다.
'책 > 밑바닥부터 시작하는 딥러닝' 카테고리의 다른 글
7장 CNN (2) (0) | 2023.09.22 |
---|---|
7장 CNN (1) (0) | 2023.09.21 |
6장 학습 관련 기술들 (1) (0) | 2023.09.20 |
5장 오차역전파법 (2) (0) | 2023.09.19 |
5장 오차역전파법 (1) (0) | 2023.09.19 |