스킬캠퍼스

오늘 끝나면

나만의 미니 LLM 만들기

  • 나만의 미니 LLM 만들기의 핵심 문제를 한 문장으로 설명한다
  • 오른쪽 실습에서 나만의이 어떻게 움직이는지 관찰한다
  • 다음 강의와 이어지는 한계를 말할 수 있다

실습 미션

nanoGPT 스타일 — 셰익스피어로 직접 학습시킨다 이 문장이 실제로 무슨 뜻인지 실습에서 한 번 손으로 확인한다.

성공 조건

  • 실습의 기본값을 먼저 관찰
  • 입력값이나 모드를 한 번 이상 바꿔 결과 비교
  • 왜 결과가 바뀌었는지 한 문장으로 설명

AI · Day 12 / 지도학습 · 생성 DL

나만의
미니 LLM

12일의 종착점이다. GPT를 한 줄씩 직접 짜고, 학습시키고, 문장을 뽑는다.나만의 작은 AI를 노트북에서 만든다. 300줄짜리 nanoGPT면 충분하다.

P.01AI · Day 12

왜 굳이 직접 만드나

API를 1만 번 호출해도 "왜 이렇게 답하지?"는 풀리지 않는다. 소비만 해서는 내부가 보이지 않는다.

논문만 읽어도 부족하다. loss.backward()를 직접 돌려보지 않으면 "학습"이 감이 오지 않는다.

학습률을 1e-3에서 1e-4로 낮추면 loss 곡선이 어떻게 휘는지,block_size를 늘리면 메모리가 왜 O(n²)로 터지는지. 이건 만들어본 사람만 아는 감각이다.

Karpathy의 말처럼 "LLM을 이해하는 유일한 길은 직접 만들어보는 것"이다. 오늘은 그의 영상 "Let's build GPT from scratch"를 한국어로 졸업하는 버전이다.

이해의 사다리
API 콜만내부는 미궁논문 읽기감은 안 옴코드 베끼기절반의 이해직접 만들기직관이 생김이해 ↑

직접 만들어야 꼭대기 칸에 오른다. 진짜 직관이 생긴다

P.02AI · Day 12

토큰은 그냥 숫자다

토크나이저는 거창한 게 아니다.문자열을 정수 수열로 바꾸는 딕셔너리 하나일 뿐이다.

셰익스피어 텍스트 1.1MB를 쓴다. 등장한 문자를 모으니 딱 65개다.

stoi는 문자를 숫자로 바꾸고, itos는 숫자를 문자로 되돌린다. 그게 전부다. character-level이라 한국어 소설을 넣어도 코드를 고치지 않고 그대로 돌아간다.

파이썬 코드 보기
chars = sorted(set(text))      # 65개 문자
stoi = {ch: i for i, ch in enumerate(chars)}
itos = {i: ch for i, ch in enumerate(chars)}

def encode(s): return [stoi[c] for c in s]
def decode(ids): return "".join(itos[i] for i in ids)

print(encode("Hi"))   # [20, 47]
print(decode([20, 47]))   # "Hi"

GPT-4의 cl100k_base도 본질은 똑같다. vocab이 65개냐 10만 개냐의 차이뿐이다. 숫자에서 의미를 배우는 건 다음 단계 Embedding의 몫이다.

문자 ↔ 정수 매핑
"Hello" → encodeH20e43l50l50o53vocab_size = 65 (그냥 딕셔너리)

문자와 정수의 양방향 매핑이 토크나이저의 본질이다

P.03AI · Day 12

GPT는 블록 N개의 반복이다

GPT의 정체는 두 문장이면 끝난다. Attention은 사실 행렬 곱 한 번이고, GPT는 똑같은 블록의 반복이다.

입력 토큰에 Token EmbeddingPositional Embedding을 더한다. 블록 하나는 LayerNorm, Causal Attention, Residual을 거치고, 이어서 다시 LayerNorm, FeedForward, Residual로 이어진다. 이 블록을 N번 쌓고, 마지막에 Linear Head로 vocab 크기의 logits을 뽑으면 끝난다.

핵심은 causal mask다. 하삼각 행렬로 미래 토큰을 -inf로 처리한다. 각 위치가 자기 이전만 보게 된다. 이게 "다음 글자 맞히기"라는 언어모델 정의 그 자체다.

