Изучите алгоритм токенизации на основе подслов, используемый в современных моделях NLP - Byte-Pair Encoding (BPE)

Раздел искусственного интеллекта, Обработка естественного языка (НЛП), предназначен для того, чтобы машины понимали и обрабатывали человеческий язык. Обработка человеческого языка - непростая задача для машин, поскольку машины работают с числами, а не с текстом. 💻 НЛП - это настолько обширная и широко изученная отрасль ИИ, что время от времени мы слышим о новых достижениях в этой области. Исследователи изо всех сил пытаются заставить машины понимать человеческий язык и стоящий за ним контекст.

Одну из основных ролей в понимании человеческого языка играют токенизаторы. Алгоритмы токенизации могут быть основаны на словах, подсловах или символах. Каждый тип токенизатора помогает машинам обрабатывать текст по-разному. У каждого есть преимущество перед другим. Если вы хотите узнать о различных типах токенизаторов, используемых в НЛП, вы можете прочитать эту статью. Эта статья представляет собой практическое руководство по TDS и даст вам хорошее понимание темы. 😇



Самым популярным среди этих токенизаторов является токенизатор на основе подслов. Этот токенизатор используется большинством современных моделей НЛП. Итак, давайте начнем с того, чтобы сначала узнать, что такое токенизаторы на основе подслов, а затем понять алгоритм кодирования пар байтов (BPE), используемый современными моделями НЛП. 🙃

Токенизация на основе подслов

Токенизация на основе подсловов - это решение между токенизацией на основе слов и символов. 😎 Основная идея состоит в том, чтобы решить проблемы, возникающие при токенизации на основе слов (очень большой словарный запас, большое количество токенов OOV и разное значение очень похожих слов) и символьной токенизации (очень длинные последовательности и менее значимые отдельные токены) .

Алгоритмы токенизации на основе подслов не разделяют часто используемые слова на более мелкие подслова. Он скорее разбивает редкие слова на более мелкие значимые подслова. Например, «мальчик» не разделяется, а «мальчики» делятся на «мальчик» и «s». Это помогает модели понять, что слово «мальчики» образовано с использованием слова «мальчик» с немного разными значениями, но с тем же корнем.

Некоторые из популярных алгоритмов токенизации подслов - это WordPiece, Byte-Pair Encoding (BPE), Unigram и SentencePiece. В этой статье мы рассмотрим кодирование пар байтов (BPE). BPE используется в языковых моделях, таких как GPT-2, RoBERTa, XLM, FlauBERT и т. Д. Некоторые из этих моделей используют токенизацию пространства в качестве метода предварительной токенизации, в то время как некоторые используют более продвинутые методы предварительной токенизации, предоставляемые Moses, spaCY, ftfy. . Итак, приступим. 🏃

Кодирование пар байтов (BPE)

BPE - это простая форма алгоритма сжатия данных, в котором наиболее распространенная пара последовательных байтов данных заменяется байтом, которого нет в этих данных. Впервые он был описан в статье Новый алгоритм сжатия данных, опубликованной в 1994 году. Приведенный ниже пример объясняет BPE и взят из Википедии.

Предположим, у нас есть данные aaabdaaabac, которые необходимо закодировать (сжать). Чаще всего встречается пара байтов aa, поэтому мы заменим ее на Z, поскольку Z не встречается в наших данных. Итак, теперь у нас есть ZabdZabac, где Z = aa. Следующая общая пара байтов - ab, поэтому давайте заменим ее на Y. Теперь у нас есть ZYdZYac, где Z = aa и Y = ab. Осталась только пара байтов ac, которая отображается как одна, поэтому мы не будем ее кодировать. Мы можем использовать рекурсивную кодировку пар байтов для кодирования ZY как X. Наши данные теперь преобразованы в XdXac, где X = ZY, Y = ab, и Z = aa. Его нельзя сжимать дальше, так как пары байтов не встречаются более одного раза. Мы распаковываем данные, выполняя замены в обратном порядке.

Вариант этого используется в НЛП. Давайте вместе разберемся с версией НЛП. 🤗

BPE гарантирует, что наиболее распространенные слова представлены в словаре как один токен, в то время как редкие слова разбиты на два или более токенов подслова, и это согласуется с тем, что делает алгоритм токенизации на основе подслов.

Предположим, у нас есть корпус, в котором есть слова (после предварительной токенизации на основе пробела) - старые, старые, самые высокие и самые низкие, и мы подсчитываем частоту появления этих слов в корпусе. Предположим, частота этих слов следующая:

{«старые»: 7, «старые»: 3, «лучшие»: 9, «самые низкие»: 4}

Давайте добавим специальный конечный знак «‹/w›» в конце каждого слова.

{«old ‹/w›»: 7, «старые ‹/w›»: 3, «лучшие ‹/w›»: 9, «самые низкие ‹/w›»: 4}

Маркер «‹/w›» в конце каждого слова добавляется для определения границы слова, чтобы алгоритм знал, где заканчивается каждое слово. Это помогает алгоритму просматривать каждый символ и находить наиболее часто встречающиеся пары символов. Я объясню эту часть подробно позже, когда мы добавим «‹/w›» в наши пары байтов.

Далее мы разделим каждое слово на символы и посчитаем их появление. Первоначальными жетонами будут все символы и жетон «‹/w›».

Поскольку всего у нас 23 слова, у нас есть 23 жетона «‹/w›». Второй по частоте токен - «e». Всего у нас 12 разных токенов.

Следующим шагом в алгоритме BPE является поиск наиболее частых пар, объединение их и повторение одной и той же итерации снова и снова, пока мы не достигнем нашего предела токенов или предела итераций.

