Byte Latent Transformer: Patches Scale Better Than Tokens
О том, как уйти от токенизации.
code
paper
🧸Этап 1 - раздели на патчи. Формально из последовательности x = [x1, x2, … xn] мы уходим в последовательность [y1, y2, ym] m < n, m - number of patches, где на каждый x_i делаем предсказание является ли он началом нового патча.
🧸Теперь нужно выбрать
функцию, которая расставит нам этот лейбл. По сути для наивной токенизации мы делаем похожую штуку (если это не Byte Level), а какой-то wordpiece, только patches - это просто токен для нас, который при этом создается динамически.
🧸На выбор представлены функции:
1. strided patching every k bytes - просто разделим на фиксированные патчи, как n-grams
2. space patching - создаем новый patch, когда встречаем space like byte.
3. entropy patching - создаем новый patch если сложно (high entropy) предсказать следующий токен в сравнении с предсказанием на всю последовательность (global entropy threshold) или предыдущих (relative to the previous entropy). Мне нравится второй из-за мотивации нахождения пойнта, который разбивает монотонность генерации.
——
🧸Архитектурно мы просто раздробили этап “токенизации”, где сначала процессим наши эмбеддинги с маленьким трансформером, который динамически создаем нам patches, а потом с большим, который берет на вход patches и их же предсказывает, отдает обратно в маленький декодер и он предсказывает байтовые представления.
Берем маленький трансформер, он передает последовательность битов в последовательность патчей. Для этого сначала эмбеддинги аугментируются с encoder
hash n-gram embeddings, проходят обычные трансформерные слои. Дальше мы используем cross-attention, но уже на patches, где используем маску на key, val, а на queries делаем pooling относительно локального патча. Интересно, что слои трансформера используют local block causal attention mask, что позволяет каким-то patches пересекаться (!)
В local decoder все также, только теперь byte representation это queries, а patches - это key values.
🧸Весь мед такого подхода - это возможность когда-то делать динамическое аллоцирование памяти и ресурсов. Также это решает проблему накопленной ошибки от токенизации в целом. Подробнее про причины [
тут].
#grokaem_nlp