← Назад к вопросам

Как работают различные токенизаторы текста?

2.0 Middle🔥 141 комментариев
#NLP и обработка текста

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работают различные токенизаторы текста

Токенизация — это первый шаг в обработке естественного языка (NLP). Это процесс разбиения текста на меньшие единицы (токены). Существует несколько подходов, от простых к сложным.

1. Character-level токенизация (Посимвольная)

Как работает: Каждый символ становится отдельным токеном.

text = "Hello World!"

# Character-level
tokens = list(text)
print(tokens)  
# Output: ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!']

vocab_size = len(set(tokens))  # 11 символов

Преимущества:

  • Очень малый размер словаря (vocab size ~100-256)
  • Может обработать любое слово, даже опечатки
  • Простая реализация

Недостатки:

  • Очень длинные последовательности (текст из 1000 слов = 5000+ токенов)
  • Модель должна учиться комбинировать символы в слова
  • Неэффективно для трансформеров (квадратичная сложность внимания)

Когда использовать:

  • Очень маленькие модели
  • Языки с иероглифами
  • Когда нужна максимальная гибкость

2. Word-level токенизация (Словная)

Как работает: Разбиение по пробелам и пунктуации на слова.

import string

text = "Hello, World! How are you?"

# Простая word-level
tokens = text.lower().split()  
# Output: ['hello,', 'world!', 'how', 'are', 'you?']

# С удалением пунктуации
translator = str.maketrans('', '', string.punctuation)
tokens = [w.translate(translator) for w in text.lower().split()]
# Output: ['hello', 'world', 'how', 'are', 'you']

vocab_size = len(set(tokens))  # 5 слов

Преимущества:

  • Разумная длина последовательности
  • Простая интерпретация (каждый токен — слово)
  • Хорошо для небольших корпусов

Недостатки:

  • Большой размер словаря (десятки тысяч слов)
  • Проблема с OOV (Out-Of-Vocabulary) словами
  • Не обрабатывает морфологию (running, runs, ran — разные токены)

Проблема OOV:

# Если в обучении не видели слово "unbelievable"
# как его обработать при инфиренсе?
# Вариант 1: <UNK> токен
# Вариант 2: Разбить на подслова

3. Subword токенизация (Подсловная)

Это современный стандарт. Разбивает редкие слова на подслова.

3.1 Byte Pair Encoding (BPE)

Как работает:

  1. Начинаем с символов
  2. Итеративно объединяем самые частые пары символов
# Пример BPE
text = "low low low low low low low low low low"

# Шаг 0: посимвольная представление
vocab = {
    'l o</w>': 10,  # </w> обозначает конец слова
    'l o w</w>': 10
}

# Шаг 1: найти самую частую пару
# 'l' 'o' встречается в каждом слове
pair = ('l', 'o')
new_token = 'lo'

# Шаг 2: объединить
vocab_after = {
    'lo w</w>': 10
}

# Шаг 3: повтори
# 'lo' 'w' объединяется
vocab_after2 = {
    'low</w>': 10
}

# Результат: один токен 'low</w>'

Реальный пример с GPT-2:

import tiktoken

encoder = tiktoken.get_encoding("cl100k_base")  # GPT-3.5/4

text = "The quick brown fox"
tokens = encoder.encode(text)
print(tokens)  # [1920, 4040, 9552, 24417]

# Декодировать обратно
for token in tokens:
    print(f"{token}: {encoder.decode_single_token_bytes(token)}")
# 1920: b'The'
# 4040: b' quick'
# 9552: b' brown'
# 24417: b' fox'

Преимущества BPE:

  • Баланс: не слишком много токенов, не слишком мало
  • Сжимает текст (компрессия)
  • Обрабатывает OOV слова

Недостатки:

  • Требует обучение на большом корпусе
  • Могут разбить слово странно (например, мистер → м ис тер)

3.2 WordPiece (BERT)

Как работает: Похож на BPE, но объединяет пары на основе вероятности, а не частоты.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")

text = "The quick brown fox jumps"
tokens = tokenizer.tokenize(text)
print(tokens)
# ['the', 'quick', 'brown', 'fox', 'jumps']

# С неизвестным словом
text2 = "unbelievable"
tokens2 = tokenizer.tokenize(text2)
print(tokens2)
# ['un', '##believe', '##able']  ## означает подслово внутри слова

Отличие от BPE:

  • Использует вероятность вместо частоты
  • Более детерминировано
  • Лучше для морфологических языков

3.3 SentencePiece