Слияние позволяет представить корпус с наименьшим количеством токенов, что является основной целью алгоритма BPE, то есть сжатия данных. Для слияния BPE ищет наиболее часто представляемые пары байтов. Здесь мы рассматриваем символ как байт. Это относится к английскому языку и может отличаться для других языков. Теперь мы объединим самые распространенные пары байтов, чтобы получился один токен, и добавим их в список токенов и пересчитаем частоту появления каждого токена. Это означает, что наш счетчик частоты будет меняться после каждого шага слияния. Мы продолжим выполнять этот шаг слияния, пока не достигнем количества итераций или не достигнем предельного размера токена.

Итерации

Итерация 1: мы начнем со второго по распространенности токена - «e». Самая распространенная пара байтов в нашем корпусе с буквой «е» - это «е» и «s» (в словах самый точный и самый низкий), которые встречаются 9 + 4 = 13 раз. Мы объединяем их, чтобы сформировать новый токен «es», и записываем его частоту как 13. Мы также уменьшим количество 13 отдельных токенов («e» и «s»). Это позволит нам узнать об оставшихся токенах «e» или «s». Мы можем видеть, что «s» встречается не одна, а «e» встречается 3 раза. Вот обновленная таблица:

Итерация 2: теперь мы объединим токены «es» и «t», поскольку они 13 раз встречались в нашем корпусе. Итак, у нас есть новый токен «est» с частотой 13, и мы уменьшим частоту «es» и «t» на 13.

Итерация 3. Теперь поработаем с токеном «‹/w›». Мы видим, что пара байтов «est» и «‹/w›» встречалась в нашем корпусе 13 раз.

Примечание. Объединение токенов остановки «‹/w›» очень важно. Это помогает алгоритму понять разницу между такими словами, как «оценка» и «наивысший». У обоих этих слов есть общее слово «est», но у одного есть жетон «est» в конце, а у другого - в начале. Таким образом, такие токены, как «est» и «est ‹/w›», будут обрабатываться по-разному. Если алгоритм увидит токен «est ‹/w›», он будет знать, что это токен для слова «высший», а не для слова «имущество».

Итерация 4: Глядя на другие токены, мы видим, что пары байтов «o» и «l» встречаются в нашем корпусе 7 + 3 = 10 раз.

Итерация 5: Теперь мы видим, что пары байтов «ol» и «d» встречаются в нашем корпусе 10 раз.

Если мы теперь посмотрим на нашу таблицу, мы увидим, что частота «f», «i» и «n» равна 9, но у нас есть только одно слово с этими символами, поэтому мы не объединяем их. Для простоты этой статьи давайте остановим наши итерации и внимательно посмотрим на наши токены.

Жетоны с нулевым счетчиком частоты были удалены из таблицы. Теперь мы видим, что общее количество токенов равно 11, что меньше нашего первоначального количества 12. Это небольшой корпус, но на практике его размер сильно уменьшается. Этот список из 11 токенов послужит нашим словарем.

Вы, должно быть, заметили, что когда мы добавляем жетон, наш счет увеличивается или уменьшается, или остается неизменным. На практике количество токенов сначала увеличивается, а затем уменьшается. Критерием остановки может быть либо количество токенов, либо количество итераций. Мы выбираем этот критерий остановки так, чтобы наш набор данных можно было разбить на токены наиболее эффективным способом.

Кодирование и декодирование

Давайте теперь посмотрим, как мы будем декодировать наш пример. Чтобы декодировать, мы должны просто объединить все токены вместе, чтобы получить целое слово. Например, закодированная последовательность [«the ‹/w›», «high», «est ‹/w›», «range ‹/w›», «in ‹/w›», «Seattle ‹/w›» ], мы будем декодированы как [«самый высокий», «диапазон», «в», «Сиэтл»], а не как [«тот», «высокий», «чужой», «в», «Сиэтл» ”]. Обратите внимание на наличие токена «‹/w›» в «est».

Для кодирования новых данных процесс снова прост. Однако кодирование само по себе требует больших вычислительных ресурсов. Предположим, что последовательность слов такая: [«‹/w›», «самый высокий ‹/w›», «диапазон ‹/w›», «in ‹/w›», «Сиэтл ‹/w›»]. Мы будем перебирать все токены, которые мы нашли в нашем корпусе - от самых длинных до самых коротких, и попытаемся заменить подстроки в нашей данной последовательности слов, используя эти токены. В конце концов, мы переберем все токены, и наши подстроки будут заменены токенами, уже присутствующими в нашем списке токенов. Если останется несколько подстрок (для слов, которые наша модель не увидела при обучении), мы заменим их неизвестными токенами.

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

Разве это не жадно? 🤔

Чтобы представить корпус наиболее эффективным образом, BPE просматривает все возможные варианты слияния на каждой итерации, глядя на его частоту. Итак, да, он следует жадному подходу к оптимизации для наилучшего возможного решения.

В любом случае, BPE - один из наиболее широко используемых алгоритмов токенизации подслов, и он имеет хорошую производительность, несмотря на свою жадность. 💃

Надеюсь, эта статья помогла вам понять идею и логику алгоритма BPE. 😍

Ссылки:

  1. Https://aclanthology.org/P16-1162.pdf
  2. Https://huggingface.co/transformers/tokenizer_summary.html
  3. Https://www.drdobbs.com/a-new-algorithm-for-data-compression/184402829
  4. Https://en.wikipedia.org/wiki/Byte_pair_encoding

Всем спасибо, что прочитали эту статью. Поделитесь своими ценными отзывами или предложениями. Приятного чтения! 📗 🖌