BERT 개념이해 #2 LayerNorm

BERT 개념이해 #2 LayerNorm #

#2026-03-04


#1 LayerNorm이 필요한 이유: 트랜스포머의 숫자가 점점 불안정해진다

트랜스포머 안에서는 벡터가 계속 변형된다. Self-Attention에서 가중합을 하고, Linear에서 섞고, Residual(Add)로 더하고, 다시 또 같은 일을 반복한다. 이 과정은 “정보를 풍부하게 만드는 과정”이지만 동시에 “숫자의 크기가 흔들리는 과정”이기도 하다. 어떤 레이어에서는 값이 커지고, 다음 레이어에서는 또 커지고, 이런 일이 누적되면 Softmax에 들어가는 값이 지나치게 커져 지수함수가 터지거나, 그래디언트가 폭발해서 학습이 불안정해질 수 있다. 반대로 값이 너무 작아져 모든 것이 비슷해지면 그래디언트가 거의 전달되지 않아 학습이 멈춘다. LayerNorm은 이 문제를 막기 위해 “각 벡터의 크기를 매번 안정된 범위로 되돌리는” 역할을 한다.

값이 너무 커지면:
  Softmax의 지수 함수 → 오버플로우
  그래디언트가 폭발(exploding gradient)

값이 너무 작아지면:
  그래디언트가 소실(vanishing gradient)
  학습이 멈춤

-> LayerNorm은 각 벡터를 "평균=0, 표준편차=1"로 정규화하여 값의 크기를 안정적으로 유지한다.

#

#2 정규화의 직관: 절대 크기를 버리고 상대 패턴만 남긴다

정규화를 시험 점수로 생각하면 제일 이해가 빠르다. 국어 95, 수학 40, 영어 72를 보면 중요한 정보는 “국어가 잘 됐고 수학이 약하다”는 상대적인 패턴이다. 그런데 절대 점수 크기는 상황에 따라 흔들릴 수 있다. 시험이 쉬우면 전체 점수가 올라가고, 어려우면 전체 점수가 내려간다. 정규화는 이런 “전체 난이도 효과”를 없애고, 대신 각 과목이 평균 대비 얼마나 위인지 아래인지 같은 상대 정보를 남긴다.

신경망 벡터에서도 똑같다. 벡터의 각 차원은 어떤 특징의 강도인데, 우리는 “전체가 갑자기 커지거나 작아지는 현상”은 없애고 싶고, 대신 “어떤 차원이 다른 차원보다 상대적으로 크다” 같은 패턴은 유지하고 싶다. LayerNorm은 바로 그 목적에 맞는 정규화다.

#

#3 LayerNorm이 실제로 하는 일: 한 토큰의 768차원을 한꺼번에 표준화한다

BERT에서는 토큰 하나가 768차원 벡터로 표현된다. LayerNorm은 이 벡터를 보고 평균을 구한다. 그리고 평균에서 얼마나 퍼져 있는지를 나타내는 분산과 표준편차를 구한다. 마지막으로 각 차원 값에서 평균을 빼고 표준편차로 나누면, 그 벡터는 평균이 0에 가깝고 표준편차가 1에 가깝게 된다.

여기서 가장 중요한 포인트는 “어느 방향으로 평균과 표준편차를 구하느냐”다. LayerNorm은 배치 전체를 섞지 않는다. 토큰 하나의 768개 값만 보고 그 안에서 평균과 표준편차를 계산한다. 그래서 배치 크기가 작든 크든 결과가 흔들리지 않는다.

BatchNorm은 이미지에서 잘 먹히는 방식이다. 같은 채널을 기준으로 배치에 있는 여러 샘플을 모아 평균과 분산을 낸다. 배치가 충분히 크고 데이터 형태가 일정하면 통계가 안정적이다.

하지만 NLP는 배치가 작을 때가 많고, 문장 길이가 계속 달라지고, 패딩이 끼어들고, 배치마다 구성도 달라진다. 이런 환경에서 BatchNorm은 통계가 불안정해질 수 있다. 반면 LayerNorm은 “각 샘플을 독립적으로” 처리하기 때문에 이런 문제를 피한다. 그래서 트랜스포머 계열 모델의 기본 정규화로 LayerNorm이 자리잡았다.

Batch Normalization (이미지에서 주로 사용): 배치 차원으로 정규화

배치:       샘플1    샘플2    샘플3
특징1:      [3.2,    2.8,     4.1]  ← 이 방향으로 평균/표준편차 계산
특징2:      [0.1,    0.3,     0.2]
특징3:      [5.5,    4.9,     6.2]

문제:
  배치가 작으면 통계가 불안정
  배치 크기에 따라 결과가 달라짐
  가변 길이 시퀀스에 적합하지 않음
Layer Normalization (Transformer에서 사용): 특징 차원으로 정규화

샘플 1의 벡터:  [3.2,  0.1,  5.5,  2.3,  4.7, ...]
                 ↑ 이 방향(768개 값)으로 평균/표준편차 계산

샘플 2의 벡터:  [2.8,  0.3,  4.9,  1.8,  5.1, ...]
                 ↑ 이것도 독립적으로 정규화

장점:
  배치 크기에 무관
  각 샘플을 독립적으로 정규화
  가변 길이 시퀀스에 자연스럽게 적용

#

#4 ε가 들어가는 이유: 나눗셈이 터지지 않게 하는 안전장치

