SentencePiece は、主にニューラル モデルのトレーニング前に語彙サイズが事前に決定されるニューラル ネットワーク ベースのテキスト生成システム用の教師なしテキスト トークナイザーおよびデトークナイザーです。 SentencePiece は、生の文からの直接トレーニングを拡張して、サブワード ユニット(バイト ペア エンコーディング (BPE) [Sennrich et al.]) およびユニグラム言語モデル[Kudo.]) を実装します。 SentencePiece を使用すると、言語固有の前処理/後処理に依存しない、純粋にエンドツーエンドのシステムを作成できます。
これは Google の公式製品ではありません。
ソフトウェア/アルゴリズムとしての SentencePiece に慣れていない人のために、ここで穏やかな紹介を読むことができます。
特徴 | センテンスピース | サブワード-nmt | ワードピース |
---|---|---|---|
サポートされているアルゴリズム | BPE、ユニグラム、文字、単語 | BPE | BPE* |
OSS? | はい | はい | Google社内 |
サブワードの正規化 | はい | いいえ | いいえ |
Python ライブラリ (pip) | はい | いいえ | 該当なし |
C++ ライブラリ | はい | いいえ | 該当なし |
事前のセグメンテーションは必要ですか? | いいえ | はい | はい |
カスタマイズ可能な正規化 (NFKC など) | はい | いいえ | 該当なし |
直接ID生成 | はい | いいえ | 該当なし |
WordPiece で使用される BPE アルゴリズムは、元の BPE とは若干異なることに注意してください。
SentencePiece はサブワード単位の再実装であり、ニューラル機械翻訳における未解決の語彙の問題を軽減する効果的な方法です。 SentencePiece は、バイト ペア エンコーディング (BPE) [Sennrich et al.] とユニグラム言語モデル[Kudo.] という 2 つのセグメンテーション アルゴリズムをサポートしています。他の実装との高レベルの違いは次のとおりです。
ニューラル機械翻訳モデルは通常、固定語彙で動作します。無限の語彙を前提とするほとんどの教師なし単語セグメンテーション アルゴリズムとは異なり、SentencePiece は、最終的な語彙サイズが固定 (たとえば、8k、16k、または 32k) になるようにセグメンテーション モデルをトレーニングします。
SentencePiece は、マージ操作の数を使用する subword-nmt とは異なる、トレーニングの最終的な語彙サイズを指定することに注意してください。マージ操作の数は BPE 固有のパラメーターであり、ユニグラム、ワード、文字などの他のセグメンテーション アルゴリズムには適用されません。
以前のサブワード実装では、入力文が事前にトークン化されていることを前提としていました。この制約は効率的なトレーニングのために必要でしたが、言語に依存するトークナイザーを事前に実行する必要があるため、前処理が複雑になります。 SentencePiece の実装は、生の文からモデルをトレーニングするのに十分な速さです。これは、単語間に明示的なスペースが存在しない中国語と日本語のトークナイザーとデトークナイザーをトレーニングする場合に役立ちます。
自然言語処理の最初のステップはテキストのトークン化です。たとえば、標準的な英語のトークナイザーは、テキスト「Hello world」をセグメント化します。以下の 3 つのトークンに分割されます。
[こんにちは世界] [。]
観察の 1 つは、元の入力とトークン化されたシーケンスは可逆的に変換できないことです。例えば、「World」と「.」の間にスペースがない情報。たとえば、 Tokenize(“World.”) == Tokenize(“World .”)
であるため、トークン化されたシーケンスから削除されます。
SentencePiece は、入力テキストを単なる Unicode 文字のシーケンスとして扱います。空白も通常の記号として扱われます。空白を基本トークンとして明示的に処理するために、SentencePiece はまず次のようにメタ シンボル " " (U+2581) で空白をエスケープします。
ハローワールド。
次に、このテキストは次のように小さな部分に分割されます。
[こんにちは] [ワー] [LD] [.]
セグメント化されたテキストでは空白が保持されるため、あいまいさなしにテキストを非トークン化できます。
detokenized = ''.join(pieces).replace('▁', ' ')
この機能により、言語固有のリソースに依存せずにトークン化解除を実行できるようになります。
標準の単語セグメンタでは空白が特別な記号として扱われるため、文を分割する場合には同じロスレス変換を適用できないことに注意してください。トークン化されたシーケンスには、元の文を復元するために必要な情報が保存されません。
サブワード正則化 [Kudo.] および BPE ドロップアウト Provilkov らは、オンザフライのサブワード サンプリングでトレーニング データを仮想的に増強する単純な正則化手法であり、NMT モデルの精度と堅牢性の向上に役立ちます。
サブワードの正則化を有効にするには、SentencePiece ライブラリ (C++/Python) を NMT システムに統合して、パラメーター更新ごとに 1 つのセグメンテーションをサンプリングします。これは、標準のオフライン データ準備とは異なります。以下は Python ライブラリの例です。 「New York」は、 SampleEncode (C++)
ごとに、またはencode with enable_sampling=True (Python)
異なる方法でセグメント化されていることがわかります。サンプリングパラメータの詳細は、sentencepiece_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 は、SentencePiece トレーニングとセグメンテーションの両方をサポートする Python ラッパーを提供します。 SentencePiece の Python バイナリパッケージをインストールできます。
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 リリース ページからダウンロードできます。リリース プロセス中に、OpenSSF の slsa-framework/slsa-github-generator を使用して SLSA3 署名を生成します。リリースバイナリを確認するには:
attestation.intoto.jsonl
をダウンロードします。slsa-verifier -artifact-path < the-wheel > -provenance attestation.intoto.jsonl -source github.com/google/sentencepiece -tag < the-tag >
pip install Wheel_file.whl
% spm_train --input=<input> --model_prefix=<model_name> --vocab_size=8000 --character_coverage=1.0 --model_type=<type>
--input
: 1 行に 1 文の生のコーパス ファイル。トークナイザー、ノーマライザー、プリプロセッサーを実行する必要はありません。デフォルトでは、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 は--output_format=(nbest|sample)_(piece|id)
フラグを使用した nbest セグメンテーションとセグメンテーション サンプリングをサポートします。
% 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.
語彙 ID 列から元の入力文が復元されていることがわかります。
% spm_export_vocab --model=<model_file> --output=<output file>
<output file>
語彙と排出ログの確率のリストが保存されます。語彙 ID は、このファイルの行番号に対応します。
デフォルトでは、ecnetepieceは、それぞれ0、1、および2のIDを持つ不明()、bos(<s>)、およびeos(</s>)トークンを使用します。このマッピングはトレーニング段階で次のように再定義できます。
% spm_train --bos_id=0 --eos_id=1 --unk_id=5 --input=... --model_prefix=... --character_coverage=...
-1 id を設定すると (例: bos_id=-1
、この特別なトークンは無効になります。不明な ID は無効にできないことに注意してください。パディング (<pad>) の ID を--pad_id=3
として定義できます。
別の特別なトークンを割り当てる場合は、「カスタム シンボルの使用」を参照してください。
spm_encode
--vocabulary
および--vocabulary_threshold
オプションを受け入れるため、 spm_encode
語彙にも (少なくともある程度の頻度で) 出現するシンボルのみを生成します。この機能の背景については、subword-nmt ページで説明されています。
使い方は基本的にsubword-nmt
と同じです。 L1 と L2 が 2 つの言語 (ソース/ターゲット言語) であると仮定して、共有 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
spm_train
デフォルトでコーパスの最初の 10M 行をロードするため、 shuffle
コマンドは念のために使用されます。
次に、 --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