Skip to content

필사 모드: 나만의 GPT 만들기 — nanoGPT로 처음부터 학습하는 언어 모델

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

ChatGPT, Claude, Gemini — 우리가 매일 쓰는 AI의 핵심은 **GPT(Generative Pre-trained Transformer)** 아키텍처입니다. 하지만 이걸 직접 만들어본 적 있나요?

이 시리즈에서는 Andrej Karpathy의 **nanoGPT**를 기반으로, 집에 있는 GPU로 언어 모델을 **처음부터** 학습합니다. 거대 모델의 축소판이지만, 원리는 GPT-4와 완전히 동일합니다.

왜 직접 만들어야 하나?

- 논문만 읽으면 30% 이해, **직접 코딩하면 90% 이해**

- GPU 서버가 있으니 실제로 학습 가능 (GB10 128GB!)

- 이력서에 "LLM 처음부터 학습 경험" — 차별화 포인트

- AI 논문 읽을 때 "아, 이 부분!" 하는 직관이 생김

GPT 아키텍처 핵심

GPT는 **Decoder-only Transformer**입니다. 핵심 3가지:

1. 토큰화 (Tokenization)

텍스트를 숫자로 변환하는 첫 단계입니다.

Character-level 토크나이저 (가장 단순)

text = "hello world"

chars = sorted(list(set(text)))

chars = [' ', 'd', 'e', 'h', 'l', 'o', 'r', 'w']

stoi = {ch: i for i, ch in enumerate(chars)} # char → int

itos = {i: ch for i, ch in enumerate(chars)} # int → char

encode = lambda s: [stoi[c] for c in s]

decode = lambda l: ''.join([itos[i] for i in l])

print(encode("hello")) # [3, 2, 4, 4, 5]

print(decode([3, 2, 4, 4, 5])) # "hello"

실제 GPT는 **BPE(Byte-Pair Encoding)** 토크나이저를 사용합니다:

enc = tiktoken.get_encoding("gpt2")

tokens = enc.encode("나만의 GPT를 만들자!")

print(tokens) # [171, 120, 230, 168, 245, ...]

print(len(tokens)) # ~15 tokens

2. Self-Attention (핵심 중의 핵심)

"각 토큰이 다른 모든 토큰을 얼마나 주목할지"를 학습합니다.

class SelfAttention(nn.Module):

def __init__(self, embed_dim, head_dim):

super().__init__()

self.query = nn.Linear(embed_dim, head_dim, bias=False)

self.key = nn.Linear(embed_dim, head_dim, bias=False)

self.value = nn.Linear(embed_dim, head_dim, bias=False)

def forward(self, x):

B, T, C = x.shape

q = self.query(x) # (B, T, head_dim)

k = self.key(x) # (B, T, head_dim)

v = self.value(x) # (B, T, head_dim)

Attention scores

weights = q @ k.transpose(-2, -1) # (B, T, T)

weights = weights * (C ** -0.5) # Scale

Causal mask — 미래 토큰은 볼 수 없음!

mask = torch.tril(torch.ones(T, T))

weights = weights.masked_fill(mask == 0, float('-inf'))

weights = F.softmax(weights, dim=-1)

out = weights @ v # (B, T, head_dim)

return out

**핵심 직관**: "The cat sat on the \_\_\_" 에서 빈칸을 예측할 때, "cat"과 "sat"에 높은 attention weight를 부여합니다.

3. Transformer Block

class TransformerBlock(nn.Module):

def __init__(self, embed_dim, num_heads):

super().__init__()

head_dim = embed_dim // num_heads

self.heads = nn.ModuleList([

SelfAttention(embed_dim, head_dim)

for _ in range(num_heads)

])

self.proj = nn.Linear(embed_dim, embed_dim)

self.ffn = nn.Sequential(

nn.Linear(embed_dim, 4 * embed_dim),

nn.GELU(),

nn.Linear(4 * embed_dim, embed_dim),

)

self.ln1 = nn.LayerNorm(embed_dim)

self.ln2 = nn.LayerNorm(embed_dim)

