karpathy/nanoGPT
요약
Karpathy의 nanoGPT 저장소는 중간 크기의 GPT 모델을 빠르고 단순하게 훈련 및 미세 조정할 수 있는 도구입니다. 실용성을 강조하여 설계되었으며, GPT-2 수준의 모델을 재현하거나 사용자 맞춤형 모델을 구축하기에 용이합니다.
핵심 포인트
- 중간 크기 GPT 모델의 훈련 및 미세 조정을 위한 단순하고 빠른 저장소
- OpenAI GPT-2 가중치 로드 및 재현 가능
- 약 300줄 규모의 간결한 코드로 구성되어 가독성과 수정 용이성 확보
- 단일 GPU 환경에서도 셰익스피어 데이터셋 등을 활용한 빠른 학습 지원
2025년 11월 업데이트 nanoGPT에는 nanochat라는 새롭고 개선된 사촌 모델이 있습니다. 아마도 nanochat을 사용하거나 찾으려 하셨을 가능성이 매우 높습니다. nanoGPT (이 저장소)는 이제 매우 오래되었고 더 이상 권장되지 않지만(deprecated), 기록을 위해 남겨둡니다.
중간 크기의 GPT를 훈련/미세 조정 (finetuning)하기 위한 가장 단순하고 빠른 저장소입니다. 이는 교육보다는 실용성 (teeth)을 우선시하여 minGPT를 재작성한 것입니다. 여전히 활발히 개발 중이지만, 현재 train.py 파일은
단일 8XA100 40GB 노드에서 약 4일간의 훈련을 통해 OpenWebText 상에서 GPT-2 (124M)를 재현합니다. 코드 자체는 단순하고 읽기 쉽습니다: train.py는
약 300줄 규모의 보일러플레이트 (boilerplate) 훈련 루프이며, model.py는
약 300줄 규모의 GPT 모델 정의로, 선택적으로 OpenAI의 GPT-2 가중치를 로드할 수 있습니다. 그게 전부입니다.
코드가 매우 단순하기 때문에, 사용자의 필요에 맞게 해킹하거나, 처음부터 새로운 모델을 훈련하거나, 사전 훈련된 체크포인트 (pretrained checkpoints)를 미세 조정하기가 매우 쉽습니다 (예: 현재 시작점으로 사용할 수 있는 가장 큰 모델은 OpenAI의 GPT-2 1.3B 모델입니다).
pip install torch numpy transformers datasets tiktoken wandb tqdm
의존성 (Dependencies):
- pytorch <3
- numpy <3
transformers(huggingface transformers <3, GPT-2 체크포인트를 로드하기 위함)
datasets(huggingface datasets <3, OpenWebText를 다운로드 및 전처리하려는 경우)
tiktoken(OpenAI의 fast BPE 코드 <3)
wandb(선택적인 로깅 <3)
tqdm(진행 표시줄 <3)
만약 당신이 딥러닝 전문가가 아니며, 그저 마법 같은 경험을 하고 입문해보고 싶다면, 가장 빠르게 시작하는 방법은 셰익스피어의 작품들로 문자 수준 (character-level) GPT를 훈련하는 것입니다. 먼저, 이를 단일 (1MB) 파일로 다운로드하고 원문 텍스트를 하나의 커다란 정수 스트림 (stream of integers)으로 변환합니다:
python data/shakespeare_char/prepare.py
이 과정은 해당 데이터 디렉토리에 train.bin과 val.bin을 생성합니다. 이제 당신의 GPT를 훈련할 시간입니다. 모델의 크기는 시스템의 계산 자원 (computational resources)에 크게 따라 달라집니다:
GPU가 있습니다. 좋습니다, config/train_shakespeare_char.py 설정 파일에 제공된 설정으로 작은 GPT (baby GPT)를 빠르게 훈련할 수 있습니다:
python train.py config/train_shakespeare_char.py
파일 내부를 살펴보면, 최대 256자의 컨텍스트 크기 (context size), 384개의 피처 채널 (feature channels)을 가진 GPT를 훈련하며, 각 레이어에 6개의 헤드 (heads)를 가진 6개 레이어의 트랜스포머 (Transformer) 모델임을 알 수 있습니다. 하나의 A100 GPU에서 이 훈련 실행은 약 3분이 소요되며, 최적의 검증 손실 (validation loss)은 1.4697입니다. 설정에 따라 모델 체크포인트 (model checkpoints)는 --out_dir 디렉토리인 out-shakespeare-char 에 기록됩니다. 따라서 훈련이 완료되면 샘플링 스크립트가 이 디렉토리를 가리키도록 하여 최적의 모델로부터 샘플을 추출할 수 있습니다:
python sample.py --out_dir=out-shakespeare-char
그러면 다음과 같은 몇 가지 샘플이 생성됩니다:
ANGELO:
And cowards it be strawn to my bed,
And thrust the gates of my threats,
...
lol ¯\_(ツ)_/¯
GPU에서 3분 동안 훈련한 문자 수준 (character-level) 모델치고는 나쁘지 않습니다. 대신 이 데이터셋에 대해 사전 훈련된 (pretrained) GPT-2 모델을 미세 조정 (finetuning)하면 훨씬 더 나은 결과를 얻을 가능성이 매우 높습니다 (나중에 미세 조정 섹션을 참조하세요).
MacBook만 있습니다 (또는 다른 저렴한 컴퓨터). 걱정 마세요, 여전히 GPT를 훈련할 수 있지만 설정을 한 단계 낮춰야 합니다. 현재 코드를 더 효율적으로 만들어 줄 가능성이 매우 높은 최신 PyTorch nightly 버전을 사용하는 것을 권장합니다 (설치 시 여기서 선택하세요). 하지만 이를 사용하지 않더라도, 간단한 훈련 실행은 다음과 같이 구성될 수 있습니다:
python train.py config/train_shakespeare_char.py --device=cpu --compile=False --eval_iters=20 --log_interval=1 --block_size=64 --batch_size=12 --n_layer=4 --n_head=4 --n_embd=128 --max_iters=2000 --lr_decay_iters=2000 --dropout=0.0
여기서 GPU 대신 CPU에서 실행하므로 --device=cpu를 설정해야 하며, --compile=False를 통해 PyTorch 2.0 컴파일 (compile) 기능을 꺼야 합니다. 그런 다음 평가할 때는 조금 더 노이즈가 있지만 더 빠른 추정치를 얻게 됩니다 (--eval_iters=20
, 200에서 감소), 컨텍스트 크기 (context size)는 256 대신 64자뿐이며, 배치 크기 (batch size)는 반복당 64가 아닌 12개의 예시뿐입니다. 또한 훨씬 더 작은 Transformer (4개 레이어, 4개 헤드, 128 임베딩 크기)를 사용하고, 반복 횟수를 2000회로 줄입니다 (그리고 이에 따라 보통 --lr_decay_iters를 사용하여 학습률 (learning rate)을 max_iters 근처까지 감쇠시킵니다). 네트워크가 매우 작기 때문에 규제 (regularization)도 완화합니다 (--dropout=0.0). 이 방식은 여전히 약 3분 정도 소요되지만, 손실 (loss) 값은 1.88에 불과하여 결과 샘플도 더 좋지 않지만, 여전히 재미있습니다:
python sample.py --out_dir=out-shakespeare-char --device=cpu
다음과 같은 샘플을 생성합니다:
GLEORKEN VINGHARD III:
Whell's the couse, the came light gacks,
And the for mought you in Aut fries the not high shee
...
CPU에서 약 3분 만에 올바른 캐릭터 게슈탈트 (character gestalt)의 기미를 보여준다는 점에서 나쁘지 않습니다. 더 오래 기다릴 의향이 있다면, 하이퍼파라미터 (hyperparameters)를 조정하거나, 네트워크 크기, 컨텍스트 길이 (--block_size), 학습 기간 등을 늘려보세요.
마지막으로, Apple Silicon Macbook과 최신 PyTorch 버전을 사용하는 경우 --device=mps ("Metal Performance Shaders"의 약자)를 반드시 추가하세요. 그러면 PyTorch가 온칩 (on-chip) GPU를 사용하여 훈련을 상당히 가속화(2-3배)할 수 있으며 더 큰 네트워크를 사용할 수 있게 해줍니다. 자세한 내용은 Issue 28을 참조하세요.
더 진지한 딥러닝 전문가라면 GPT-2 결과를 재현하는 데 더 관심이 있을 수 있습니다. 그럼 시작해 보겠습니다. 먼저 데이터셋을 토큰화 (tokenize)하는데, 이 경우에는 OpenAI의 (비공개) WebText를 공개적으로 재현한 OpenWebText를 사용합니다:
python data/openwebtext/prepare.py
이 명령은 OpenWebText 데이터셋을 다운로드하고 토큰화합니다. 그러면 GPT2 BPE 토큰 ID를 하나의 시퀀스로 담고 있는 train.bin과 val.bin 파일을 생성하며, 이는 원시 uint16 바이트로 저장됩니다. 이제 훈련을 시작할 준비가 되었습니다. GPT-2 (124M)를 재현하려면 최소 8X A100 40GB 노드가 필요하며 다음을 실행합니다:
torchrun --standalone --nproc_per_node=8 train.py config/train_gpt2.py
이 과정은 PyTorch Distributed Data Parallel (DDP)를 사용하여 약 4일 동안 실행되며, 손실(loss) 값은 약 2.85까지 내려갑니다. 현재 OWT에서 막 평가된 GPT-2 모델은 약 3.11의 검증 손실(val loss)을 기록하지만, 이를 미세 조정(finetune)하면 (명백한 도메인 차이로 인해) 약 2.85 영역까지 내려가게 되어 두 모델이 거의 비슷해집니다.
만약 클러스터 환경에 있고 여러 개의 GPU 노드를 사용할 수 있는 축복을 받았다면, 예를 들어 다음과 같이 2개의 노드에 걸쳐 GPU를 풀가동(go brrrr)할 수 있습니다:
# 예시 IP 123.456.123.456를 사용하는 첫 번째 (마스터) 노드에서 실행:
torchrun --nproc_per_node=8 --nnodes=2 --node_rank=0 --master_addr=123.456.123.456 --master_port=1234 train.py
# 워커(worker) 노드에서 실행:
...
상호 연결(interconnect) 성능을 벤치마킹(예: iperf3)해 보는 것이 좋습니다. 특히, Infiniband가 없다면 위의 실행 명령 앞에 NCCL_IB_DISABLE=1을 추가하십시오.
멀티 노드 학습이 작동은 하겠지만, 아마도 매우 느릿느릿하게(crawl) 진행될 것입니다. 기본적으로 체크포인트(checkpoints)는 주기적으로 --out_dir에 저장됩니다. 단순히 python sample.py를 실행하여 모델로부터 샘플을 추출할 수 있습니다.
마지막으로, 단일 GPU에서 학습하려면 단순히 python train.py 스크립트를 실행하면 됩니다. 스크립트의 모든 인자(args)를 살펴보세요. 이 스크립트는 매우 읽기 쉽고, 해킹(hackable) 가능하며, 투명하게 설계되었습니다. 여러분의 필요에 따라 이러한 변수 중 다수를 튜닝하고 싶을 것입니다.
OpenAI GPT-2 체크포인트를 사용하면 openwebtext에 대한 몇 가지 베이스라인(baselines)을 설정할 수 있습니다. 다음과 같이 수치를 확인할 수 있습니다:
$ python train.py config/eval_gpt2.py
$ python train.py config/eval_gpt2_medium.py
$ python train.py config/eval_gpt2_large.py
...
그리고 학습(train) 및 검증(val)에 대해 다음과 같은 손실(losses)을 관찰할 수 있습니다:
| model | params | train loss | val loss |
|---|---|---|---|
| gpt2 | 124M | 3.11 | 3.12 |
| ... |
하지만 GPT-2는 (비공개되어 공개된 적 없는) WebText로 학습된 반면, OpenWebText는 이 데이터셋을 최대한 비슷하게 재현하려고 노력한 오픈 데이터셋이라는 점에 유의해야 합니다. 이는 데이터셋 도메인 차이 (dataset domain gap)가 존재함을 의미합니다. 실제로 GPT-2 (124M) 체크포인트 (checkpoint)를 가져와 OWT에서 직접 일정 시간 미세 조정 (finetuning)을 수행하면 손실 (loss) 값이 약 2.85까지 도달합니다. 따라서 이것이 재현 (reproduction) 관점에서는 더 적절한 베이스라인 (baseline)이 됩니다.
미세 조정 (Finetuning)은 학습 (training)과 다르지 않으며, 단지 사전 학습된 (pretrained) 모델로부터 초기화하고 더 작은 학습률 (learning rate)로 학습하도록 할 뿐입니다. 새로운 텍스트로 GPT를 미세 조정하는 방법에 대한 예시는 data/shakespeare로 이동하여
prepare.py를 실행하면 됩니다.
이를 통해 작은 Shakespeare 데이터셋을 다운로드하고, GPT-2의 OpenAI BPE 토크나이저 (tokenizer)를 사용하여 이를 train.bin 및 val.bin으로 렌더링합니다.
OpenWebText와 달리 이 과정은 몇 초 안에 완료됩니다. 미세 조정은 매우 짧은 시간이 걸릴 수 있으며, 예를 들어 단일 GPU에서 단 몇 분이면 충분합니다. 다음과 같이 미세 조정 예시를 실행해 보세요:
python train.py config/finetune_shakespeare.py
이렇게 하면 config/finetune_shakespeare.py에 있는 설정 (config) 파라미터 재정의 (overrides) 사항들이 로드됩니다 (저는 많이 튜닝하지는 않았습니다).
기본적으로 init_from을 사용하여 GPT2 체크포인트로부터 초기화한 다음, 평소보다 짧은 기간 동안 작은 학습률로 일반적인 학습을 진행합니다. 만약 메모리 (memory)가 부족하다면 모델 크기를 줄이거나 ({'gpt2', 'gpt2-medium', 'gpt2-large', 'gpt2-xl'}), 혹은 block_size (문맥 길이, context length)를 줄여보시기 바랍니다. 가장 좋은 체크포인트 (가장 낮은 검증 손실, validation loss)는 설정 파일에 따라 기본적으로 out-shakespeare와 같은 out_dir 디렉토리에 저장됩니다. 그 후 sample.py --out_dir=out-shakespeare 코드를 실행할 수 있습니다:
THEODORE:
Thou shalt sell me to the highest bidder: if I die,
I sell thee to the first; if I go mad,
...
와우, GPT가 다소 어두운 영역으로 들어가고 있네요. 설정 파일의 하이퍼파라미터 (hyperparameters)를 크게 튜닝하지는 않았으니, 자유롭게 시도해 보세요!
sample.py 스크립트를 사용하세요.
OpenAI에서 출시한 사전 학습된 (pre-trained) GPT-2 모델들로부터 샘플링하거나, 직접 학습시킨 모델로부터 샘플링할 수 있습니다. 예를 들어, 사용 가능한 가장 큰 gpt2-xl 모델로부터 샘플링하는 방법은 다음과 같습니다:
python sample.py \
--init_from=gpt2-xl \
--start="What is the answer to life, the universe, and everything?" \
...
직접 학습시킨 모델로부터 샘플링하고 싶다면, --out_dir을 사용하여 코드가 적절한 위치를 가리키도록 하세요. 또한 파일에 있는 텍스트로 모델에 프롬프트 (prompt)를 줄 수도 있습니다. 예: python sample.py --start=FILE:prompt.txt.
간단한 모델 벤치마킹 (benchmarking) 및 프로파일링 (profiling)을 위해서는 bench.py가 유용할 수 있습니다. 이는 train.py의 학습 루프 (training loop) 핵심 부분에서 일어나는 일과 동일하지만, 다른 많은 복잡한 과정들은 생략되어 있습니다.
이 코드는 기본적으로 PyTorch 2.0을 사용한다는 점에 유의하세요. 이 글을 쓰는 시점 (2022년 12월 29일) 기준으로, 이는 나이틀리 (nightly) 릴리스에서 torch.compile()을 사용할 수 있게 해줍니다. 단 한 줄의 코드로 얻는 개선 효과는 눈에 띄며, 예를 들어 반복 (iteration) 시간을 iter당 ~250ms에서 135ms로 단축해 줍니다. PyTorch 팀, 멋진 작업입니다!
- DDP 대신 FSDP를 조사하고 추가
- 표준 평가 (standard evals) (예: LAMBADA? HELM? 등)에서 제로샷 퍼플렉서티 (zero-shot perplexities) 평가
- 파인튜닝 (finetuning) 스크립트 개선, 하이퍼파라미터 (hyperparams)가 아주 좋지는 않은 것 같습니다
- 학습 중 선형적인 배치 크기 (batch size) 증가를 위한 스케줄링
- 다른 임베딩 (embeddings) (rotary, alibi) 통합
- 체크포인트 (checkpoints)에서 옵티마이저 (optim) 버퍼를 모델 파라미터 (model params)와 분리
- 네트워크 상태에 관한 추가적인 로깅 (logging) (예: 그래디언트 클리핑 (gradient clip) 이벤트, 크기 등)
- 더 나은 초기화 (init) 등에 관한 몇 가지 추가 조사
이 저장소는 기본적으로 PyTorch 2.0 (torch.compile 포함)을 사용합니다. 이는 상당히 새롭고 실험적인 기능이며, 아직 모든 플랫폼 (예: Windows)에서 사용할 수 없습니다. 관련 에러 메시지가 발생한다면 --compile=False 플래그를 추가하여 이 기능을 비활성화해 보세요. 이렇게 하면 코드는 느려지겠지만, 적어도 실행은 될 것입니다.
이 저장소(repository), GPT, 그리고 언어 모델링 (language modeling)에 대한 맥락을 파악하고 싶다면 저의 Zero To Hero 시리즈를 시청하는 것이 도움이 될 것입니다. 특히, 언어 모델링에 대한 사전 지식이 있다면 GPT 영상이 인기가 많습니다.
더 많은 질문이나 토론을 원하시면 Discord의 #nanoGPT 채널을 자유롭게 방문해 주세요:
모든 nanoGPT 실험은 제가 가장 좋아하는 클라우드 GPU 제공업체인 Lambda Labs의 GPU를 통해 구동됩니다. nanoGPT를 후원해 주신 Lambda Labs에 감사드립니다!
AI 자동 생성 콘텐츠
본 콘텐츠는 GitHub Trending Python (daily)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기