SentencePiece — это неконтролируемый токенизатор и детокенизатор текста, в основном для систем генерации текста на основе нейронных сетей, где размер словаря заранее определяется до обучения нейронной модели. SentencePiece реализует единицы подслова (например, кодирование парами байтов (BPE) [Sennrich et al.]) и языковую модель униграмм [Kudo.]) с расширением прямого обучения на основе необработанных предложений. SentencePiece позволяет нам создать чисто сквозную систему, не зависящую от специфичной для языка предварительной/постобработки.
Это не официальный продукт Google.
Для тех, кто не знаком с SentencePiece как с программным обеспечением/алгоритмом, можно прочитать краткое введение здесь.
Особенность | ПредложениеЧасть | подслово-NMT | WordPiece |
---|---|---|---|
Поддерживаемый алгоритм | BPE, униграмма, символ, слово | БПЭ | БПЭ* |
ОСС? | Да | Да | Внутренний Google |
Регуляризация подслов | Да | Нет | Нет |
Библиотека Python (пип) | Да | Нет | Н/Д |
Библиотека С++ | Да | Нет | Н/Д |
Требуется предварительная сегментация? | Нет | Да | Да |
Настраиваемая нормализация (например, NFKC) | Да | Нет | Н/Д |
Прямое создание идентификатора | Да | Нет | Н/Д |
Обратите внимание, что алгоритм BPE, используемый в WordPiece, немного отличается от исходного BPE.
SentencePiece — это повторная реализация единиц подслов , эффективный способ облегчить проблемы открытого словаря при нейронном машинном переводе. SentencePiece поддерживает два алгоритма сегментации: кодирование парами байтов (BPE) [Sennrich et al.] и языковую модель униграмм [Kudo.]. Вот высокоуровневые отличия от других реализаций.
Модели нейронного машинного перевода обычно работают с фиксированным словарем. В отличие от большинства неконтролируемых алгоритмов сегментации слов, которые предполагают бесконечный словарный запас, SentencePiece обучает модель сегментации так, что конечный размер словаря фиксирован, например, 8 КБ, 16 КБ или 32 КБ.
Обратите внимание, что SentencePiece указывает окончательный размер словаря для обучения, который отличается от subword-nmt, который использует количество операций слияния. Количество операций слияния является параметром, специфичным для BPE, и не применимо к другим алгоритмам сегментации, включая униграммы, слова и символы.
Предыдущие реализации подслов предполагают, что входные предложения предварительно размечены. Это ограничение было необходимо для эффективного обучения, но усложняет предварительную обработку, поскольку нам приходится заранее запускать зависящие от языка токенизаторы. Реализация SentencePiece достаточно быстра, чтобы обучать модель на основе необработанных предложений. Это полезно для обучения токенизатора и детокенизатора для китайского и японского языков, где между словами нет явных пробелов.
Первым шагом обработки естественного языка является токенизация текста. Например, стандартный английский токенизатор сегментирует текст «Привет, мир». в следующие три токена.
[Привет, мир] [.]
Одним из наблюдений является то, что исходный ввод и токенизированная последовательность НЕ являются обратимо конвертируемыми . Например, информация, в которой нет пробела между «Миром» и «.» удаляется из токенизированной последовательности, поскольку, например, Tokenize(“World.”) == Tokenize(“World .”)
SentencePiece обрабатывает входной текст как последовательность символов Юникода. Пробелы также обрабатываются как обычный символ. Чтобы явно обработать пробел как базовый токен, SentencePiece сначала экранирует пробел с помощью метасимвола " " (U+2581) следующим образом.
Привет, мир.
Затем этот текст сегментируется на небольшие кусочки, например:
[Привет] [ Вор] [лд] [.]
Поскольку пробелы сохраняются в сегментированном тексте, мы можем детокенизировать текст без каких-либо двусмысленностей.
detokenized = ''.join(pieces).replace('▁', ' ')
Эта функция позволяет выполнять детокенизацию, не полагаясь на ресурсы, специфичные для языка.
Обратите внимание, что мы не можем применять те же преобразования без потерь при разделении предложения с помощью стандартных сегментаторов слов, поскольку они рассматривают пробелы как специальный символ. Токенизированные последовательности не сохраняют необходимую информацию для восстановления исходного предложения.
Регуляризация подслов [кудо.] и BPE-dropout Провилков и др. — это простые методы регуляризации, которые практически дополняют обучающие данные с помощью выборки подслов «на лету», что помогает повысить точность, а также надежность моделей NMT.
Чтобы включить регуляризацию подслов, вы хотели бы интегрировать библиотеку SentencePiece (C++/Python) в систему NMT для выборки одной сегментации для каждого обновления параметра, что отличается от стандартной подготовки данных в автономном режиме. Вот пример библиотеки Python. Вы можете обнаружить, что «Нью-Йорк» сегментируется по-разному для каждого вызова SampleEncode (C++)
или encode with enable_sampling=True (Python)
. Подробности о параметрах выборки можно найти в предложенииpiece_processor.h.
>>> import sentencepiece as spm
>>> s = spm.SentencePieceProcessor(model_file='spm.model')
>>> for n in range(5):
... s.encode('New York', out_type=str, enable_sampling=True, alpha=0.1, nbest_size=-1)
...
['▁', 'N', 'e', 'w', '▁York']
['▁', 'New', '▁York']
['▁', 'New', '▁Y', 'o', 'r', 'k']
['▁', 'New', '▁York']
['▁', 'New', '▁York']
SentencePiece предоставляет оболочку Python, которая поддерживает как обучение, так и сегментацию SentencePiece. Вы можете установить двоичный пакет Python SentencePiece с помощью.
pip install sentencepiece
Более подробную информацию см. в разделе Модуль Python.
Для сборки SentencePiece необходимы следующие инструменты и библиотеки:
В Ubuntu инструменты сборки можно установить с помощью apt-get:
% sudo apt-get install cmake build-essential pkg-config libgoogle-perftools-dev
Затем вы можете создать и установить инструменты командной строки следующим образом.
% git clone https://github.com/google/sentencepiece.git
% cd sentencepiece
% mkdir build
% cd build
% cmake ..
% make -j $(nproc)
% sudo make install
% sudo ldconfig -v
В OSX/macOS замените последнюю команду на sudo update_dyld_shared_cache
Вы можете скачать и установить предложение с помощью менеджера зависимостей vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install sentencepiece
Порт части предложения в vcpkg постоянно обновляется членами команды Microsoft и участниками сообщества. Если версия устарела, создайте проблему или запрос на извлечение в репозитории vcpkg.
Вы можете скачать колесо со страницы релизов GitHub. Мы генерируем подписи SLSA3, используя OpenSSF slsa-framework/slsa-github-generator в процессе выпуска. Чтобы проверить двоичный файл выпуска:
attestation.intoto.jsonl
со страницы выпусков GitHub.slsa-verifier -artifact-path < the-wheel > -provenance attestation.intoto.jsonl -source github.com/google/sentencepiece -tag < the-tag >
pip установитьwheel_file.whl
% spm_train --input=<input> --model_prefix=<model_name> --vocab_size=8000 --character_coverage=1.0 --model_type=<type>
--input
: необработанный корпусный файл с одним предложением в строке. Нет необходимости запускать токенизатор, нормализатор или препроцессор. По умолчанию SentencePiece нормализует ввод с помощью Unicode NFKC. Вы можете передать список файлов, разделенных запятыми.--model_prefix
: префикс имени выходной модели. Создаются <model_name>.model
и <model_name>.vocab
.--vocab_size
: размер словаря, например, 8000, 16000 или 32000.--character_coverage
: количество символов, охватываемых моделью, хорошие значения по умолчанию: 0.9995
для языков с богатым набором символов, таких как японский или китайский, и 1.0
для других языков с небольшим набором символов.--model_type
: тип модели. Выберите unigram
(по умолчанию), bpe
, char
или word
. Входное предложение должно быть предварительно маркировано при использовании типа word
. Используйте флаг --help
, чтобы отобразить все параметры для обучения, или посмотрите здесь обзор.
% spm_encode --model=<model_file> --output_format=piece < input > output
% spm_encode --model=<model_file> --output_format=id < input > output
Используйте флаг --extra_options
, чтобы вставить маркеры BOS/EOS или изменить последовательность ввода.
% spm_encode --extra_options=eos (add </s> only)
% spm_encode --extra_options=bos:eos (add <s> and </s>)
% spm_encode --extra_options=reverse:bos:eos (reverse input and add <s> and </s>)
SentencePiece поддерживает сегментацию nbest и выборку сегментации с флагами --output_format=(nbest|sample)_(piece|id)
.
% spm_encode --model=<model_file> --output_format=sample_piece --nbest_size=-1 --alpha=0.5 < input > output
% spm_encode --model=<model_file> --output_format=nbest_id --nbest_size=10 < input > output
% spm_decode --model=<model_file> --input_format=piece < input > output
% spm_decode --model=<model_file> --input_format=id < input > output
Используйте флаг --extra_options
для декодирования текста в обратном порядке.
% spm_decode --extra_options=reverse < input > output
% spm_train --input=data/botchan.txt --model_prefix=m --vocab_size=1000
unigram_model_trainer.cc(494) LOG(INFO) Starts training with :
input: "../data/botchan.txt"
... <snip>
unigram_model_trainer.cc(529) LOG(INFO) EM sub_iter=1 size=1100 obj=10.4973 num_tokens=37630 num_tokens/piece=34.2091
trainer_interface.cc(272) LOG(INFO) Saving model: m.model
trainer_interface.cc(281) LOG(INFO) Saving vocabs: m.vocab
% echo "I saw a girl with a telescope." | spm_encode --model=m.model
▁I ▁saw ▁a ▁girl ▁with ▁a ▁ te le s c o pe .
% echo "I saw a girl with a telescope." | spm_encode --model=m.model --output_format=id
9 459 11 939 44 11 4 142 82 8 28 21 132 6
% echo "9 459 11 939 44 11 4 142 82 8 28 21 132 6" | spm_decode --model=m.model --input_format=id
I saw a girl with a telescope.
Вы можете обнаружить, что исходное входное предложение восстанавливается из последовательности идентификаторов словаря.
% spm_export_vocab --model=<model_file> --output=<output file>
<output file>
хранит список вероятностей словаря и журнала выбросов. Идентификатор словаря соответствует номеру строки в этом файле.
By default, SentencePiece uses Unknown (<unk>), BOS (<s>) and EOS (</s>) tokens which have the ids of 0, 1, and 2 respectively. Мы можем переопределить это отображение на этапе обучения следующим образом.
% spm_train --bos_id=0 --eos_id=1 --unk_id=5 --input=... --model_prefix=... --character_coverage=...
При установке идентификатора -1, например, bos_id=-1
, этот специальный токен отключается. Обратите внимание, что неизвестный идентификатор невозможно отключить. Мы можем определить идентификатор заполнения (<pad>) как --pad_id=3
.
Если вы хотите назначить другие специальные токены, см. раздел «Использование пользовательских символов».
spm_encode
принимает опции --vocabulary
и --vocabulary_threshold
, так что spm_encode
будет создавать только те символы, которые также встречаются в словаре (по крайней мере, с некоторой частотой). История этой функции описана на странице subword-nmt.
Использование в основном такое же, как и у subword-nmt
. Предполагая, что L1 и L2 — это два языка (исходный/целевой), обучите общую модель spm и получите результирующий словарь для каждого:
% cat {train_file}.L1 {train_file}.L2 | shuffle > train
% spm_train --input=train --model_prefix=spm --vocab_size=8000 --character_coverage=0.9995
% spm_encode --model=spm.model --generate_vocabulary < {train_file}.L1 > {vocab_file}.L1
% spm_encode --model=spm.model --generate_vocabulary < {train_file}.L2 > {vocab_file}.L2
Команда shuffle
используется на всякий случай, потому что spm_train
по умолчанию загружает первые 10 миллионов строк корпуса.
Затем сегментируйте корпус поездов/тестов с помощью опции --vocabulary
% spm_encode --model=spm.model --vocabulary={vocab_file}.L1 --vocabulary_threshold=50 < {test_file}.L1 > {test_file}.seg.L1
% spm_encode --model=spm.model --vocabulary={vocab_file}.L2 --vocabulary_threshold=50 < {test_file}.L2 > {test_file}.seg.L2