5장. Decoder-only LLM과 학습 단계
사전학습: 언어와 지식을 배우는 단계
빈칸 채우기 문제집을 수만 권 푼 학생을 생각해 봅니다. "그는 어제 도서관에 ( )"를 풀려면 문법을 알아야 하고, "대한민국의 수도는 ( )이다"를 풀려면 상식을 알아야 합니다. 과제는 빈칸 하나 채우기로 단순하지만, 잘 맞히려면 문법, 어휘, 세계 지식, 간단한 추론까지 알아야 합니다. 사전학습은 이 문제집을 인터넷 규모로 푸는 단계입니다.
다음 토큰을 맞히며 배우는 것
| 배우는 것 | 사전학습 중 만나는 문장 예시 |
|---|---|
| 문법 | 그는 어제 도서관에 {갔다 / 간다} |
| 세계 지식 | 대한민국의 수도는 {서울 / 부산}이다 |
| 감정 | 이 영화는 지루해서 {최악 / 최고}이었다 |
| 계산 | 5 × 6 = {30 / 42} |
| 코드 | for i in range(10): 다음 줄의 들여쓰기 |
표의 중괄호에서 앞쪽이 자연스러운 다음 토큰입니다. "어제"가 있으니 과거형 "갔다", "지루해서"가 있으니 "최악"이 와야 합니다. 모델은 이런 판단을 수조 개 토큰에서 되풀이하며 익힙니다.
사전학습은 수천 개의 GPU 로 몇 주에서 몇 달이 걸리는 작업이라 개별 기관이 직접 하기 어렵습니다. 그래서 실무에서는 공개된 사전학습 모델(Llama, Qwen 등)을 가져와 그다음 단계(2일차의 SFT 등)부터 진행하는 경우가 대부분입니다.
짧은 예시
import pandas as pd
# 아주 작은 "인터넷": 네 문장(설명용 장난감 말뭉치)
corpus = [
"대한민국의 수도는 서울이다",
"일본의 수도는 도쿄이다",
"대한민국의 수도는 서울이다",
"프랑스의 수도는 파리이다",
]
# 문장마다 "수도는" 바로 다음 낱말을 모은다
# split() = 띄어쓰기로 나누기, index() = 그 낱말이 몇 번째인지
next_words = [s.split()[s.split().index("수도는") + 1] for s in corpus]
# value_counts(normalize=True) = 값마다 비율(합 1)로 세기
print(pd.Series(next_words).value_counts(normalize=True))
# 결과:
# 서울이다 0.50
# 도쿄이다 0.25
# 파리이다 0.25이 코드가 뜻하는 것
수습생이 책 네 권을 읽고 "수도는" 다음에 무엇이 오는지 공책에 적어 둔 것과 같습니다. 많이 본 "서울이다"가 0.50 으로 가장 높습니다. LLM 은 이 표를 단순히 세지 않고 신경망으로 배우지만, "많이 읽은 이어짐에 높은 확률을 준다"는 생각은 같습니다.
| 줄 | 하는 일 | 쉽게 말하면 |
|---|---|---|
corpus = [...] | 학습용 문장 네 개 | 수습생이 읽은 책 |
s.split().index("수도는") + 1 | "수도는" 다음 자리 | 빈칸의 위치 |
value_counts(normalize=True) | 다음 낱말의 비율 | 다음 토큰 확률표 |
pandas 의 value_counts 로 열의 분포를 보던 것과 같은 계산입니다. 실제 LLM 의 "확률표"는 어휘 151,936개 전체에 대한 비율이고, 앞 문맥이 조금만 달라도 표가 새로 계산됩니다.
주의할 점
- 모델은 읽은 글의 치우침도 함께 배웁니다. 말뭉치에 틀린 정보나 한쪽으로 치우친 표현이 많으면 그대로 따라 합니다. 데이터 품질이 곧 모델 품질입니다.
- 사전학습이 끝난 Base 모델은 질문에 답하기보다 "질문 다음에 올 법한 글"을 이어 씁니다. 질문 목록 뒤에 또 다른 질문을 늘어놓을 수도 있습니다. 대화를 잘하게 만드는 것은 다음 단계(SFT)의 몫입니다.