파이썬 코드 보기
wei = q @ k.transpose(-2, -1) * C ** -0.5
wei = wei.masked_fill(tril == 0, float("-inf"))
wei = softmax(wei, dim=-1)   # 미래는 가린 채
out = wei @ v                # 과거를 가중 평균

n_layer=6이면 nanoGPT이고, n_layer=96이면 GPT-3다. 아키텍처는 같다. 확장의 문제일 뿐이다.

TRANSFORMER 블록 × N
Token + Pos Emb× NLayerNormCausal Attention+ ResidualFeedForward (4×)+ ResidualLN → Linear HeadLogits (B, T, vocab)

파란 블록 하나를 N번 쌓으면 GPT가 된다. n_layer=96이면 GPT-3다

P.04AI · Day 12

학습은 loss가 떨어지는 현상

학습은 결국 loss라는 숫자가 떨어지는 현상이다.

매 스텝마다 get_batch로 임의 구간을 뽑는다. 입력 x와 한 칸 민 정답 y를 만들고, 예측과 정답의 cross-entropy를 잰다.loss.backward()로 기울기를 흘리고, optimizer.step()으로 가중치를 살짝 고친다. 이 반복이 전부다.

파이썬 코드 보기
for step in range(max_steps):
    xb, yb = get_batch("train")
    _, loss = model(xb, yb)
    optimizer.zero_grad()
    loss.backward()         # 기울기
    optimizer.step()        # 한 걸음

warmup으로 학습률을 완만히 올렸다가 cosine으로 부드럽게 내린다. 그러면 train·val loss가 4.2에서 2.1, 1.5로 우하향한다.

TRAINING CURVE
lossstep →4.22.11.5trainval

loss가 4.2, 2.1, 1.5로 우하향한다. 이게 "학습"의 전부다

P.05AI · Day 12

Temperature는 모델의 성격

학습이 끝나면 모델이 처음으로 "뭔가"를 말한다. Temperature 하나 바꿨을 뿐인데 성격이 달라진다.

같은 모델에 같은 프롬프트 ROMEO:를 넣어도 디코딩 전략이 결과를 바꾼다.

Greedy는 항상 argmax라 지루하다.Temperature는 logits을 T로 나눈다. T가 낮으면 엄격해지고 높으면 자유로워진다.Top-k는 상위 k개만 남기고, Top-p는 누적확률 p까지만 두고 샘플링한다.

여기까지가 12일의 결론이다. 사내 문서 전용 소형 LLM, 엣지용 경량 모델, 데이터가 밖으로 못 나가는 on-premise 보안 LLM, 브랜드 보이스 페르소나 LLM까지 모두 출발점은 오늘 손으로 만든 이 구조다. 차이는 파라미터와 데이터, 컴퓨트뿐이고 근본은 같다.

Q. 오늘 만든 nanoGPT와 GPT-4의 근본적 차이는?아키텍처는 본질적으로 동일하다. 차이는 다섯 가지뿐이다. 첫째 파라미터 수(M 대 T), 둘째 학습 데이터(MB 대 TB), 셋째 학습 컴퓨트, 넷째 Post-training(SFT+RLHF), 다섯째 토크나이저 크기다. 복잡해 보여도 뜯어보면 만들 수 있다는 체험이 오늘의 진짜 수확이다.
디코딩 놀이터 (직접 조작)
디코딩 놀이터 · "ROMEO:" 다음 글자를 모델이 고른다
P5621I12t5hOwz점선 = 자르기 전
출력ROMEO:
살아남은 후보
8/8
최빈 글자 확률
56%
펴짐(엔트로피)
0.62
적당히 다양해서 자연스러운 문장이 나오기 좋은 구간이다

3줄 요약

  1. 1nanoGPT 스타일 — 셰익스피어로 직접 학습시킨다
  2. 2나만의 미니 LLM 만들기은 준비운동 → 지도학습 → 시퀀스 → 생성모델 → 실무 적용 흐름 안의 한 칸이다.
  3. 3개념을 외우는 것보다 입력을 바꾸면 무엇이 달라지는지 보는 것이 우선이다.

완료 전 점검

복습 카드

나만의

nanoGPT 스타일 — 셰익스피어로 직접 학습시킨다

모델

입력을 받아 예측이나 출력을 만드는 계산 규칙

손실

예측이 정답에서 얼마나 빗나갔는지 재는 숫자