지난 글에서 다층 퍼셉트론을 구현하고 학습시켰다. 그런데 학습이 한 스텝이라도 돌기 전에, 신경망 안의 숫자들이 처음에 어떤 값이었느냐가 학습의 성패를 크게 가른다. 잘못 고른 초기값은 몇 층만 지나도 신호를 0으로 만들거나 터뜨려, 기울기가 흐르지 않는 상태로 학습을 시작하게 한다. 가중치 초기화는 그 사고를 막기 위해 처음 숫자의 분포를 고르는 일이고, 딥러닝이 깊은 신경망을 실제로 학습시킬 수 있게 된 계기 중 하나이기도 하다. 이 글은 분산이 층을 지나며 어떻게 변하는지를 식 하나로 잡고, 거기서 Xavier와 He가 어떻게 도출되는지, 정규화 레이어가 흔해진 지금 무엇이 남았는지를 본다.
초기값과 분산
분산이 층을 지나는 식
층 하나가 하는 일은 입력 여러 개에 가중치를 곱해 더하는 것이다. 이 합의 퍼짐이 얼마나 되는지를 보면 신호가 층을 지나며 커지는지 작아지는지를 알 수 있다. 입력과 가중치가 서로 독립이고 평균이 0이라고 가정하면 합의 분산은 깔끔하게 정리된다.
여기서 n은 그 뉴런에 들어오는 입력의 개수이고 σ²_w는 가중치의 분산, σ²_x는 입력의 분산이다. 읽는 법은 간단하다 — 한 층을 지날 때마다 신호의 분산에 n · σ²_w라는 인수가 곱해진다. 초기화 이론 전체가 이 인수를 1 근처로 맞추려는 시도다.
식에 무엇이 없는지도 봐 둘 만하다. 층의 깊이도, 학습률도, 옵티마이저도 없다. 들어 있는 것은 층의 폭과 가중치 분포의 퍼짐 둘뿐이고, 그래서 초기화는 다른 하이퍼파라미터와 달리 모델 구조만 보고 값을 계산할 수 있다. Xavier와 He가 튜닝 대상이 아니라 공식으로 주어지는 이유다.
증폭과 감쇠
인수가 1이 아니면 층을 지날수록 지수로 벌어진다. 입력이 500개인 층을 열 겹 쌓고 가중치 표준편차를 0.01로 두면 인수는 500 × 0.0001 = 0.05다. 열 층을 지나면 분산에 0.05의 10제곱, 곧 10조분의 1이 곱해진다. 마지막 층에 도착한 신호는 사실상 0이고, 역방향으로 돌아오는 기울기도 같은 인수를 타고 사라진다.
반대로 표준편차를 1.0으로 두면 인수가 500이다. 두세 층만 지나도 값이 폭주하는데, tanh나 sigmoid를 쓰면 폭주 대신 포화가 온다. 출력이 -1이나 1에 붙어 버리고 그 구간의 미분이 거의 0이라 기울기가 역시 흐르지 않는다. 너무 작으면 소멸, 너무 크면 포화 — 양쪽 끝의 증상이 다르지만 결과는 같다.
활성값 히스토그램
이 현상은 층마다 활성값을 히스토그램으로 찍어 보면 눈으로 확인된다. 건강한 초기화에서는 층이 깊어져도 히스토그램의 폭이 비슷하게 유지된다. 표준편차가 너무 작으면 히스토그램이 층마다 좁아져 0 하나에 뾰족하게 몰리고, 너무 크면 -1과 1 양쪽 끝에 두 덩어리로 갈라진다.
def activation_std(W_std, depth=10):
x = torch.randn(1000, 500)
stds = [x.std().item()]
for _ in range(depth):
x = torch.tanh(x @ (torch.randn(500, 500) * W_std))
stds.append(x.std().item())
return stds
print(activation_std(0.01)) # 층마다 좁아짐 → 0으로 수렴
print(activation_std(1.0)) # 양 끝으로 갈라짐 → tanh 포화
학습이 안 될 때 손실 곡선만 보면 두 경우가 똑같이 "안 줄어든다"로 보이는데, 이 히스토그램은 둘을 가른다. 초기화를 의심할 때 가장 먼저 찍어 볼 그림이다.
표준편차 하나만 층별로 찍어도 대부분 잡힌다. 층 번호와 활성값 표준편차를 나란히 출력해 값이 층을 따라 한 자릿수씩 떨어지는지, 한 자리에 머무는지, 오르는지 보면 세 상태가 구별된다. 학습을 돌리기 전 한 번의 순전파만으로 확인되므로 비용이 거의 없다.
0 초기화와 대칭성
대칭성 파괴
가중치를 전부 0으로 두면 깔끔할 것 같지만 학습이 아예 시작되지 않는다. 한 층의 뉴런들이 모두 같은 가중치를 가지면 같은 입력에 같은 출력을 내고, 같은 출력을 내면 역전파에서 같은 기울기를 받고, 같은 기울기를 받으면 같은 방향으로 같은 크기만큼 움직인다. 갱신 뒤에도 여전히 서로 같다.
이 상태가 계속되면 뉴런이 아무리 많아도 실질적으로는 하나다. 서로 다른 특징을 잡아내라고 넓게 만든 층이 같은 함수를 여러 벌 계산하는 층이 된다. 학습이 시작되려면 뉴런들이 서로 달라야 하고, 그 차이를 만드는 유일한 출처가 초기값의 무작위성이다. 이것을 대칭성 파괴라고 부른다.
편향 0
가중치와 달리 편향은 0으로 두는 것이 표준이다. 대칭성을 깨는 일은 가중치가 이미 하고 있기 때문이다. 같은 층의 두 뉴런이 서로 다른 가중치를 가지면 편향이 같아도 출력이 다르고, 출력이 다르면 기울기도 다르다.
예외가 두 자리 있다. ReLU를 쓰면서 처음부터 뉴런이 꺼지는 것이 걱정될 때 편향을 0.01처럼 작은 양수로 두는 관례가 있었고, 클래스가 크게 불균형한 분류에서 출력층 편향을 사전 확률에 맞춰 두면 초반 수렴이 빨라진다. 둘 다 대칭성과는 무관한 이유이고, 그 밖에는 0이 기본이다.
상수 초기화
0이 아닌 같은 상수, 이를테면 전부 0.1로 두면 어떨까. 대칭성 문제는 그대로다. 값이 0이든 0.1이든 같은 층의 뉴런이 서로 구별되지 않는다는 사실은 변하지 않는다.
무작위이기만 하면 되는 것도 아니다. 값을 전부 크게 뽑으면 대칭성은 깨지지만 앞 절의 인수가 커져 신호가 폭주하고, 전부 작게 뽑으면 소멸한다. 초기화가 「무작위로 작은 값」이라는 요약으로 자주 설명되는데, 그 요약이 빠뜨리는 것이 「얼마나 작아야 하는가」이고 그 답이 폭에 따라 달라진다는 사실이다.
여기서 초기화의 요건 두 가지가 정리된다. 첫째, 같은 층 안에서 값이 서로 달라야 한다. 둘째, 그 값들의 분산이 앞 절의 인수를 1 근처로 만드는 크기여야 한다. Xavier와 He는 둘째 요건을 각각 다른 가정 아래 푼 답이고, 첫째 요건은 무작위로 뽑는 것만으로 저절로 충족된다.
Xavier 초기화
순전파와 역전파의 조건
2010년 Xavier Glorot와 Yoshua Bengio는 분산 인수를 양방향에서 함께 맞추려 했다. 순전파에서 신호의 분산이 유지되려면 그 층에 들어오는 입력 수를 n_in이라 할 때 가중치 분산이 1 / n_in이어야 한다. 그런데 역방향으로 기울기가 흐를 때는 나가는 방향의 개수가 인수가 되므로 1 / n_out이 필요하다.
두 조건은 n_in과 n_out이 같지 않으면 동시에 만족되지 않는다. 그래서 둘의 조화로운 절충으로 분모에 합을 쓴다.
n_in과 n_out이 같을 때 이 식은 정확히 1 / n이 되어 두 조건을 다 만족한다. 다를 때는 어느 쪽도 정확히 맞추지 않되 양쪽 다 크게 어긋나지 않는 자리에 선다. 순전파만 보는 초기화와 갈리는 지점이 여기다.
√6의 출처
Xavier에는 정규분포 버전과 균등분포 버전이 있고, 균등형 쪽에 √6이라는 낯선 상수가 붙는다. 이 수는 마법이 아니라 균등분포의 분산 공식에서 그대로 나온다.
구간 [-a, a]의 균등분포는 분산이 a² / 3이다. 이 값이 위에서 구한 분산과 같아야 하므로 a² / 3 = 2 / (n_in + n_out)이고, a에 대해 풀면 6이 분자로 올라온다.
같은 방식으로 He의 균등형 상수도 나온다. 분산이 2 / n_in이어야 하므로 a² / 3을 거기에 맞추면 분자가 6이 되고, 결과는 √(6 / n_in)이다. 상수 6은 Xavier만의 것이 아니라 균등분포를 쓸 때면 따라오는 수라는 뜻이다.
두 버전은 분산이 같으므로 실무에서 성능 차이가 거의 없다. 균등형은 값이 구간 밖으로 안 나가고 정규형은 드물게 큰 값을 허용한다는 차이가 있을 뿐이다.
tanh와 sigmoid
Xavier의 유도에는 숨은 가정이 하나 있다. 활성화 함수가 원점 근처에서 거의 선형이고 출력의 평균이 0이라는 가정이다. tanh는 원점 근처 기울기가 1이고 좌우 대칭이라 이 가정에 잘 맞는다.
sigmoid는 출력이 0과 1 사이라 평균이 0이 아니고 원점 기울기도 0.25다. 그래서 엄밀히는 보정이 필요한데, 실무에서는 은닉층에 sigmoid를 쓰는 일 자체가 드물어져 문제가 되지 않는다. 정작 Xavier가 어긋난 자리는 다른 곳이었다 — ReLU가 표준이 되면서 「원점 근처에서 선형」이라는 가정이 절반만 참이 됐다.
가정을 확인하는 방법도 적어 둘 만하다. 그 층의 출력 평균을 찍어 보면 된다. 0 근처면 Xavier의 가정이 서 있는 것이고, 한쪽으로 치우쳐 있으면 유도의 전제가 깨진 것이라 공식이 주는 값도 최적이 아니다. 초기화 공식을 외워 쓰는 것과 그 공식이 언제 성립하는지 아는 것의 차이가 여기서 난다.
He 초기화
ReLU가 깎는 절반
ReLU는 음수 입력을 전부 0으로 만든다. 입력이 0을 중심으로 대칭이면 절반이 0이 되고, 그러면 출력의 분산이 입력 분산의 절반으로 줄어든다.
이 감쇠가 층마다 쌓인다. 분산 인수를 1로 맞춰 놓아도 ReLU가 층마다 0.5를 곱하므로 실제 인수는 0.5다. 20층을 쌓으면 0.5의 20제곱, 곧 100만분의 1로 신호가 줄어든다. Xavier로 초기화한 깊은 ReLU 신경망이 학습이 안 되던 원인이 정확히 이것이었다.
절반이라는 값이 어디서 나오는지도 짚어 두자. ReLU를 지난 뒤 살아남는 것은 양수 쪽뿐인데, 입력 분포가 0을 기준으로 대칭이면 그 양수 쪽이 전체 제곱합의 정확히 절반을 차지한다. 입력이 한쪽으로 치우쳐 있으면 절반이 아니게 되고, 그래서 He의 상수도 Xavier와 마찬가지로 가정 위에 선 값이다.
2배 상수
2015년 Kaiming He가 낸 답은 단순하다. ReLU가 절반을 깎으니 처음부터 두 배를 넣어 둔다.
분자의 2가 ReLU의 감쇠를 정확히 상쇄한다. Leaky ReLU처럼 음수 쪽 기울기가 0이 아닌 변형에는 그 기울기를 반영한 상수가 따로 있고, PyTorch의 kaiming_normal_은 nonlinearity 인자로 그 값을 고른다. 활성화를 바꿨으면 초기화 인자도 같이 바꿔야 한다는 뜻이다.
def init_he(m):
if isinstance(m, (nn.Linear, nn.Conv2d)):
nn.init.kaiming_normal_(m.weight, mode='fan_in', nonlinearity='relu')
if m.bias is not None:
nn.init.zeros_(m.bias)
model.apply(init_he)
fan_in과 fan_out
He 초기화는 Xavier와 달리 분모에 합을 쓰지 않고 한쪽만 쓴다. 그래서 어느 쪽을 쓸지 고르는 인자가 붙는다. fan_in은 순전파에서 활성값 분산을 지키고 fan_out은 역전파에서 기울기 분산을 지킨다.
둘 중 하나만 고르는 것이 Xavier처럼 절충하는 것보다 나쁜 선택은 아니다. Xavier는 양쪽을 반씩 어기는 값이고 He는 한쪽을 정확히 지키고 다른 쪽을 버리는 값인데, ReLU 신경망에서는 순전파 쪽 신호가 살아 있는 것이 더 결정적이라 후자가 실측에서 잘 나왔다.
PyTorch의 기본값은 fan_in이다. 실무에서 둘의 차이는 대개 크지 않은데, 두 값이 크게 다른 층에서만 갈린다. 폭이 일정한 네트워크에서는 n_in과 n_out이 같아 어느 쪽을 골라도 결과가 똑같고, 그래서 이 인자를 고민해야 하는 상황은 층 폭이 급격히 바뀌는 구간뿐이다.
층별 분산 실측
20층의 층별 분산
식을 믿기보다 재 보는 편이 빠르다. 폭 100짜리 층을 20겹 쌓고 ReLU를 끼운 뒤 층마다 활성값의 분산을 찍어 보자.
가중치 표준편차를 0.01로 두면 분산이 층마다 급격히 줄어 다섯 층쯤에서 이미 측정이 무의미해진다. Xavier로 두면 ReLU의 절반 감쇠 때문에 층마다 0.5배씩 줄어, 20층 끝에서 처음의 100만분의 1이 된다. He로 두면 층마다 비슷한 값이 유지되어 20층 끝에서도 첫 층과 같은 자릿수다. 셋의 차이가 상수 하나에서 나온다는 점이 이 실험의 요점이다.
재는 방법도 간단하다. 학습을 시키지 말고 무작위 입력 한 배치를 넣어 순전파만 하면서 층마다 출력의 분산을 기록하면 된다. 역전파도 옵티마이저도 필요 없다 — 여기서 확인하려는 것은 학습의 결과가 아니라 학습이 시작될 수 있는 상태인지 여부이기 때문이다.
수렴 속도
같은 세 초기화로 실제 학습을 돌려 보면 차이가 손실 곡선에 그대로 나타난다. 너무 작게 초기화한 쪽은 손실이 초반 수십 에폭 동안 거의 평평하다 — 기울기가 안 흐르니 파라미터가 사실상 안 움직인다. Xavier는 그보다 낫지만 He보다 늦게 내려가고, He는 첫 에폭부터 곧장 떨어진다.
초기화가 바꾸는 것이 최종 성능이 아니라 출발 조건이라는 점을 여기서 확인할 수 있다. 잘못된 초기화는 모델의 표현력을 깎는 것이 아니라 학습이 시작되지 못하게 만든다. 그래서 증상이 "성능이 조금 낮다"가 아니라 "학습이 안 된다"로 나타난다.
차이가 사라지는 지점
층이 얕으면 셋의 차이가 거의 안 보인다. 분산 인수는 층 수만큼 거듭제곱되므로 두세 층에서는 0.5배와 1배의 차이가 기껏해야 네 배 남짓이고, 그 정도는 학습률 조정이나 몇 에폭의 학습으로 흡수된다.
초기화가 결정적인 것은 깊이가 열 겹을 넘어갈 때부터다. 거꾸로 말하면 얕은 신경망으로 실험하면서 초기화의 중요성을 체감하지 못한 채 깊은 모델로 넘어가는 순간 벽에 부딪히게 된다. 20층을 넘기는 모델을 처음부터 학습시킬 때 초기화와 정규화를 함께 확인하는 것이 순서다.
사전 학습된 가중치를 불러와 파인튜닝하는 경우는 이 이야기 바깥이다. 그때 초기값은 우리가 고르는 것이 아니라 앞사람이 학습시켜 놓은 값이고, 새로 붙이는 마지막 분류 층만 초기화 대상이 된다. 초기화를 직접 고르는 일이 예전보다 줄어든 것은 이 때문이기도 하다.
정규화 레이어와 초기화
BN과 LN
배치 정규화와 레이어 정규화는 층의 출력을 평균 0, 분산 1로 다시 맞춘다. 앞 층에서 분산이 조금 커지거나 작아져도 다음 정규화 지점에서 되돌려지므로, 분산 인수가 정확히 1이 아니어도 그 오차가 층을 타고 쌓이지 않는다. 정규화 레이어가 들어간 신경망에서 초기화에 덜 민감해지는 이유다.
둘의 차이도 여기서 나온다. 배치 정규화는 배치 안의 여러 샘플을 가로질러 통계를 내므로 배치가 작으면 통계가 흔들린다. 레이어 정규화는 샘플 하나 안에서 통계를 내므로 배치 크기와 무관하고, 그래서 배치 구성이 들쭉날쭉한 트랜스포머 계열에서 표준이 됐다.
| 상황 | 권장 초기화 |
|---|---|
| ReLU 계열 은닉층 | He/Kaiming Normal (mode=fan_in) |
| Sigmoid/Tanh 은닉층 | Xavier Uniform/Normal |
| 트랜스포머 | N(0, 0.02) |
| 출력층 | N(0, 0.01) 또는 Xavier |
| 임베딩 층 | N(0, 1) 또는 폭의 제곱근에 반비례하는 분산 |
초기화가 남는 자리
"덜 민감"은 "무관"이 아니다. 정규화가 없는 자리가 여전히 있다. 임베딩 층은 조회 연산이라 정규화를 안 거치는 경우가 많고, 출력층은 그대로 손실로 들어가므로 초기 분산이 첫 손실값을 정한다. 잔차 분기의 마지막 층을 0에 가깝게 두어 학습 초반에 항등 경로만 살리는 기법도 초기화로 하는 일이다.
이 목록에 공통점이 있다. 전부 정규화 레이어가 손대지 않는 지점이고, 동시에 모델 바깥과 맞닿는 지점이다. 입력이 들어오는 임베딩과 결과가 나가는 출력층이 그렇고, 경로가 갈라지고 합쳐지는 잔차 분기가 그렇다. 초기화를 어디에 신경 쓸지 고를 때 이 경계를 먼저 보면 된다.
한 가지 더 있다. 정규화 레이어는 분산을 되돌려 주지만 학습 초반 몇 스텝은 정규화 자신의 통계가 안정되기 전이다. 그 구간의 거동을 정하는 것은 여전히 초기값이고, 학습률 워밍업이 필요한 이유의 일부이기도 하다.
정규화 레이어 자신의 파라미터도 초기화 대상이다. 출력을 다시 늘리고 옮기는 두 값이 붙어 있는데, 보통 늘리는 쪽을 1로 옮기는 쪽을 0으로 두어 학습 초기에는 정규화 결과를 그대로 통과시킨다. 잔차 분기의 마지막 정규화에서 늘리는 쪽을 0으로 두는 변형도 있고, 이것이 앞에서 말한 항등 경로만 살리는 기법의 한 형태다.
트랜스포머의 관례
트랜스포머 계열에서는 가중치를 평균 0, 표준편차 0.02의 정규분포로 두는 관례가 널리 쓰인다. 폭에 따라 값을 계산하는 Xavier나 He와 달리 고정된 상수라는 점이 특이한데, 이 값이 자주 쓰이는 폭에서 He가 주는 값과 비슷한 자릿수이고 레이어 정규화가 나머지를 잡아 주기 때문에 굳어진 관례다.
여기에 잔차 분기 수를 반영한 보정이 붙는 경우가 많다. 잔차 연결이 층마다 출력을 더하므로 깊이가 깊어질수록 합의 분산이 커지는데, 분기의 마지막 층을 깊이의 제곱근에 반비례하게 줄여 그 증가를 상쇄한다. 깊은 트랜스포머가 워밍업 없이도 안정적으로 학습되도록 만드는 장치들 중 하나이고, 초기화가 여전히 설계의 대상이라는 증거이기도 하다.
정리하면 이 글의 결론은 상수 두 개가 아니라 절차 하나다. 층의 폭을 보고 분산 인수를 1 근처로 맞추는 값을 고르고, 활성화가 그 인수를 깎으면 깎는 만큼 되돌리고, 정규화가 뒤를 받쳐 주는 구간은 덜 신경 쓰되 정규화가 없는 자리는 직접 챙긴다. Xavier와 He는 그 절차를 두 가지 흔한 경우에 대해 미리 풀어 둔 답이고, 새로운 활성화나 새로운 구조가 나오면 같은 절차를 다시 밟아 값을 구하게 된다.
읽어주셔서 감사합니다. 😊

