microGPT로 보는 역전파와 GPT의 정수
microGPT로 보는 역전파와 GPT의 정수
LLM이 실제로 뭘 하는 건지 한눈에 보려면, 의존성 없는 순수 파이썬 200줄짜리 microgpt를 읽는 게 가장 확실해요. 이 한 파일 안에 데이터셋·토크나이저·자동 미분 엔진·GPT-2형 신경망·Adam 옵티마이저·학습 루프·추론 루프가 전부 들어 있어요. 나머지는 모두 "효율성"의 문제일 뿐이라는 관점에서, 마이크로그래드류 단순화의 정점이에요.
토크나이저
신경망은 숫자만 다루니 텍스트를 정수 토큰 id로 바꿔야 해요. 가장 단순한 토크나이저는 데이터셋의 고유 문자 하나에 정수 하나를 붙이는 방식이에요. 여기에 문서의 시작/끝을 알리는 특수 토큰 BOS(Beginning of Sequence)를 하나 더해요. 이름 데이터 32,000개를 쓰는 예제에서는 알파벳 26자에 BOS까지 총 27개 토큰이 돼요.
# Let there be a Tokenizer to translate strings to discrete symbols and back
uchars = sorted(set(''.join(docs))) # unique characters in the dataset become token ids 0..n-1
BOS = len(uchars) # token id for the special Beginning of Sequence (BOS) token
vocab_size = len(uchars) + 1 # total number of unique tokens, +1 is for BOS
역전파의 본질
Value가 스칼라 하나(.data)와 어떻게 계산됐는지(_children, _local_grads)를 기억해요. 모든 연산은 forward 값을 만들고, 자신의 출력이 각 입력에 대해 어떻게 변하는지(local gradient)를 안다. backward()는 그래프를 역토폴로지 순서로 훑으며 체인 룰을 적용해요. 그래프가 분기하면 각 경로에서 흐른 그래디언트를 합산(+)해야 해요 — 다변수 체인 룰의 결과예요.
a = Value(2.0)
b = Value(3.0)
c = a * b # c = 6.0
L = c + a # L = 8.0
L.backward()
print(a.grad) # 4.0 (dL/da = b + 1 = 3 + 1, via both paths)
print(b.grad) # 2.0 (dL/db = a = 2)
PRNG·GPT와의 연결점
microGPT가 이름을 "환각"해서 만들어내는 것(karia, kamon 같은)은 ChatGPT가 그럴듯한 거짓말을 하는 것과 같은 현상이에요. 둘 다 "통계적으로 그럴듯한 완성"일 뿐이에요. 학습을 더 오래 하거나 모델을 키우거나(n_embd, n_layer, n_head) 데이터셋을 바꾸면 더 나은 결과가 나와요. 데이터셋만 바꾸면 나머지 코드는 그대로인 채 다른 패턴을 배워요.