def forward(self, x):

Multi-Head Attention + Residual

attn_out = torch.cat([h(self.ln1(x)) for h in self.heads], dim=-1)

x = x + self.proj(attn_out)

Feed-Forward + Residual

x = x + self.ffn(self.ln2(x))

return x

전체 GPT 모델

class MicroGPT(nn.Module):

def __init__(self, vocab_size, embed_dim=384, num_heads=6,

num_layers=6, block_size=256):

super().__init__()

self.token_emb = nn.Embedding(vocab_size, embed_dim)

self.pos_emb = nn.Embedding(block_size, embed_dim)

self.blocks = nn.Sequential(*[

TransformerBlock(embed_dim, num_heads)

for _ in range(num_layers)

])

self.ln_f = nn.LayerNorm(embed_dim)

self.head = nn.Linear(embed_dim, vocab_size)

def forward(self, idx, targets=None):

B, T = idx.shape

tok_emb = self.token_emb(idx) # (B, T, embed_dim)

pos_emb = self.pos_emb(torch.arange(T)) # (T, embed_dim)

x = tok_emb + pos_emb

x = self.blocks(x)

x = self.ln_f(x)

logits = self.head(x) # (B, T, vocab_size)

loss = None

if targets is not None:

loss = F.cross_entropy(

logits.view(-1, logits.size(-1)),

targets.view(-1)

)

return logits, loss

def generate(self, idx, max_new_tokens):

for _ in range(max_new_tokens):

logits, _ = self(idx[:, -256:]) # block_size 제한

probs = F.softmax(logits[:, -1, :], dim=-1)

next_token = torch.multinomial(probs, num_samples=1)

idx = torch.cat([idx, next_token], dim=1)

return idx

**모델 크기 비교:**

| 모델 | 파라미터 | 레이어 | 학습 시간 (1 GPU) |

| --------------- | ------------ | ------ | ----------------- |

| 우리의 MicroGPT | **10M** | 6 | ~30분 |

| GPT-2 Small | 124M | 12 | ~수일 |

| GPT-3 | 175B | 96 | 수천 GPU-일 |

| GPT-4 | ~1.8T (추정) | ? | ? |

실습: Shakespeare로 학습하기

데이터 준비

spark01 (GB10 128GB)에서 실행

cd ~/nanoGPT

python3 data/shakespeare_char/prepare.py

→ train: 1,003,854 tokens / val: 111,540 tokens

학습 시작

python3 train.py config/train_shakespeare_char.py \

--device=cuda \

--max_iters=5000 \

--eval_interval=500 \

--log_interval=100

생성 결과 (5000 iter 후)

ROMEO:

What say you to this? Let me not stay a whit;

And yet I feel the thing I have forgot

To take upon the honour of my word.

셰익스피어 스타일의 텍스트를 **처음부터** 생성합니다!

다음 단계: 한국어 GPT

1. **한국어 토크나이저 학습** (SentencePiece BPE)

2. **나무위키 / 뉴스 데이터** 수집

3. **MicroGPT 500M** 학습 (spark01 128GB)

4. **LoRA 파인튜닝**으로 대화형 모델

시리즈 로드맵

| 편 | 주제 | 상태 |

| --- | -------------------------------- | ---- |

| 1편 | nanoGPT로 GPT 이해하기 (이 글) | ✅ |

| 2편 | 한국어 토크나이저 만들기 | 🔜 |

| 3편 | 500M 한국어 GPT 학습 | 🔜 |

| 4편 | RLHF로 대화형 모델 만들기 | 🔜 |

| 5편 | 이미지 생성 모델 (DDPM) 처음부터 | 🔜 |

**Q1.** GPT는 Encoder-Decoder 중 어떤 구조인가?

||Decoder-only Transformer||

**Q2.** Self-Attention에서 Causal Mask의 역할은?

||미래 토큰을 볼 수 없도록 차단 — autoregressive 생성을 위해 하삼각 행렬로 마스킹||

**Q3.** Attention score 계산 시 sqrt(d_k)로 나누는 이유는?

