Day 3: 토큰화와 임베딩 이해
LLM은 텍스트를 직접 이해하지 못합니다. 텍스트를 숫자로 바꾸는 첫 번째 단계가 토큰화(Tokenization) 이고, 그 숫자를 의미 있는 벡터로 바꾸는 것이 임베딩(Embedding) 입니다.
토큰화 알고리즘 비교
| 알고리즘 | 사용 모델 | 특징 |
|---|---|---|
| BPE (Byte Pair Encoding) | GPT 시리즈 | 가장 빈번한 바이트 쌍을 반복 병합 |
| WordPiece | BERT | BPE와 유사하나 우도(likelihood) 기반 병합 |
| SentencePiece | T5, Llama | 언어에 독립적, 공백도 토큰으로 처리 |
| Unigram | mBART | 큰 어휘에서 시작해 확률 낮은 토큰 제거 |
tiktoken으로 토큰화 실습
# pip install tiktoken
import tiktoken
# GPT-4가 사용하는 토크나이저
encoder = tiktoken.encoding_for_model("gpt-4")
text_ko = "대규모 언어모델은 자연어를 이해합니다"
text_en = "Large language models understand natural language"
tokens_ko = encoder.encode(text_ko)
tokens_en = encoder.encode(text_en)
print(f"한국어: {len(tokens_ko)}개 토큰 → {tokens_ko}")
print(f"영어: {len(tokens_en)}개 토큰 → {tokens_en}")
# 토큰을 다시 텍스트로 복원
for token_id in tokens_ko:
print(f" {token_id} → '{encoder.decode([token_id])}'")
한국어는 영어보다 동일한 의미를 표현하는 데 더 많은 토큰이 필요합니다. 이는 비용과 컨텍스트 윈도우 활용에 직접적인 영향을 줍니다.
BPE 알고리즘 직접 구현
def simple_bpe(corpus, num_merges):
"""간소화된 BPE 알고리즘"""
# 초기: 글자 단위로 분리
vocab = {}
for word in corpus:
chars = list(word) + ["</w>"]
key = " ".join(chars)
vocab[key] = vocab.get(key, 0) + 1
for i in range(num_merges):
pairs = {}
for word, freq in vocab.items():
symbols = word.split()
for j in range(len(symbols) - 1):
pair = (symbols[j], symbols[j + 1])
pairs[pair] = pairs.get(pair, 0) + freq
if not pairs:
break
best_pair = max(pairs, key=pairs.get)
print(f"병합 {i+1}: '{best_pair[0]}' + '{best_pair[1]}'")
# 가장 빈번한 쌍을 병합
merged = " ".join(best_pair)
replacement = "".join(best_pair)
new_vocab = {}
for word, freq in vocab.items():
new_word = word.replace(merged, replacement)
new_vocab[new_word] = freq
vocab = new_vocab
return vocab
corpus = ["low", "lower", "newest", "widest", "low", "low"]
simple_bpe(corpus, 5)
Word2Vec으로 보는 벡터 공간
# pip install gensim
from gensim.models import Word2Vec
# 간단한 학습 데이터
sentences = [
["왕", "은", "왕비", "와", "궁전", "에", "산다"],
["여왕", "은", "궁전", "을", "다스린다"],
["고양이", "는", "생선", "을", "좋아한다"],
["강아지", "는", "산책", "을", "좋아한다"],
]
model = Word2Vec(sentences, vector_size=50, window=3, min_count=1, epochs=100)
# 단어 벡터 확인
print(f"'왕' 벡터 차원: {model.wv['왕'].shape}")
# 유사 단어 찾기 (학습 데이터가 적어 정확도는 낮음)
similar = model.wv.most_similar("왕", topn=3)
for word, score in similar:
print(f" {word}: {score:.3f}")
토큰화는 LLM의 입구이고, 임베딩은 LLM이 언어를 이해하는 기반입니다. 내일은 이 임베딩 위에서 작동하는 Transformer 아키텍처를 배웁니다.
오늘의 연습문제
- tiktoken을 설치하고, 한국어 문장 3개와 영어 문장 3개를 각각 토큰화해보세요. 한국어가 몇 배 더 많은 토큰을 사용하는지 계산해보세요.
- BPE 알고리즘에서 병합(merge) 횟수를 늘리면 어휘 크기와 토큰 길이에 어떤 변화가 생기는지 실험해보세요.
- Word2Vec의 유명한 관계식 “왕 - 남자 + 여자 = 여왕”이 왜 성립하는지, 벡터 공간의 관점에서 설명해보세요.