표준편차로 나누는 순간, 표준편차가 0이면 계산이 터진다. 극단적으로 768개 값이 모두 같으면 분산이 0이고 표준편차도 0이 된다. 실제 학습에서 완전히 0인 경우는 드물지만, 수치적으로 매우 작은 값이 나오는 것은 충분히 가능하다. 그래서 분산에 아주 작은 수 ε를 더해서, 표준편차가 0이 되는 상황을 원천 차단한다. BERT에서 eps=1e-12 같은 값이 들어가는 이유는 “수치 안정성”을 확보하기 위해서다.

여기서 또 자연스러운 질문이 나온다. “정규화해서 평균 0, 표준편차 1로 고정하면 안정적이긴 한데, 그게 항상 좋은가?” 어떤 레이어는 출력이 조금 더 큰 스케일을 가져야 표현이 잘 될 수도 있고, 어떤 레이어는 특정 차원의 값이 의도적으로 치우쳐야 할 수도 있다.

그래서 LayerNorm은 정규화 후에 “조절 손잡이”를 붙인다. 각 차원마다 스케일을 조절하는 γ와, 값을 이동시키는 β를 둔다. 처음엔 γ=1, β=0으로 시작해서 “정규화 그대로” 동작하게 하고, 학습이 진행되면서 모델이 필요하면 γ를 키워 특정 차원을 더 강조하거나, β를 이동시켜 특정 차원의 기준점을 옮길 수 있게 만든다. 즉 LayerNorm은 안정성을 위해 표준화하지만, 유연성을 위해 다시 조절할 수 있는 길을 열어둔다.

단순 정규화만 하면:
  모든 레이어 출력이 항상 평균=0, 분산=1
  → 레이어가 원하는 값의 범위를 표현할 수 없음

해결: 학습 가능한 파라미터 γ(scale), β(shift) 추가

LayerNorm(x) = γ · x̂ + β

초기값:
  γ = 1 (ones)  ← 스케일링 없는 상태
  β = 0 (zeros) ← 시프트 없는 상태

학습 후:
  γ, β가 각 차원마다 최적의 값으로 업데이트
  → 레이어가 원하는 분포를 학습

#

#5 BERT에서 LayerNorm이 등장하는 위치: “더한 뒤마다” 스케일을 다시 잡는다

BERT에서 LayerNorm은 한 번만 쓰이지 않는다. 임베딩을 만들 때 Token/Position/Segment를 더한 직후에 한 번 등장한다. 이건 “입력 벡터를 트랜스포머에 넣기 전에” 스케일을 정돈하는 단계다.

γ: 768개 파라미터 (각 차원마다 하나의 스케일)
β: 768개 파라미터 (각 차원마다 하나의 시프트)
총: 1,536 파라미터

BERT 전체에서 LayerNorm이 쓰이는 곳:
  Embedding 후: 1회
  각 BERT Layer: 2회 (Attention 후, MLP 후)
  총: 1 + 12×2 = 25회
  총 파라미터: 25 × 1,536 = 38,400 (전체 대비 0.035% — 매우 작음)

그리고 각 Transformer layer 안에서 두 번 더 등장한다. Self-Attention을 통과한 뒤 Dropout을 하고 residual로 입력을 더한 다음 LayerNorm을 한다. MLP를 통과한 뒤에도 Dropout을 하고 residual로 더한 다음 LayerNorm을 한다. 이렇게 보면 LayerNorm은 트랜스포머에서 “연산을 한 번 크게 하고, 잔차로 더해서 스케일이 흔들릴 수 있는 순간마다” 다시 균형을 맞추는 장치로 배치되어 있다.

→ Embedding
     Token + Position + Segment → Add
     → LayerNorm ①   ← Embedding 정규화
     → Dropout

→ BERT Layer (×12)
   [Attention Sublayer]
     Self-Attention
     → Dropout
     → Add (residual)
     → LayerNorm ②   ← Attention 후 정규화

   [MLP Sublayer]
     Linear → GELU → Linear
     → Dropout
     → Add (residual)
     → LayerNorm ③   ← MLP 후 정규화

#

#6 정리

LayerNorm은 한 토큰의 벡터를 평균 0, 표준편차 1로 맞춰 숫자 폭주와 소실을 막는다. Batch 통계를 쓰지 않아서 배치 크기나 문장 길이 변화에 흔들리지 않는다. 그리고 γ, β로 다시 스케일과 기준점을 학습할 수 있게 해 “안정성과 표현력”을 동시에 확보한다. 그래서 BERT처럼 레이어를 깊게 쌓아도 Softmax가 터지지 않고 그래디언트가 살아있으며, 학습이 중간에 멈추지 않고 끝까지 진행될 수 있다.

예시: 벡터 x = [10.5, -3.2, 8.7, 0.1, -15.0, ...]  (768개)

정규화 전:
  값이 -15 ~ +10 사이에 넓게 퍼짐
  Self-Attention의 Softmax에서 극단값이 문제 될 수 있음

정규화 후:
  x̂ = [(10.5-μ)/σ, (-3.2-μ)/σ, (8.7-μ)/σ, ...]
  값이 대략 -2 ~ +2 사이로 압축

γ, β 적용 후:
  모델이 "이 레이어에서는 값이 약간 더 커야 한다"고 학습했다면
  γ > 1로 스케일 복원

#

#cf2 핵심 요약

  • LayerNorm = 각 토큰의 768차원 벡터를 평균=0, 분산=1로 정규화
  • Batch Norm과 달리 배치 크기에 무관 → 시퀀스 처리에 적합
  • γ(스케일), β(시프트): 학습 가능한 파라미터로 유연성 부여
  • BERT에서 25번 사용 (Embedding 후 + 각 Layer의 Attention/MLP 후)
  • 역할: 그래디언트 안정화 + 값 폭발/소실 방지
  • eps=1e-12: 표준편차=0일 때 0으로 나누는 오류 방지