Ch.8 PyTorch로 나만의 AI 만들기
TinyLM — 세상에서 가장 작은 언어모델
지금까지 배운 모든 것이 여기에 모인다
토큰화(Ch3), 임베딩(Ch4), Softmax와 Cross-Entropy(Ch5), 역전파와 경사하강법(Ch6) — 이 모든 것을 조합해 진짜 언어모델을 만듭니다.
100줄의 코드로 GPT와 같은 구조의 모델을 만들 수 있을까?
TinyLM — 세상에서 가장 작은 언어모델. 구조는 GPT와 완전히 동일하고, 차이는 오직 규모뿐입니다.
핵심 내용
모든 챕터의 개념이 하나의 모델에 통합됩니다
'나는 고양이를 좋아한다'로 LLM을 학습합니다
💡 PyTorch는 로컬 환경에서 실행하세요 (pip install torch)
import torch
import torch.nn as nn
# === 세상에서 가장 작은 언어모델 ===
# --- 1. 데이터 준비 (Ch2) ---
text = "나는 고양이를 좋아한다 나는 강아지를 좋아한다"
words = text.split()
# --- 2. 토큰화 (Ch3) ---
vocab = {word: i for i, word in enumerate(sorted(set(words)))}
vocab_size = len(vocab)
print(f"어휘: {vocab}")
print(f"어휘 크기: {vocab_size}")
X_train, Y_train = [], []
for i in range(len(words) - 1):
X_train.append(vocab[words[i]])
Y_train.append(vocab[words[i+1]])
X = torch.tensor(X_train)
Y = torch.tensor(Y_train)
# --- 3. 모델 정의 (Ch4 + Ch8) ---
class TinyLM(nn.Module):
def __init__(self, vocab_size, embed_dim=16):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim)
self.output = nn.Linear(embed_dim, vocab_size)
def forward(self, x):
embeds = self.embedding(x)
logits = self.output(embeds)
return logits
model = TinyLM(vocab_size)
params = sum(p.numel() for p in model.parameters())
print(f"파라미터 수: {params:,}\n")
# --- 4. 학습 (Ch5 + Ch6) ---
criterion = nn.CrossEntropyLoss() # Ch5
optimizer = torch.optim.SGD(model.parameters(), lr=0.1) # Ch6
print("=== 학습 시작 ===")
for epoch in range(100):
logits = model(X)
loss = criterion(logits, Y)
optimizer.zero_grad()
loss.backward() # Ch6 역전파
optimizer.step()
if epoch % 20 == 0:
print(f" Epoch {epoch:3d}: 손실 = {loss.item():.4f}")
# --- 5. 추론 (Ch5 Softmax) ---
print("\n=== 추론 (다음 단어 예측) ===")
idx_to_word = {i: w for w, i in vocab.items()}
for word in ["나는", "고양이를"]:
if word in vocab:
input_id = torch.tensor([vocab[word]])
with torch.no_grad():
logits = model(input_id)
probs = torch.softmax(logits, dim=-1)
print(f"\n'{word}' 다음에 올 단어:")
for idx in range(vocab_size):
w = idx_to_word[idx]
p = probs[0][idx].item()
bar = "█" * int(p * 30)
print(f" {w:8s}: {p:.3f} {bar}")실행 결과 (예시)
기본 원리는 동일하다 규모와 트랜스포머 구조의 깊이만 다르다
핵심 메시지: 구조는 완전히 동일합니다. 차이는 오직 규모뿐. TinyLM에 어텐션 층을 추가하고, 어휘 사전을 50,000개로 늘리고, 수조 개의 데이터로 학습하면 → GPT와 같은 모델이 됩니다. 여러분은 이미 LLM의 핵심 원리를 모두 이해했습니다!
순수 파이썬으로 미니 언어모델의 학습 루프를 돌려봅시다
import math
import random
random.seed(42)
# === TinyLM: 순수 파이썬 미니 언어모델 ===
# 어휘 사전 (토큰화)
vocab = {"나는": 0, "AI를": 1, "공부": 2, "한다": 3}
idx2word = {v: k for k, v in vocab.items()}
V = len(vocab) # 어휘 크기
# 학습 데이터: "나는" → "AI를", "AI를" → "공부", "공부" → "한다"
data = [(0, 1), (1, 2), (2, 3)]
# 임베딩 + 출력 가중치 (랜덤 초기화)
embed = [[random.gauss(0, 0.5) for _ in range(8)] for _ in range(V)]
W_out = [[random.gauss(0, 0.3) for _ in range(V)] for _ in range(8)]
def softmax(logits):
mx = max(logits)
exps = [math.exp(x - mx) for x in logits]
s = sum(exps)
return [e / s for e in exps]
def cross_entropy(probs, target):
return -math.log(probs[target] + 1e-9)
# 학습 루프
lr = 0.5
for epoch in range(30):
total_loss = 0
for x_idx, y_idx in data:
# 순전파: 임베딩 → 선형 → softmax
h = embed[x_idx]
logits = [sum(h[k] * W_out[k][j] for k in range(8)) for j in range(V)]
probs = softmax(logits)
loss = cross_entropy(probs, y_idx)
total_loss += loss
# 역전파 (수동): dL/d_logits
d_logits = list(probs)
d_logits[y_idx] -= 1 # softmax + CE 기울기
# 가중치 업데이트
for k in range(8):
for j in range(V):
W_out[k][j] -= lr * h[k] * d_logits[j]
embed[x_idx][k] -= lr * sum(W_out[k][j] * d_logits[j] for j in range(V))
if epoch % 5 == 0:
print(f"에폭 {epoch:2d} | 손실: {total_loss:.4f}")
# 추론: 다음 단어 예측
print("\n--- 추론 결과 ---")
for word, idx in vocab.items():
h = embed[idx]
logits = [sum(h[k] * W_out[k][j] for k in range(8)) for j in range(V)]
probs = softmax(logits)
pred = max(range(V), key=lambda j: probs[j])
print(f" {word} → {idx2word[pred]} (확률 {probs[pred]:.1%})")TinyLM의 학습 루프에서 올바른 순서는?
TinyLM과 GPT-3는 모두 토큰→임베딩→변환→출력의 기본 원리를 공유한다.
TinyLM 학습 루프에서 경사하강법 optimizer의 zero_grad()를 호출하는 이유는?
다음 학습 루프 코드의 빈칸을 채우세요. optimizer.zero_grad() output = model(X) loss = criterion(output, Y) loss.backward() optimizer.___()
optimizer.___()
TinyLM의 파라미터 수는 GPT-3(1750억 개)의 약 몇 배인가요?
LLM 개발자의 첫걸음 완료!
핵심 용어
**Ch2**
데이터 준비 (text.split())
**Ch3**
토큰화 ({word: id} 딕셔너리)
**Ch4**
임베딩 (nn.Embedding) + 행렬곱 (nn.Linear)
**Ch5**
소프트맥스 + 크로스 엔트로피 손실
**Ch6**
역전파 (loss.backward()) + 경사하강법 (SGD)
**Ch7**
어텐션 구조 (TinyLM 확장 시)
**Ch8**
PyTorch nn.Module로 모델 정의
정리 노트
TinyLM — 모든 챕터의 개념이 하나로 통합
TinyLM에 사용된 개념 (챕터별)
- Ch2 데이터 준비
- text.split()으로 단어 분리
- Ch3 토큰화
- {word: id} 딕셔너리로 단어→숫자 변환
- Ch4 임베딩
- nn.Embedding으로 토큰 ID → 벡터
- Ch5 확률
- Softmax + Cross-Entropy로 손실 계산
- Ch6 역전파
- loss.backward() + SGD로 파라미터 업데이트
- Ch8 모델 정의
- nn.Module 상속하여 TinyLM 클래스 구현
학습 루프 순서
- 1. 순전파
- logits = model(X) — forward() 자동 호출
- 2. 손실 계산
- loss = criterion(logits, Y) — Cross-Entropy
- 3. 기울기 초기화
- optimizer.zero_grad() — 이전 기울기 제거
- 4. 역전파
- loss.backward() — 모든 파라미터 기울기 계산
- 5. 업데이트
- optimizer.step() — 경사하강법으로 파라미터 조정
TinyLM과 GPT-3의 차이는 오직 규모뿐 — 기본 원리는 완전히 동일하다
시각 자료
핵심 정리
- 1Ch1-2: Python 기초와 AI 역사
- 2Ch3: 토큰화 — 텍스트를 숫자로 (BPE)
- 3Ch4: 벡터와 행렬 — 의미를 수학으로
- 4Ch5: 확률 — Softmax, Temperature, Cross-Entropy
- 5Ch6: 미적분 — 경사하강법과 역전파
- 6Ch7: Attention — 모든 수학의 집대성
- 7Ch8: PyTorch로 나만의 TinyLM 구현!
퀴즈와 인터랙션으로 더 깊이 학습하세요
play_circle인터랙티브 레슨 시작