LLMs 파인튜닝 프로젝트: 제품 설명으로 가격 예측하기 (4)

KiwiChipKiwiChip
3 min read

이번 포스트에서는 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개 토큰을 텍스트로 디코딩해 출력

주요 기능

  1. 토큰화 과정 시각화

    • Item.tokenizer.encode()를 통해 프롬프트 전체를 토큰 ID로 변환한다.

    • 예) "This is a test"[1234, 567, 890, 111]

  2. 마지막 10개 토큰 확인

    • tokens[-10:]는 토큰 리스트에서 마지막 10개의 토큰만 추출한다.

    • 이를 통해 프롬프트의 끝부분이 어떻게 토큰화되는지 알 수 있다.

  3. 토큰을 다시 텍스트로 변환

    • 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 프로젝트에서 모델을 선택할 때, 토크나이저 특성도 고려하는 것이 중요하다.


❓왜 모델마다 토큰화 개수가 다를까?

  1. 토크나이저의 종류 차이

    • Byte-Pair Encoding (BPE): GPT 시리즈에서 사용. 글자를 쪼개고 병합해 고유한 서브워드(subword)를 학습.
      예: unhappinessun + happ + iness

    • WordPiece: BERT에서 사용. 비슷하지만 병합 기준이 조금 다름.

    • SentencePiece: LLAMA, T5, XLM 등에서 사용. 전체 문장을 단위로 처리하고 공백도 토큰으로 사용.
      예: Hello world_Hello + _world (공백이 포함된 토큰)

    • Unigram: 주로 SentencePiece와 함께 사용되며, 확률 기반으로 토큰을 생성.

  2. 어휘 크기 (Vocabulary Size)

    • 모델마다 어휘 크기가 다르다. 어휘 크기가 크면 더 많은 단어를 하나의 토큰으로 처리할 수 있고, 작으면 더 잘게 쪼개야 한다.
      예:

      • BERT – 30,522개

      • GPT-3 – 50,257개

      • LLaMA 2 – 32,000개

      • Gemini (Google) – 어휘 크기가 클수록 긴 문장도 효율적으로 토큰화

  3. 숫자와 특수 문자 처리 방식

    • GPT: 3자리 숫자는 하나의 토큰으로 처리. 예: 765 → [765]

    • LLAMA: 비슷하지만 더 다양한 범위의 숫자가 개별 토큰으로 처리됨.

    • BERT: 숫자는 하나씩 쪼개져서 765 → [7, 6, 5]

  4. 어근(lemma)과 접사 처리

    • 어떤 토크나이저는 어근접사를 따로 쪼갠다. 예를 들어 runningrun-ing로 쪼개질 수 있다.

    • 일부는 단어 전체를 하나의 토큰으로 유지한다.


코드 출처: Udemy - Become an LLM Engineer in 8 weeks: Build and deploy 8 LLM apps, mastering Generative AI and key theoretical concepts.

0
Subscribe to my newsletter

Read articles from KiwiChip directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

KiwiChip
KiwiChip

I'm currently learning Python and studying RAG (Retrieval-Augmented Generation).