||내적 값이 커지면 softmax가 극단적이 되어 gradient vanishing 발생 — 스케일링으로 안정화||

**Q4.** BPE 토크나이저와 Character-level 토크나이저의 장단점은?

||BPE: 어휘 효율적 (짧은 시퀀스), 하지만 구현 복잡. Character: 단순하지만 시퀀스가 길어지고 장거리 의존성 학습 어려움||

**Q5.** Residual Connection (잔차 연결)이 Transformer에서 중요한 이유는?

||깊은 네트워크에서 gradient가 소실되지 않도록 원본 입력을 더해줌 — 학습 안정성과 수렴 속도 향상||

**Q6.** Feed-Forward Network에서 4x 확장 후 다시 축소하는 이유는?

||비선형 변환을 위한 표현력 확보 — 더 넓은 공간에서 특징을 추출한 후 원래 차원으로 압축||

**Q7.** 우리 MicroGPT의 파라미터 수는 약 얼마이고, GPT-2 Small과 몇 배 차이인가?

||약 10M, GPT-2 Small(124M)과 약 12배 차이||

**Q8.** next token prediction으로 학습하는 것만으로 언어를 이해할 수 있는 이유는?

||다음 토큰을 정확히 예측하려면 문법, 의미, 맥락, 세계 지식까지 내재적으로 학습해야 함 — 압축이 곧 이해||

📚 참고 자료 & GitHub 레퍼런스

원본 코드

- **nanoGPT** — Andrej Karpathy의 최소 GPT 구현: [github.com/karpathy/nanoGPT](https://github.com/karpathy/nanoGPT)

- **minGPT** — nanoGPT의 전신, 교육용 구현: [github.com/karpathy/minGPT](https://github.com/karpathy/minGPT)

- **microGPT 분석** (본 블로그 기반): [github.com/fjvbn2003/ai-model-analysis](https://github.com/fjvbn2003/ai-model-analysis)

원본 논문

- [Attention Is All You Need (2017)](https://arxiv.org/abs/1706.03762) — Transformer 아키텍처 원논문

- [Improving Language Understanding by Generative Pre-Training (GPT-1, 2018)](https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf)

- [Language Models are Unsupervised Multitask Learners (GPT-2, 2019)](https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf)

영상 강의

- [Andrej Karpathy — Let's build GPT from scratch](https://www.youtube.com/watch?v=kCc8FmEb1nY) — 2시간짜리 nanoGPT 구현 강의 (필수 시청!)

- [Andrej Karpathy — Let's reproduce GPT-2 (124M)](https://www.youtube.com/watch?v=l8pRSuU81PU) — GPT-2 재현

📖 관련 시리즈 & 추천 포스팅

- [AI를 위한 수학 완전 가이드](/blog/ai/2026-03-03-math-for-ai-complete-guide) — 선형대수, 미적분, 정보이론 (GPT 이해에 필수)

- [GPT 시리즈 논문 완벽 분석: GPT-1부터 GPT-4까지](/blog/ai-papers/gpt_series_evolution) — GPT 진화 계보

- [torchaudio 완전 가이드](/blog/ai-platform/2026-03-03-torchaudio-complete-guide) — 오디오 AI (GPT 이후 멀티모달)

- [torchvision 완전 가이드](/blog/ai-platform/2026-03-03-torchvision-complete-guide) — 비전 AI (ViT = Vision Transformer)

- [vLLM 추론 최적화 가이드](/blog/llm/2026-03-03-vllm-inference-optimization) — 학습한 GPT를 서빙하려면

- [LLM 양자화 GPTQ/AWQ/GGUF](/blog/llm/2026-03-03-llm-quantization-gptq-awq-gguf) — 모델 경량화

현재 단락 (1/156)

ChatGPT, Claude, Gemini — 우리가 매일 쓰는 AI의 핵심은 **GPT(Generative Pre-trained Transformer)** 아키텍처입니다. 하지만...

작성 글자: 0원문 글자: 6,432작성 단락: 0/156