이번 포스트에서는 LLM의 토큰화에 대해서 잠깐 짚고 넘어가겠다.
🔍 코드 설명
def report(item):
prompt = item.prompt # 아이템의 프롬프트(설명) 가져오기
tokens = Item.tokenizer.encode(item.prompt) # 프롬프트를 토큰화해 토큰 ID 리스트로 변환
print(prompt) # 원본 프롬프트 출력
print(tokens[-10:]) # 마지막 10개 토큰 ID 출력
print(Item.tokenizer.batch_decode(tokens[-10:])) # 마지막 10개 토큰을 텍스트로 디코딩해 출력
주요 기능
토큰화 과정 시각화
Item.tokenizer.encode()
를 통해 프롬프트 전체를 토큰 ID로 변환한다.예)
"This is a test"
→[1234, 567, 890, 111]
마지막 10개 토큰 확인
tokens[-10:]
는 토큰 리스트에서 마지막 10개의 토큰만 추출한다.이를 통해 프롬프트의 끝부분이 어떻게 토큰화되는지 알 수 있다.
토큰을 다시 텍스트로 변환
Item.tokenizer.batch_decode()
는 토큰 ID 리스트를 원래 텍스트로 되돌린다.이를 통해 어떤 단어/기호가 마지막 10개의 토큰을 차지하는지 확인할 수 있다.
예)
[345, 678, 901]
→['the', 'price', '.']
예시
item.prompt = "This is a high-quality stainless steel pan for $99.99."
report(item)
출력 예시:
This is a high-quality stainless steel pan for $99.99.
[345, 678, 901, 459, 123, 654, 321, 888, 999, 777]
['high', '-', 'quality', 'stainless', 'steel', 'pan', 'for', '$', '99', '.']
📌 사용 목적
토큰 길이 제한 확인: 프롬프트가 토큰 제한을 넘는지 확인할 수 있다.
모델 입력 이해: LLM이 텍스트를 어떻게 토큰으로 나누고 처리하는지 이해하는 데 도움이 된다.
프롬프트 최적화: 필요한 경우 불필요한 단어 제거 및 토큰 수 줄이기 작업이 가능하다.
추가 팁
batch_decode()
대신decode()
를 사용하면 개별 토큰을 하나씩 디코딩할 수 있다.이 코드는 프롬프트 길이가 길 경우 모델 입력이 어디까지 잘리는지,
숫자나 특수문자가 어떻게 토큰화되는지 파악하는 데 특히 유용하다. 😃
➕ 추가 자료) 모델마다 다른 토큰화 개수
모델마다 토큰화 방식과 결과가 다른데,
이 차이는 각 모델이 사용하는 토크나이저(tokenizer)의 종류와 알고리즘에 따라 발생한다.
from transformers import AutoTokenizer
texts = ["The price is $765.", "I love programming."]
# GPT-3
gpt_tokenizer = AutoTokenizer.from_pretrained("gpt2")
print(gpt_tokenizer.tokenize(texts[0]))
# ['The', 'Ġprice', 'Ġis', 'Ġ$', '765', '.']
# BERT
bert_tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
print(bert_tokenizer.tokenize(texts[0]))
# ['the', 'price', 'is', '$', '76', '##5', '.']
# LLaMA
llama_tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
print(llama_tokenizer.tokenize(texts[0]))
# ['▁The', '▁price', '▁is', '▁$', '765', '.']
GPT는 숫자
765
를 하나의 토큰으로 처리BERT는
76
과##5
로 나누어 두 개의 토큰으로 처리LLAMA는 GPT와 비슷하지만, 공백까지 포함해 토큰화
같은 문장도 모델마다 토큰화 결과가 다를 수 있고, 성능에 영향을 미칠 수 있다.
특정 작업에서는 토큰 수가 적을수록 효율적이지만, 어떤 경우에는 세밀하게 쪼갠 것이 더 정확한 결과를 내기도 한다.
LLM 프로젝트에서 모델을 선택할 때, 토크나이저 특성도 고려하는 것이 중요하다.
❓왜 모델마다 토큰화 개수가 다를까?
토크나이저의 종류 차이
Byte-Pair Encoding (BPE): GPT 시리즈에서 사용. 글자를 쪼개고 병합해 고유한 서브워드(subword)를 학습.
예:unhappiness
→un
+happ
+iness
WordPiece: BERT에서 사용. 비슷하지만 병합 기준이 조금 다름.
SentencePiece: LLAMA, T5, XLM 등에서 사용. 전체 문장을 단위로 처리하고 공백도 토큰으로 사용.
예:Hello world
→_Hello
+_world
(공백이 포함된 토큰)Unigram: 주로 SentencePiece와 함께 사용되며, 확률 기반으로 토큰을 생성.
어휘 크기 (Vocabulary Size)
모델마다 어휘 크기가 다르다. 어휘 크기가 크면 더 많은 단어를 하나의 토큰으로 처리할 수 있고, 작으면 더 잘게 쪼개야 한다.
예:BERT – 30,522개
GPT-3 – 50,257개
LLaMA 2 – 32,000개
Gemini (Google) – 어휘 크기가 클수록 긴 문장도 효율적으로 토큰화
숫자와 특수 문자 처리 방식
GPT: 3자리 숫자는 하나의 토큰으로 처리. 예:
765
→ [765]LLAMA: 비슷하지만 더 다양한 범위의 숫자가 개별 토큰으로 처리됨.
BERT: 숫자는 하나씩 쪼개져서
765
→ [7, 6, 5]
어근(lemma)과 접사 처리
어떤 토크나이저는 어근과 접사를 따로 쪼갠다. 예를 들어
running
은run
과-ing
로 쪼개질 수 있다.일부는 단어 전체를 하나의 토큰으로 유지한다.
코드 출처: Udemy - Become an LLM Engineer in 8 weeks: Build and deploy 8 LLM apps, mastering Generative AI and key theoretical concepts.