BERT 뉴스 분류 #3 레이어별 차등 학습률 #
#2026-03-01
#1 BERT의 12개 레이어
BERT 안에 Transformer 인코더가 12개 쌓여 있다고 했다. 이 12개 레이어가 전부 똑같은 역할을 하는 걸까? 아니다. 연구자들이 각 레이어가 무엇을 학습하는지 분석해보니, 하위 레이어와 상위 레이어가 포착하는 정보의 종류가 확연히 달랐다.
레이어 0~ 3: 문법, 형태소, 기본 구문 ← 범용 언어 지식
레이어 4~ 7: 구문 구조, 의존 관계
레이어 8~11: 의미, 문맥, 과제 특화 ← 뉴스 분류에 직접 관련
하위 레이어(0~3번 근처)는 문법적이고 형태적인 기본 지식을 담고 있다. 주어와 동사의 수 일치, 품사 구분, 기본적인 구문 구조 같은 것이다. 이런 지식은 영어라는 언어 자체의 규칙이라서 뉴스 분류를 하든, 감정 분석을 하든, 번역을 하든 보편적으로 필요하다.
상위 레이어(8~11번 근처)는 훨씬 추상적이고 과제에 특화된 정보를 담는다. 문장 전체의 의미, 단어들 사이의 복잡한 문맥 관계, 그리고 특정 과제(우리의 경우 뉴스 카테고리 판단)에 직접적으로 유용한 표현을 만들어낸다. 이 관찰은 Conv1D를 여러 겹 쌓았을 때의 패턴과 놀랍도록 유사하다. DNA 분석에서 첫 번째 Conv1D가 기본 모티프(개별 글자 패턴)를 잡고, 두 번째가 모티프 조합을, 세 번째가 전체적인 구조 패턴을 잡았던 것처럼, BERT의 하위 레이어는 언어의 기본 단위를 처리하고 상위 레이어는 의미의 큰 그림을 처리한다.
즉 하위 레이어의 범용 언어 지식은 뉴스 분류에도 그대로 유용하니까 굳이 바꿀 필요가 없다. 그대로 두고 상위 레이어만 뉴스 분류에 맞게 조정하면 된다.
#
#2 레이어 동결
# 임베딩 레이어 동결
for param in model.bert.embeddings.parameters():
param.requires_grad = False
# 하위 6개 레이어(0~5) 동결
for i in range(6):
for param in model.bert.encoder.layer[i].parameters():
param.requires_grad = False
# 학습되는 부분: layer 6~11 + 분류 헤드
# 동결된 파라미터: 약 52M / 전체 110M
# 실제 학습 파라미터: 약 60M
이것이 레이어 동결(Layer Freezing)이다. requires_grad = False를 설정하면 해당 파라미터는 학습 과정에서 업데이트되지 않는다. 그래디언트가 계산되지 않으니 값이 변하지 않는다. 사전학습에서 배운 상태 그대로 얼어붙는 것이다. 코드를 보면 임베딩 레이어와 하위 6개 레이어(0~5번)를 동결한다. 전체 1억 1천만 개 파라미터 중 약 5,200만 개가 동결되어 실제로 학습되는 파라미터는 약 6,000만 개로 줄어든다. 거의 절반이 줄어드는 셈이다.
[임베딩] ← 동결 (사전학습 토큰 표현 유지)
[레이어 0] ← 동결
[레이어 1] ← 동결 범용 언어 지식 보존
[레이어 2] ← 동결
[레이어 3] ← 동결
[레이어 4] ← 동결
[레이어 5] ← 동결
─────────────────────
[레이어 6] ← 학습
[레이어 7] ← 학습
[레이어 8] ← 학습 뉴스 분류 특화 조정
[레이어 9] ← 학습
[레이어 10] ← 학습
[레이어 11] ← 학습
[분류 헤드] ← 학습 (랜덤 초기화)
# 이것은 Conv1D 모델에서 "이 문제를 풀기 위해 레이어 수를 몇 개 쌓을 것인가"를 결정한 것과 같은 질문이다. BERT에서는 "이 문제를 풀기 위해 몇 개 레이어까지 건드릴 것인가"를 결정하는 것이다.
이 전략의 이점은 세 가지다. 첫째, 학습할 파라미터가 줄어드니 같은 양의 데이터로도 과적합이 덜 생긴다. 파라미터가 많을수록 훈련 데이터를 외워버리기 쉬운데, 절반이 고정되어 있으면 그만큼 외울 여지가 줄어든다. 둘째, 그래디언트를 절반의 파라미터에 대해서만 계산하면 되니까 학습 속도가 빨라진다. 셋째, 가장 중요한 이점으로, 사전학습 지식이 보존된다. 하위 레이어의 범용 언어 이해 능력이 파인튜닝 과정에서 손상될 위험이 원천적으로 차단된다.
이걸 DNA 분석과 연결해서 생각하면 흥미로운 대비가 보인다. DNA 모델에서는 “이 문제에 Conv1D 레이어를 몇 겹 쌓을 것인가"를 결정했다. 101bp 서열에는 3겹, 21bp 서열에는 2겹을 골랐다. BERT에서는 레이어가 이미 12개 고정되어 있으니, 대신 “이 12개 중 몇 개를 실제로 학습시킬 것인가"를 결정하는 것이다. 문제의 형태는 다르지만, “모델의 용량을 과제의 복잡도에 맞게 조절한다"는 본질은 동일하다.
#
#3 레이어별 차등 학습률 (Layer-wise LR Decay)
동결은 효과적이지만 이진적이다. 학습하거나 안 하거나, 둘 중 하나다. 레이어 5는 완전히 얼어 있고 레이어 6은 완전히 풀려 있다. 경계가 칼로 자른 듯 뚜렷하다.
하지만 현실에서 레이어의 역할은 그렇게 깔끔하게 나뉘지 않는다. 레이어 5의 지식도 뉴스 분류에 약간은 조정이 필요할 수 있고, 레이어 6의 지식도 대부분은 보존해야 할 수 있다. “전부 얼리거나 전부 풀거나"보다 더 세밀한 조절이 가능하지 않을까?
차등 학습률(Layer-wise Learning Rate Decay)이 바로 그 해결책이다. 각 레이어에 서로 다른 학습률을 부여하는 것이다. 상위 레이어일수록 학습률이 크고, 하위 레이어로 갈수록 학습률이 작아진다. 완전히 동결하는 대신, 하위 레이어도 아주 살짝은 조정할 여지를 남기되 그 정도를 최소화하는 것이다.
optimizer_grouped_parameters = []
base_lr = 3.5e-5
decay = 0.9 # 한 레이어 내려갈 때마다 0.9배
# 분류 헤드: 가장 큰 학습률 (랜덤 초기화 → 많이 바꿔야 함)
optimizer_grouped_parameters.append({
"params": model.classifier.parameters(),
"lr": 3.6e-5
})
# Transformer 레이어 11 → 0: 점점 작은 학습률
for i in range(11, -1, -1):
optimizer_grouped_parameters.append({
"params": model.bert.encoder.layer[i].parameters(),
"lr": base_lr * (decay ** (11 - i))
})
# 임베딩: 가장 작은 학습률
optimizer_grouped_parameters.append({
"params": model.bert.embeddings.parameters(),
"lr": base_lr * (decay ** 12)
})
optimizer = AdamW(optimizer_grouped_parameters)
코드를 보면 분류 헤드의 학습률이 3.6e-5로 가장 크다. 이건 랜덤 초기화에서 시작하는 부분이니까 가장 많이 바꿔야 한다. 레이어 11의 학습률은 3.5e-5로 거의 비슷하다. 과제에 가장 특화된 최상위 레이어니까 적극적으로 조정한다. 여기서부터 레이어가 하나 내려갈 때마다 학습률에 0.9를 곱한다. 레이어 10은 3.15e-5, 레이어 9는 2.84e-5, 이런 식으로 줄어든다. 맨 아래 임베딩 레이어에 도달하면 0.99e-5까지 내려간다. 최상위 학습률의 약 4분의 1 수준이다.
# 실제 학습률 분포:
분류 헤드: 3.60e-5 (가장 크게)
레이어 11: 3.50e-5
레이어 10: 3.15e-5 (× 0.9)
레이어 9: 2.84e-5 (× 0.9²)
레이어 8: 2.55e-5
레이어 7: 2.30e-5
레이어 6: 2.07e-5
레이어 5: 1.86e-5
레이어 4: 1.67e-5
레이어 3: 1.51e-5
레이어 2: 1.36e-5
레이어 1: 1.22e-5
레이어 0: 1.10e-5
임베딩: 0.99e-5 (가장 작게)
0.9를 반복해서 곱하니까 이건 기하급수적 감쇠다. VAE 학습에서 ExponentialDecay로 시간이 지남에 따라 학습률을 줄였던 것과 같은 수학적 구조인데, 적용되는 축이 다르다. 거기서는 “학습 초반에는 크게, 후반에는 작게"라는 시간 축의 감쇠였다. 여기서는 “상위 레이어는 크게, 하위 레이어는 작게"라는 깊이 축의 감쇠다.
이 전략이 직관적으로 왜 합리적인지를 생각해보자. 임베딩 레이어는 각 토큰의 기본 표현을 담고 있다. “the"라는 단어의 벡터 표현은 뉴스 분류를 하든 감정 분석을 하든 거의 같아야 한다. 이걸 크게 바꾸면 BERT가 “the"의 의미를 잊어버리는 것과 같다. 그래서 학습률이 가장 작다. 반면 레이어 11은 입력 문장의 최종적인 의미 표현을 만드는 곳이다. “이 문장이 스포츠에 관한 것인가 경제에 관한 것인가"를 판단하는 데 가장 직접적으로 관여하므로, 뉴스 분류에 맞게 적극적으로 조정해야 한다. 그래서 학습률이 가장 크다.
# 왜 log 스케일 감쇠인가?
- 레이어마다 역할이 다르니 학습 강도도 달라야 한다. 0.9씩 곱하면 위에서 아래로 갈수록 기하급수적으로 줄어든다.
- 이것은 이전 VAE에서 `ExponentialDecay`로 시간에 따라 학습률을 줄인 것과 같은 발상이다. 거기서는 시간축으로 감쇠했고, 여기서는 레이어 깊이 축으로 감쇠한다.
AdamW 옵티마이저에 파라미터 그룹별로 다른 학습률을 지정할 수 있다는 점이 이 구현을 가능하게 한다. 보통은 모델 전체에 하나의 학습률을 쓰지만, PyTorch의 옵티마이저는 파라미터를 그룹으로 나눠서 각 그룹에 다른 학습률을 적용할 수 있다. 이 기능을 활용해서 14개 그룹(분류 헤드 1개 + 레이어 12개 + 임베딩 1개)에 각각 다른 학습률을 배정하는 것이다.
#
#4 정리
동결과 차등 학습률은 같은 스펙트럼 위에 있다. 동결은 차등 학습률의 극단적인 경우다. 학습률을 0으로 설정하면 동결과 같은 효과가 난다. 차등 학습률은 동결을 일반화한 것으로, 0과 최대값 사이의 연속적인 값을 허용한다.
실무에서는 둘 중 하나를 선택하거나 둘을 조합할 수 있다. 하위 6개 레이어를 완전히 동결하고, 나머지 6개 레이어에만 차등 학습률을 적용하는 것도 가능하다. 어떤 전략이 최적인지는 데이터의 양, 과제의 특성, 사전학습 데이터와 파인튜닝 데이터의 유사도에 따라 달라진다. 뉴스 텍스트는 위키피디아와 상당히 유사하므로 하위 레이어의 지식이 대부분 유효하다. 만약 파인튜닝 데이터가 의학 논문이나 법률 문서처럼 사전학습 데이터와 아주 다른 도메인이라면, 하위 레이어도 더 많이 조정해야 할 수 있다.