밑바닥부터 만드는 mini GPT 공부 시리즈 7편
사전학습된 GPT는 기본적으로 다음 토큰을 맞히는 모델이다. 하지만 과제의 마지막 단계에서는 NSMC 리뷰가 긍정인지 부정인지 맞히는 분류 모델로 바꾼다.
여기서 핵심은 GPT 전체를 버리는 것이 아니다. 텍스트를 읽어 hidden state를 만드는 backbone은 그대로 쓰고, 마지막 목적에 맞는 classification head를 새로 붙인다.
LM head와 classification head
| 구분 | 출력 | 목적 |
|---|---|---|
| LM head | vocab_size개 점수 | 다음 토큰 예측 |
| classification head | 2개 점수 | 부정/긍정 분류 |
이번 단계의 입력과 정답
{"text": "배우들의 연기가 좋고 끝까지 몰입됐다.", "label": 1}
{"text": "전개가 지루하고 결말도 아쉬웠다.", "label": 0}
사전학습에서는 문장 안의 다음 token이 정답이었다. 미세조정에서는 문장 하나에 label 하나가 붙는다. 이 차이 때문에 출력층도 바뀌어야 한다.
1. 리뷰 전체를 대표하는 벡터가 필요하다
GPT backbone은 각 token 위치마다 hidden state를 만든다. 하지만 감성 분류는 리뷰 전체에 대해 하나의 label만 필요하다. 그래서 여러 hidden state 중 문장을 대표할 하나를 골라 classifier에 넣는다.
2. classification head는 vocab이 아니라 label을 본다
사전학습의 `lm_head`는 hidden state 하나를 `vocab_size`개의 점수로 바꾼다. 감성 분류에서는 “다음 token 후보 전체”가 필요하지 않다. 필요한 것은 부정과 긍정 두 개의 점수다.
문장 대표 hidden state: (B, C)
classifier: Linear(C, 2)
logits: (B, 2)
그래서 GPT backbone은 재사용하지만, 마지막 head는 과제 목적에 맞게 바꿔 끼운다.
3. padding은 분류 위치 선택에서 제외해야 한다
리뷰 길이는 제각각이다. batch로 묶기 위해 짧은 리뷰는 pad token으로 채운다. 이때 마지막 위치를 무조건 고르면 pad의 hidden state를 대표 벡터로 쓰는 실수가 생긴다.
마지막 token이 아니라, padding이 아닌 마지막 유효 token의 hidden state를 골라야 한다.
input_ids:
[좋다, 영화, <eos>, <pad>, <pad>]
대표 위치:
마지막 index 4가 아니라, 마지막 유효 token인 <eos> 위치 2
4. 미세조정에서 학습되는 것은 “분류 기준”이다
backbone은 문장을 hidden state로 바꾸는 역할을 한다. classifier는 그 hidden state를 보고 부정/긍정 기준을 학습한다. 이때 loss는 다음 token 예측용 cross entropy가 아니라 label 0/1에 대한 cross entropy다.
각 위치마다 다음 token ID를 맞힌다.
리뷰 전체의 label 0/1을 맞힌다.
스스로 점검
- 감성 분류에서 LM head를 그대로 쓰면 왜 맞지 않는가?
- 리뷰 전체 label을 예측하려면 token별 hidden state 중 무엇을 선택해야 하는가?
- padding 위치를 대표 벡터로 쓰면 어떤 문제가 생기는가?
- 사전학습 loss와 분류 미세조정 loss는 무엇이 다른가?
시리즈 마무리
여기까지 오면 mini GPT 구현의 큰 흐름은 연결된다. 텍스트는 BPE로 token ID가 되고, Dataset과 Embedding을 거쳐 attention과 Transformer block을 통과하고, 사전학습 또는 분류 미세조정 목표에 맞게 loss를 계산한다.
한 줄 정리: 미세조정은 GPT backbone의 문장 이해 흐름을 재사용하고, 마지막 목적에 맞는 작은 head를 새로 붙이는 과정이다.