Сравнение токенов, сгенерированных алгоритмами токенизации SOTA с использованием пакета токенизаторов Hugging Face
Продолжая глубокое погружение в море НЛП, этот пост посвящен обучению токенизаторов с нуля с использованием пакета токенизаторов Hugging Face.
Токенизация часто рассматривается как подполе НЛП, но у нее есть своя история эволюции и то, как она достигла своей нынешней стадии, когда она лежит в основе современных моделей НЛП.
Прежде чем мы перейдем к интересной части обучения и сравнения различных токенизаторов, я хочу дать вам краткое описание основных различий между алгоритмами.
Основное различие заключается в выборе пар символов для слияния и той политике слияния, которую каждый из этих алгоритмов использует для генерации окончательного набора токенов.
BPE - частотная модель
- Кодирование пар байтов использует частоту шаблонов подслов, чтобы составить короткий список для их объединения.
- Недостатком использования частоты в качестве движущего фактора является то, что в конечном итоге вы можете получить неоднозначные окончательные кодировки, которые могут оказаться бесполезными для нового входного текста.
- Он все еще нуждается в улучшении с точки зрения генерации однозначных токенов.
Юниграмма - вероятностная модель
- Поставляется в модели Unigram, которая подходит к решению проблемы слияния путем вычисления вероятности каждой комбинации подслов, а не выбора наиболее частого шаблона.
- Он вычисляет вероятность каждого токена подслова, а затем отбрасывает его на основе функции потерь, которая объясняется в этой исследовательской статье.
- На основе определенного порога значения потерь вы можете затем запустить модель, чтобы отбросить нижние 20–30% токенов подслов.
- Unigram - это полностью вероятностный алгоритм, который выбирает как пары символов, так и окончательное решение объединить (или нет) на каждой итерации на основе вероятности.
WordPiece
- С выпуском BERT в 2018 году появился новый алгоритм токенизации подслов под названием WordPiece, который можно рассматривать как посредник между алгоритмами BPE и Unigram.
- WordPiece также является жадным алгоритмом, который использует вероятность, а не частоту подсчета, чтобы объединить лучшую пару на каждой итерации, но выбор символов для пары основан на частоте подсчета.
- Таким образом, он похож на BPE с точки зрения выбора персонажей для объединения и аналогичен Unigram с точки зрения выбора лучшей пары для слияния.
С учетом алгоритмических различий я попытался реализовать каждый из этих алгоритмов (не с нуля), чтобы сравнить результат, генерируемый каждым из них.
Обучение алгоритмов BPE, Unigram и WordPiece
Теперь, чтобы иметь беспристрастное сравнение результатов, я не хотел использовать предварительно обученные алгоритмы, поскольку это принесло бы в картину размер, качество и содержание набора данных.
Одним из способов может быть кодирование этих алгоритмов с нуля с использованием исследовательских работ, а затем их тестирование, что является хорошим подходом, чтобы по-настоящему понять работу каждого алгоритма, но в конечном итоге вы можете потратить на это недели.
Вместо этого я использовал пакет токенизаторы Hugging Face, который предлагает реализацию всех наиболее часто используемых токенизаторов. Это также позволяет мне обучать эти модели с нуля на моем выборе набора данных, а затем токенизировать входную строку по нашему собственному выбору.
Наборы данных для обучения
Я выбрал два разных набора данных для обучения этих моделей: один - это бесплатная книга от Гутенберга, которая служит небольшим набором данных, а другой - wikitext-103, который занимает 516 Мб текста.
В Colab вы можете сначала загрузить наборы данных и разархивировать их (при необходимости),
!wget http://www.gutenberg.org/cache/epub/16457/pg16457.txt
!wget https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip
!unzip wikitext-103-raw-v1.zip
Импортируйте необходимые модели и кроссовки.
Просматривая документацию, вы обнаружите, что основным API пакета является класс Tokenizer.
Затем вы можете создать экземпляр любого токенизатора с выбранной моделью (BPE / Unigram / WordPiece).
Здесь я импортировал основной класс, все модели, которые хотел протестировать, и их тренеры, так как я хочу обучать эти модели с нуля.
## importing the tokenizer and subword BPE trainer from tokenizers import Tokenizer from tokenizers.models import BPE, Unigram, WordLevel, WordPiece from tokenizers.trainers import BpeTrainer, WordLevelTrainer, \ WordPieceTrainer, UnigramTrainer
## a pretokenizer to segment the text into words from tokenizers.pre_tokenizers import Whitespace
Трехэтапный процесс для автоматизации обучения и токенизации
Поскольку мне нужно выполнить несколько схожие процессы для трех разных моделей, я разбил процессы на 3 функции. Мне нужно будет только вызвать эти функции для каждой модели, и моя работа будет сделана.
Итак, как выглядят эти функции?
Шаг 1 - Подготовьте токенизатор
Подготовка токенизатора требует, чтобы мы создали экземпляр класса Tokenizer с моделью по нашему выбору, но поскольку у нас есть четыре модели (также добавлен простой алгоритм уровня Word) для тестирования, мы напишем случаи if / else для создания экземпляра токенизатора с помощью правильная модель.
Чтобы обучить созданный экземпляр токенизатора на малых и больших наборах данных, нам также потребуется создать экземпляр тренера, в нашем случае это будет BpeTrainer, WordLevelTrainer, WordPieceTrainer, and UnigramTrainer.
Для создания экземпляра и обучения нам потребуется указать некоторые специальные токены. Это жетоны неизвестных слов и другие специальные жетоны, которые нам понадобятся позже, чтобы пополнить наш словарный запас.
Вы также можете указать здесь размер словаря других аргументов обучения или минимальную частоту.
unk_token = "<UNK>" # token for unknown words spl_tokens = ["<UNK>", "<SEP>", "<MASK>", "<CLS>"] # special tokens
def prepare_tokenizer_trainer(alg): """ Prepares the tokenizer and trainer with unknown & special tokens. """ if alg == 'BPE': tokenizer = Tokenizer(BPE(unk_token = unk_token)) trainer = BpeTrainer(special_tokens = spl_tokens) elif alg == 'UNI': tokenizer = Tokenizer(Unigram()) trainer = UnigramTrainer(unk_token= unk_token, special_tokens = spl_tokens) elif alg == 'WPC': tokenizer = Tokenizer(WordPiece(unk_token = unk_token)) trainer = WordPieceTrainer(special_tokens = spl_tokens) else: tokenizer = Tokenizer(WordLevel(unk_token = unk_token)) trainer = WordLevelTrainer(special_tokens = spl_tokens) tokenizer.pre_tokenizer = Whitespace() return tokenizer, trainer
Нам также нужно будет добавить пре-токенизатор, чтобы разделить наш ввод на слова, поскольку без пре-токенизатора мы можем получить токены, которые перекрывают несколько слов: например, мы могли бы получить токен "there is"
, поскольку эти два слова часто появляются рядом с друг с другом.
Использование пре-токенизатора гарантирует, что токен не будет больше слова, возвращаемого пре-токенизатором.
Эта функция вернет токенизатор и его обучающий объект, который можно использовать для обучения модели на наборе данных.
Здесь мы используем один и тот же пре-токенизатор (Whitespace
) для всех моделей. Вы можете протестировать его с другими.
Шаг 2 - Обучите токенизатор
После подготовки токенизаторов и трейнеров можно приступать к тренировочному процессу.
Вот функция, которая будет принимать файлы, на которых мы собираемся обучить наш токенизатор, вместе с идентификатором алгоритма.
‘WLV’
- Алгоритм уровня слов‘WPC’
- Алгоритм WordPiece‘BPE’
- Кодирование пары байтов‘UNI’
- Юниграмма
def train_tokenizer(files, alg='WLV'):
"""
Takes the files and trains the tokenizer.
"""
tokenizer, trainer = prepare_tokenizer_trainer(alg)
tokenizer.train(files, trainer) # training the tokenzier
tokenizer.save("./tokenizer-trained.json")
tokenizer = Tokenizer.from_file("./tokenizer-trained.json")
return tokenizer
Это основная функция, которую нам нужно будет вызвать для обучения токенизатора. Сначала он подготовит токенизатор и трейнер, а затем начнет обучение токенизаторов с помощью предоставленных файлов.
После обучения он сохраняет модель в файле JSON, загружает ее из файла и возвращает обученный токенизатор, чтобы начать кодирование нового ввода.
Шаг 3 - Токенизация входной строки
Последний шаг - начать кодирование новых входных строк и сравнить токены, сгенерированные каждым алгоритмом.
Здесь мы напишем вложенный цикл for, чтобы сначала обучить каждую модель на меньшем наборе данных с последующим обучением на более крупном наборе данных и токенизацией входной строки.
Строка ввода - «Это руководство по токенизации с глубоким обучением. Токенизация - это первый шаг в конвейере глубокого обучения НЛП. Мы будем сравнивать токены, генерируемые каждой моделью токенизации. Сильно взволнован?! 😍 »
small_file = ['pg16457.txt'] large_files = [f"./wikitext-103-raw/wiki.{split}.raw" for split in ["test", "train", "valid"]]
for files in [small_file, large_files]: print(f"========Using vocabulary from {files}=======") for alg in ['WLV', 'BPE', 'UNI', 'WPC']: trained_tokenizer = train_tokenizer(files, alg) input_string = "This is a deep learning tokenization tutorial. Tokenization is the first step in a deep learning NLP pipeline. We will be comparing the tokens generated by each tokenization model. Excited much?!😍" output = tokenize(input_string, trained_tokenizer) tokens_dict[alg] = output.tokens print("----", alg, "----") print(output.tokens, "->", len(output.tokens))
## вывод:
Анализ вывода:
Посмотрев на результат, вы увидите разницу в том, как генерируются токены, что, в свою очередь, привело к разному количеству сгенерированных токенов.
- Простой алгоритм на уровне слов создал 35 токенов независимо от того, на каком наборе данных он был обучен.
- Алгоритм BPE создал 55 токенов при обучении на меньшем наборе данных и 47 токенов при обучении на более крупном наборе данных. Это показывает, что он смог объединить больше пар символов при обучении на более крупном наборе данных.
- Модель Unigram создала аналогичное (68 и 67) количество токенов с обоими наборами данных. Но вы могли увидеть разницу в сгенерированных токенах:
Благодаря большему набору данных слияние приблизилось к генерации токенов, которые лучше подходят для кодирования реального английского языка, который мы часто используем.
- WordPiece создал 52 токена при обучении на меньшем наборе данных и 48 при обучении на более крупном наборе данных. Сгенерированные токены имеют двойной ## для обозначения использования токена в качестве префикса / суффикса.
- Все три алгоритма генерировали меньшие и лучшие токены подслов при обучении на более крупном наборе данных.
Сравнение токенов
Чтобы сравнить токены, я сохранил выходные данные каждого алгоритма в словаре и превращу его в фрейм данных, чтобы лучше видеть различия в токенах.
Поскольку количество токенов, генерируемых каждой моделью, разное, я добавил токен ‹PAD›, чтобы данные были прямоугольными и соответствовали фрейму данных.
‹PAD› - это в основном нан в фреймворке данных.
import pandas as pd
max_len = max(len(tokens_dict['UNI']), len(tokens_dict['WPC']), len(tokens_dict['BPE'])) diff_bpe = max_len - len(tokens_dict['BPE']) diff_wpc = max_len - len(tokens_dict['WPC'])
tokens_dict['BPE'] = tokens_dict['BPE'] + ['<PAD>']*diff_bpe tokens_dict['WPC'] = tokens_dict['WPC'] + ['<PAD>']*diff_wpc
del tokens_dict['WLV']
df = pd.DataFrame(tokens_dict) df.head(10)
## вывод:
Вы также можете посмотреть разницу в токенах, используя наборы:
Весь код можно найти в этой записной книжке Colab.
Заключительные мысли и следующие шаги!
Судя по типу генерируемых токенов, WPC действительно генерирует токены подслов, которые чаще встречаются в английском языке, но я не возлагаю на меня ответственность за это наблюдение.
Эти алгоритмы немного отличаются друг от друга и выполняют в чем-то схожую работу по разработке достойной модели НЛП. Но производительность во многом зависит от варианта использования вашей языковой модели, размера словаря, скорости и других факторов.
Дальнейшим развитием этих алгоритмов является алгоритм SentencePiece, который представляет собой полноценный подход ко всей проблеме токенизации, но большая часть этой проблемы решается с помощью HuggingFace, и, что еще лучше, все алгоритмы реализованы в одном репозитории GitHub.
На этом мы завершаем алгоритмы токенизации, и следующим шагом будет понимание того, что такое встраивания, как токенизация играет жизненно важную роль в создании этих встраиваний и как они влияют на производительность модели.
Ссылки и примечания
Если вы не согласны с моим анализом или какой-либо из моих работ в этом посте, я настоятельно рекомендую вам проверить эти ресурсы для точного понимания работы каждого алгоритма:
- Регуляризация подслов: улучшение моделей трансляции нейронных сетей Обучение токенизаторов BPE, WordPiece и Unigram с нуля с помощью Hugging Face
- Нейро-машинный перевод редких слов с подсловными единицами - исследовательская статья, в которой обсуждаются различные методы сегментации, основанные на алгоритме сжатия BPE.
- Пакет токенизатора Hugging Face.
Свяжитесь со мной!
Если вы хотите начать в области науки о данных или машинного обучения, ознакомьтесь с моим курсом Основы науки о данных и машинного обучения.
Если вы хотите видеть больше такого контента и не являетесь подписчиком, рассмотрите возможность подписки на мой информационный бюллетень.
Если есть что добавить или предложить, вы можете связаться со мной через: