8.7 KiB
Byte Pair Encoding (BPE) Algorithm
Введение
Byte Pair Encoding (BPE) - это алгоритм компрессии данных, адаптированный для токенизации текста в обработке естественного языка. В контексте языковых моделей BPE используется для создания эффективного словаря подстрок (токенов).
Основные понятия
- Токен - элементарная единица текста (символ или последовательность символов)
- Словарь - набор уникальных токенов, используемых для представления текста
- Частота пары - количество раз, когда два токена встречаются вместе в тексте
Алгоритм работы
1. Инициализация
Исходный текст → Разбить на символы → Первоначальный словарь
Пример:
"мама" → ['м', 'а', 'м', 'а']
2. Основной цикл
graph TD
A[Подсчет частот пар] --> B[Выбор наиболее частой пары]
B --> C[Создание нового токена]
C --> D[Обновление последовательности]
D --> E{Достигнут лимит словаря?}
E -->|Нет| A
E -->|Да| F[Конец]
3. Детализация шагов
Шаг 1: Подсчет частот пар
Для текущей последовательности токенов подсчитываем все пары соседних токенов:
Текст: "мама мыла"
Токены: ['м', 'а', 'м', 'а', ' ', 'м', 'ы', 'л', 'а']
Пары: ('м','а'), ('а','м'), ('м','а'), ('а',' '), (' ','м'), ('м','ы'), ('ы','л'), ('л','а')
Шаг 2: Выбор пары для слияния
Находим пару с максимальной частотой. При равенстве частот выбираем пару, которая встречается раньше в тексте.
Шаг 3: Слияние
Объединяем выбранную пару в новый токен и заменяем все её вхождения в тексте:
Выбранная пара: ('м', 'а')
Новый токен: 'ма'
Обновленная последовательность: ['ма', 'ма', ' ', 'м', 'ы', 'л', 'а']
Шаг 4: Обновление словаря
Добавляем новый токен в словарь:
Словарь: ['м', 'а', ' ', 'ы', 'л', 'ма']
4. Критерии остановки
- Достижение заданного размера словаря
- Отсутствие пар для слияния (все возможные пары уже добавлены)
- Достижение максимального числа итераций
Псевдокод
def train_bpe(text, vocab_size):
# Инициализация
tokens = list(text)
vocab = set(tokens)
while len(vocab) < vocab_size:
# Подсчет пар
pairs = get_pairs(tokens)
if not pairs:
break
# Выбор наиболее частой пары
best_pair = max(pairs, key=pairs.get)
# Слияние
new_tokens = []
i = 0
while i < len(tokens):
if i < len(tokens)-1 and (tokens[i], tokens[i+1]) == best_pair:
new_tokens.append(best_pair[0] + best_pair[1])
i += 2
else:
new_tokens.append(tokens[i])
i += 1
tokens = new_tokens
# Обновление словаря
vocab.add(best_pair[0] + best_pair[1])
return vocab
Пример работы
Исходный текст: "мама мыла раму"
Итерация 1:
- Пара ('м','а') встречается 2 раза
- Новый токен: 'ма'
- Текст: ['ма', 'ма', ' ', 'м', 'ы', 'л', 'а', ' ', 'р', 'а', 'м', 'у']
Итерация 2:
- Пара ('ма',' ') встречается 1 раз
- Новый токен: 'ма '
- Текст: ['ма ', 'ма', 'мы', 'л', 'а', ' ', 'р', 'а', 'м', 'у']
Результирующий словарь (частично): ['м', 'а', ' ', 'ы', 'л', 'р', 'у', 'ма', 'ма ', 'мы']
Алгоритм энкодинга (токенизации)
После обучения BPE-модели (создания словаря), энкодинг текста происходит по следующему алгоритму:
graph TD
A[Начало] --> B[Разбить текст на символы]
B --> C[Инициализировать пустой список токенов]
C --> D[Установить i=0 'начало последовательности']
D --> E{i < длины текста?}
E -->|Нет| F[Заменить токены на их ID]
E -->|Да| G[Найти все токены в словаре, начинающиеся с text_i]
G --> H[Выбрать самый длинный подходящий токен]
H --> I[Добавить токен в результат]
I --> J[Увеличить i на длину токена]
J --> E
F --> K[Конец]
Пошаговое описание:
-
Инициализация:
- Исходный текст разбивается на символы
- Создается пустой список для результата
- Указатель
iустанавливается в 0
-
Основной цикл:
- Для текущей позиции
iнаходим все токены в словаре, которые:- Начинаются с символа
text[i] - Совпадают с подстрокой
text[i:i+len(token)]
- Начинаются с символа
- Из подходящих токенов выбираем самый длинный
- Добавляем найденный токен в результат
- Сдвигаем указатель
iна длину добавленного токена
- Для текущей позиции
-
Завершение:
- Когда весь текст обработан, заменяем токены на их ID из словаря
Пример:
Словарь: ['ма', 'мама', ' ', 'мыл', 'а', 'раму']
Текст: "мама мыла раму"
Энкодинг:
1. Находим самый длинный токен, начинающийся с 'м' -> 'мама'
2. Добавляем 'мама', i += 4
3. Токен ' ' (пробел), i += 1
4. Токен 'мыл', i += 3
5. Токен 'а', i += 1
6. Токен ' ', i += 1
7. Токен 'раму', i += 4
Результат: ['мама', ' ', 'мыл', 'а', ' ', 'раму']
Алгоритм декодирования
Принцип работы
- Преобразование списка ID обратно в текст
- Замена каждого ID на соответствующий токен
- Обработка неизвестных ID (
[UNK])
flowchart TD
A[Список ID] --> B{ID ∈ словарь?}
B -->|Да| C[Добавить токен]
B -->|Нет| D[Добавить UNK]
C --> E[Следующий ID]
D --> E
E --> F{Конец списка?}
F -->|Нет| B
F -->|Да| G[Объединить токены]
Пример:
decode([0,1,2]) → "абра" # Для словаря {0:"а", 1:"б", 2:"ра"}
Применение в языковых моделях
- Эффективное представление редких слов
- Снижение размерности входных данных
- Возможность обработки OOV (Out-of-Vocabulary) слов
Ограничения
- Чувствительность к регистру (можно решить предварительной нормализацией)
- Зависимость от обучающего корпуса
- Не всегда выделяет лингвистически осмысленные морфемы