Как работает: Токенизирует текст как последовательность, не разделяя по пробелам.

import sentencepiece as spm

# Обучение SentencePiece модели
train_data = "hello world. this is a test.\nmore text here."
with open('train.txt', 'w') as f:
    f.write(train_data)

spm.SentencePieceTrainer.train(
    input='train.txt',
    model_prefix='my_model',
    vocab_size=1000
)

# Использование
sp = spm.SentencePieceProcessor('my_model.model')
tokens = sp.encode("hello world")
print(tokens)  # [256, 571]  # ID токенов

# Декодировать
text_back = sp.decode(tokens)
print(text_back)  # "hello world"

Особенности:

  • Работает с любым языком (не требует пробелов)
  • Используется в T5, LLaMA, XLNet
  • Пробел — часть словаря (обозначается как _)

Пример с многоязычностью:

# SentencePiece работает с китайским, японским, etc.
# Без явного разделения на слова

text_chinese = "你好世界"
tokens = sp.encode(text_chinese)
# SentencePiece разберется автоматически

3.4 Unigram Language Model

Как работает: Итеративно удаляет токены, которые уменьшают вероятность языковой модели.

# Используется в XLNet, ALBERT
# Более сложный алгоритм, реже используется в практике

Сравнение токенизаторов

МетодРазмер vocabДлина seqСкоростьЯзыкПримеры
Character~200Очень длиннаяМедленноЛюбойКастомные модели
Word50K-100KСредняяБыстроАнглийскийСтарые NLP
BPE30K-50KКорочеБыстроАнгл, кодингGPT-2, GPT-3
WordPiece30KКорочеБыстроЛюбойBERT
SentencePiece32KКорочеОчень быстроЛюбойT5, LLaMA

Практический пример: сравнение токенизаторов

from transformers import AutoTokenizer

text = "The quick brown fox jumps over the lazy dog"

# BERT (WordPiece)
bert_tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
bert_tokens = bert_tokenizer.tokenize(text)
print(f"BERT: {len(bert_tokens)} tokens")
# Output: 11 tokens

# GPT-2 (BPE)
import tiktoken
gpt2_tokenizer = tiktoken.get_encoding("gpt2")
gpt2_tokens = gpt2_tokenizer.encode(text)
print(f"GPT-2: {len(gpt2_tokens)} tokens")
# Output: 11 tokens

# GPT-4 (BPE улучшенный)
gpt4_tokenizer = tiktoken.get_encoding("cl100k_base")
gpt4_tokens = gpt4_tokenizer.encode(text)
print(f"GPT-4: {len(gpt4_tokens)} tokens")
# Output: 14 tokens

Специальные токены

# [CLS] - начало последовательности (BERT)
# [SEP] - разделитель (BERT)
# [PAD] - padding
# [UNK] - неизвестное слово
# [MASK] - маска (для BERT masked language modeling)
# <s>, </s> - начало/конец (RoBERTa)
# <bos>, <eos> - (GPT-like модели)

bert_tokens = ["[CLS]", "hello", "world", "[SEP]"]

Как выбрать токенизатор

  1. Используешь существующую модель? → Используй токенизатор этой модели
  2. Обучаешь с нуля? → SentencePiece или BPE
  3. Нужна универсальность? → SentencePiece (работает с любыми языками)
  4. Только английский? → BPE или WordPiece
  5. Максимальная скорость? → BPE
  6. Лучше морфология? → WordPiece

Проблемы токенизации и как их решать

Проблема 1: Странное разбиение

text = "unbelievably"
tokens = ["un", "believably"]  # или ["unbelievable", "ly"]
# Решение: это норма для subword токенизаторов

Проблема 2: Моноглотские токенизаторы

# BERT (англ) плохо работает с русским
# Решение: используй multilingual-bert или mBERT

Проблема 3: Специальные символы

text = "Hello @user #hashtag 🎉"
# Разные токенизаторы обрабатывают по-разному
# Решение: очистить текст перед токенизацией

Заключение

Токенизация — не просто препроцессинг, это критическая часть архитектуры NLP модели. Выбор токенизатора влияет на:

  1. Длину последовательности (влияет на скорость и память)
  2. Размер словаря (влияет на размер embeddings)
  3. Способность обрабатывать редкие слова и OOV
  4. Качество на разных языках

Современные модели (GPT, BERT, T5) используют subword токенизацию, которая балансирует между гибкостью character-level и эффективностью word-level токенизации.

Как работают различные токенизаторы текста? | PrepBro