SentencePiece ist ein unbeaufsichtigter Text-Tokenizer und -Detokenizer, der hauptsächlich für auf neuronalen Netzwerken basierende Textgenerierungssysteme verwendet wird, bei denen die Vokabulargröße vor dem Training des neuronalen Modells vorgegeben wird. SentencePiece implementiert Unterworteinheiten (z. B. Byte-Pair-Encoding (BPE) [Sennrich et al.]) und Unigram-Sprachmodell [Kudo.]) mit der Erweiterung des direkten Trainings aus Rohsätzen. Mit SentencePiece können wir ein reines End-to-End-System erstellen, das nicht auf sprachspezifische Vor-/Nachbearbeitung angewiesen ist.
Dies ist kein offizielles Google-Produkt.
Für diejenigen, die mit SentencePiece als Software/Algorithmus nicht vertraut sind, kann hier eine sanfte Einführung gelesen werden.
Besonderheit | Satzstück | Unterwort-nmt | Wortstück |
---|---|---|---|
Unterstützter Algorithmus | BPE, Unigramm, Zeichen, Wort | BPE | BPE* |
OSS? | Ja | Ja | Google-intern |
Unterwort-Regularisierung | Ja | NEIN | NEIN |
Python-Bibliothek (pip) | Ja | NEIN | N / A |
C++-Bibliothek | Ja | NEIN | N / A |
Vorsegmentierung erforderlich? | NEIN | Ja | Ja |
Anpassbare Normalisierung (z. B. NFKC) | Ja | NEIN | N / A |
Direkte ID-Generierung | Ja | NEIN | N / A |
Beachten Sie, dass sich der in WordPiece verwendete BPE-Algorithmus geringfügig vom ursprünglichen BPE unterscheidet.
SentencePiece ist eine Neuimplementierung von Unterworteinheiten , eine wirksame Möglichkeit, die Probleme mit dem offenen Wortschatz bei der neuronalen maschinellen Übersetzung zu lindern. SentencePiece unterstützt zwei Segmentierungsalgorithmen: Byte-Pair-Encoding (BPE) [Sennrich et al.] und Unigram-Sprachmodell [Kudo.]. Hier sind die großen Unterschiede zu anderen Implementierungen aufgeführt.
Modelle der neuronalen maschinellen Übersetzung arbeiten typischerweise mit einem festen Vokabular. Im Gegensatz zu den meisten unbeaufsichtigten Wortsegmentierungsalgorithmen, die von einem unendlichen Vokabular ausgehen, trainiert SentencePiece das Segmentierungsmodell so, dass die endgültige Vokabulargröße fest ist, z. B. 8k, 16k oder 32k.
Beachten Sie, dass SentencePiece die endgültige Vokabulargröße für das Training angibt, was sich von subword-nmt unterscheidet, das die Anzahl der Zusammenführungsvorgänge verwendet. Die Anzahl der Zusammenführungsvorgänge ist ein BPE-spezifischer Parameter und nicht auf andere Segmentierungsalgorithmen anwendbar, einschließlich Unigramm, Wort und Zeichen.
Frühere Unterwort-Implementierungen gehen davon aus, dass die Eingabesätze vorab tokenisiert sind. Diese Einschränkung war für ein effizientes Training erforderlich, macht die Vorverarbeitung jedoch kompliziert, da wir sprachabhängige Tokenizer im Voraus ausführen müssen. Die Implementierung von SentencePiece ist schnell genug, um das Modell anhand von Rohsätzen zu trainieren. Dies ist nützlich, um den Tokenizer und Detokenizer für Chinesisch und Japanisch zu trainieren, wo keine expliziten Leerzeichen zwischen Wörtern vorhanden sind.
Der erste Schritt der Verarbeitung natürlicher Sprache ist die Text-Tokenisierung. Beispielsweise würde ein standardmäßiger englischer Tokenizer den Text „Hallo Welt“ segmentieren. in die folgenden drei Token.
[Hallo] [Welt] [.]
Eine Beobachtung ist, dass die ursprüngliche Eingabe und die tokenisierte Sequenz NICHT reversibel konvertierbar sind. Zum Beispiel die Informationen, bei denen zwischen „Welt“ und „.“ kein Leerzeichen steht. wird aus der tokenisierten Sequenz gelöscht, da z. B. Tokenize(“World.”) == Tokenize(“World .”)
SentencePiece behandelt den Eingabetext einfach als eine Folge von Unicode-Zeichen. Leerzeichen werden ebenfalls als normales Symbol behandelt. Um das Leerzeichen explizit als Basis-Token zu behandeln, maskiert SentencePiece das Leerzeichen zunächst wie folgt mit einem Metasymbol „ “ (U+2581).
Hallo Welt.
Anschließend wird dieser Text in kleine Teile segmentiert, zum Beispiel:
[Hallo] [ Wor] [ld] [.]
Da der Leerraum im segmentierten Text erhalten bleibt, können wir den Text ohne Mehrdeutigkeiten detokenisieren.
detokenized = ''.join(pieces).replace('▁', ' ')
Diese Funktion ermöglicht die Durchführung der Detokenisierung, ohne auf sprachspezifische Ressourcen angewiesen zu sein.
Beachten Sie, dass wir beim Teilen des Satzes mit Standard-Wortsegmentierern nicht dieselben verlustfreien Konvertierungen anwenden können, da diese das Leerzeichen als spezielles Symbol behandeln. Tokenisierte Sequenzen bewahren nicht die notwendigen Informationen, um den ursprünglichen Satz wiederherzustellen.
Subword-Regularisierung [Kudo.] und BPE-Dropout Provilkov et al. sind einfache Regularisierungsmethoden, die Trainingsdaten durch spontane Subword-Sampling virtuell erweitern, was dazu beiträgt, die Genauigkeit und Robustheit von NMT-Modellen zu verbessern.
Um die Subwort-Regularisierung zu ermöglichen, möchten Sie die SentencePiece-Bibliothek (C++/Python) in das NMT-System integrieren, um eine Segmentierung für jede Parameteraktualisierung abzutasten, was sich von den standardmäßigen Offline-Datenvorbereitungen unterscheidet. Hier ist das Beispiel einer Python-Bibliothek. Sie können feststellen, dass „New York“ bei jedem SampleEncode (C++)
oder encode with enable_sampling=True (Python)
unterschiedlich segmentiert ist. Die Details der Sampling-Parameter finden Sie in sentpiece_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 bietet einen Python-Wrapper, der sowohl das SentencePiece-Training als auch die Segmentierung unterstützt. Sie können das Python-Binärpaket von SentencePiece mit installieren.
pip install sentencepiece
Weitere Einzelheiten finden Sie im Python-Modul
Zum Erstellen von SentencePiece sind die folgenden Tools und Bibliotheken erforderlich:
Unter Ubuntu können die Build-Tools mit apt-get installiert werden:
% sudo apt-get install cmake build-essential pkg-config libgoogle-perftools-dev
Anschließend können Sie Befehlszeilentools wie folgt erstellen und installieren.
% git clone https://github.com/google/sentencepiece.git
% cd sentencepiece
% mkdir build
% cd build
% cmake ..
% make -j $(nproc)
% sudo make install
% sudo ldconfig -v
Ersetzen Sie unter OSX/macOS den letzten Befehl durch sudo update_dyld_shared_cache
Sie können Satzstück mit dem vcpkg-Abhängigkeitsmanager herunterladen und installieren:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install sentencepiece
Der Satzstück-Port in vcpkg wird von Microsoft-Teammitgliedern und Community-Mitwirkenden auf dem neuesten Stand gehalten. Wenn die Version veraltet ist, erstellen Sie bitte einen Issue oder Pull Request im vcpkg-Repository.
Sie können das Rad von der GitHub-Release-Seite herunterladen. Während des Veröffentlichungsprozesses generieren wir SLSA3-Signaturen mithilfe des slsa-framework/slsa-github-generators von OpenSSF. So überprüfen Sie eine Release-Binärdatei:
attestation.intoto.jsonl
von der GitHub-Release-Seite herunter.slsa-verifier -artifact-path < the-wheel > -provenance attestation.intoto.jsonl -source github.com/google/sentencepiece -tag < the-tag >
pip installwheel_file.whl
% spm_train --input=<input> --model_prefix=<model_name> --vocab_size=8000 --character_coverage=1.0 --model_type=<type>
--input
: Rohkorpusdatei mit einem Satz pro Zeile. Es ist nicht erforderlich, Tokenizer, Normalizer oder Präprozessor auszuführen. Standardmäßig normalisiert SentencePiece die Eingabe mit Unicode NFKC. Sie können eine durch Kommas getrennte Liste von Dateien übergeben.--model_prefix
: Präfix für den Ausgabemodellnamen. <model_name>.model
und <model_name>.vocab
werden generiert.--vocab_size
: Vokabelgröße, z. B. 8000, 16000 oder 32000--character_coverage
: Anzahl der vom Modell abgedeckten Zeichen. Gute Standardwerte sind: 0.9995
für Sprachen mit umfangreichem Zeichensatz wie Japanisch oder Chinesisch und 1.0
für andere Sprachen mit kleinem Zeichensatz.--model_type
: Modelltyp. Wählen Sie zwischen unigram
(Standard), bpe
, char
oder word
. Bei Verwendung word
Worttyps muss der Eingabesatz vorab tokenisiert werden. Verwenden Sie das Flag --help
, um alle Parameter für das Training anzuzeigen, oder sehen Sie sich hier eine Übersicht an.
% spm_encode --model=<model_file> --output_format=piece < input > output
% spm_encode --model=<model_file> --output_format=id < input > output
Verwenden Sie das Flag --extra_options
, um die BOS/EOS-Markierungen einzufügen oder die Eingabesequenz umzukehren.
% 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 unterstützt nbest-Segmentierung und Segmentierungsstichprobe mit den Flags --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
Verwenden Sie das Flag --extra_options
, um den Text in umgekehrter Reihenfolge zu dekodieren.
% 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.
Sie können feststellen, dass der ursprüngliche Eingabesatz aus der Vokabular-ID-Sequenz wiederhergestellt wird.
% spm_export_vocab --model=<model_file> --output=<output file>
<output file>
speichert eine Liste von Vokabular- und Emissionsprotokollwahrscheinlichkeiten. Die Vokabular-ID entspricht der Zeilennummer in dieser Datei.
By default, SentencePiece uses Unknown (<unk>), BOS (<s>) and EOS (</s>) tokens which have the ids of 0, 1, and 2 respectively. Wir können diese Zuordnung in der Trainingsphase wie folgt neu definieren.
% spm_train --bos_id=0 --eos_id=1 --unk_id=5 --input=... --model_prefix=... --character_coverage=...
Wenn Sie die ID -1 festlegen, z. B. bos_id=-1
, ist dieses spezielle Token deaktiviert. Beachten Sie, dass die unbekannte ID nicht deaktiviert werden kann. Wir können eine ID zum Auffüllen (<pad>) als --pad_id=3
definieren.
Wenn Sie weitere spezielle Token zuweisen möchten, lesen Sie bitte Benutzerdefinierte Symbole verwenden.
spm_encode
akzeptiert die Optionen --vocabulary
und --vocabulary_threshold
sodass spm_encode
nur Symbole erzeugt, die auch im Vokabular vorkommen (zumindest mit einer gewissen Häufigkeit). Der Hintergrund dieser Funktion wird auf der Seite „subword-nmt“ beschrieben.
Die Verwendung ist grundsätzlich dieselbe wie die von subword-nmt
. Unter der Annahme, dass L1 und L2 die beiden Sprachen (Quell-/Zielsprachen) sind, trainieren Sie das gemeinsame SPM-Modell und erhalten Sie das resultierende Vokabular für jede:
% 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
Der Befehl shuffle
wird nur für den Fall verwendet, da spm_train
standardmäßig die ersten 10 Millionen Zeilen des Korpus lädt.
Dann segmentieren Sie den Trainings-/Testkorpus mit der Option --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