SentencePiece عبارة عن أداة ترميز نصية غير خاضعة للرقابة ومزيلة للرموز بشكل أساسي لأنظمة إنشاء النص المستندة إلى الشبكة العصبية حيث يتم تحديد حجم المفردات مسبقًا قبل تدريب النموذج العصبي. تطبق SentencePiece وحدات الكلمات الفرعية (على سبيل المثال، تشفير زوج البايت (BPE) [Sennrich et al.]) ونموذج اللغة unigram [Kudo.]) مع توسيع التدريب المباشر من الجمل الأولية. يتيح لنا SentencePiece إنشاء نظام شامل تمامًا لا يعتمد على المعالجة المسبقة/اللاحقة الخاصة باللغة.
هذا ليس أحد منتجات Google الرسمية.
بالنسبة لأولئك الذين ليسوا على دراية بـ SentencePiece كبرنامج/خوارزمية، يمكن للمرء قراءة مقدمة لطيفة هنا.
ميزة | SentencePiece | الكلمة الفرعية NMT | قطعة Word |
---|---|---|---|
الخوارزمية المدعومة | BPE، يونيجرام، شار، كلمة | BPE | بي بي إي* |
OSS؟ | نعم | نعم | جوجل الداخلية |
تنظيم الكلمات الفرعية | نعم | لا | لا |
مكتبة بايثون (نقطة) | نعم | لا | لا يوجد |
مكتبة سي++ | نعم | لا | لا يوجد |
هل يلزم التقسيم المسبق؟ | لا | نعم | نعم |
التطبيع القابل للتخصيص (على سبيل المثال، NFKC) | نعم | لا | لا يوجد |
توليد الهوية المباشرة | نعم | لا | لا يوجد |
لاحظ أن خوارزمية BPE المستخدمة في WordPiece تختلف قليلاً عن خوارزمية BPE الأصلية.
SentencePiece عبارة عن إعادة تنفيذ لوحدات الكلمات الفرعية ، وهي طريقة فعالة للتخفيف من مشاكل المفردات المفتوحة في الترجمة الآلية العصبية. يدعم SentencePiece خوارزميتين للتجزئة، تشفير زوج البايت (BPE) [Sennrich et al.] ونموذج لغة unigram [Kudo.]. فيما يلي الاختلافات عالية المستوى عن التطبيقات الأخرى.
تعمل نماذج الترجمة الآلية العصبية عادةً بمفردات ثابتة. على عكس معظم خوارزميات تجزئة الكلمات غير الخاضعة للرقابة، والتي تفترض عددًا لا نهائيًا من المفردات، تقوم SentencePiece بتدريب نموذج التجزئة بحيث يكون حجم المفردات النهائي ثابتًا، على سبيل المثال، 8k، 16k، أو 32k.
لاحظ أن SentencePiece يحدد حجم المفردات النهائي للتدريب، والذي يختلف عن الكلمات الفرعية nmt التي تستخدم عدد عمليات الدمج. يعد عدد عمليات الدمج معلمة خاصة بـ BPE ولا ينطبق على خوارزميات التجزئة الأخرى، بما في ذلك unigram والكلمة والحرف.
تفترض تطبيقات الكلمات الفرعية السابقة أن جمل الإدخال تم ترميزها مسبقًا. كان هذا القيد مطلوبًا للتدريب الفعال، ولكنه يجعل المعالجة المسبقة معقدة حيث يتعين علينا تشغيل الرموز المميزة المعتمدة على اللغة مسبقًا. إن تنفيذ SentencePiece سريع بما يكفي لتدريب النموذج على الجمل الأولية. يعد هذا مفيدًا لتدريب أداة الرموز المميزة وأداة إزالة الرموز للغة الصينية واليابانية حيث لا توجد مسافات واضحة بين الكلمات.
الخطوة الأولى في معالجة اللغة الطبيعية هي ترميز النص. على سبيل المثال، يمكن لأداة الرمز المميزة الإنجليزية القياسية أن تقوم بتقسيم النص "Hello World". في الرموز الثلاثة التالية.
[مرحبا بالعالم] [.]
إحدى الملاحظات هي أن المدخلات الأصلية والتسلسل المميز غير قابلين للتحويل بشكل عكسي . على سبيل المثال، المعلومات التي لا توجد مسافة بين "العالم" و"." يتم إسقاطه من التسلسل المميز، على سبيل المثال، Tokenize(“World.”) == Tokenize(“World .”)
يتعامل SentencePiece مع نص الإدخال كسلسلة من أحرف Unicode. يتم التعامل مع المسافة البيضاء أيضًا كرمز عادي. للتعامل مع المسافة البيضاء كرمز أساسي بشكل صريح، تقوم SentencePiece أولاً بالهروب من المسافة البيضاء برمز التعريف " " (U+2581) كما يلي.
مرحبا العالم.
ثم يتم تقسيم هذا النص إلى أجزاء صغيرة، على سبيل المثال:
[مرحبا] [وور] [لد] [.]
نظرًا لأنه يتم الحفاظ على المسافة البيضاء في النص المجزأ، يمكننا إزالة الرمز من النص دون أي غموض.
detokenized = ''.join(pieces).replace('▁', ' ')
تتيح هذه الميزة إجراء عملية إزالة الترميز دون الاعتماد على موارد خاصة باللغة.
لاحظ أنه لا يمكننا تطبيق نفس التحويلات غير المفقودة عند تقسيم الجملة باستخدام مجزئات الكلمات القياسية، لأنها تتعامل مع المسافة البيضاء كرمز خاص. لا تحتفظ التسلسلات المميزة بالمعلومات الضرورية لاستعادة الجملة الأصلية.
تنظيم الكلمات الفرعية [Kudo.] وBPE-dropout Provilkov وآخرون هي طرق تنظيم بسيطة تعمل فعليًا على زيادة بيانات التدريب من خلال أخذ عينات من الكلمات الفرعية بشكل فوري، مما يساعد على تحسين دقة وقوة نماذج NMT.
لتمكين تنظيم الكلمات الفرعية، ترغب في دمج مكتبة SentencePiece (C++/Python) في نظام NMT لأخذ عينات من تجزئة واحدة لكل تحديث للمعلمة، وهو ما يختلف عن الاستعدادات القياسية للبيانات دون اتصال. إليك مثال مكتبة بايثون. يمكنك أن تجد أن "نيويورك" مقسمة بشكل مختلف في كل SampleEncode (C++)
أو encode with enable_sampling=True (Python)
. تم العثور على تفاصيل معلمات أخذ العينات في الجملة_المعالجة.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
لمزيد من التفاصيل، راجع وحدة بايثون
الأدوات والمكتبات التالية مطلوبة لإنشاء 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 باستخدام إطار عمل slsa/slsa-github-generator الخاص بـ OpenSSF أثناء عملية الإصدار. للتحقق من الإصدار الثنائي:
attestation.intoto.jsonl
من صفحة إصدارات GitHub.slsa-verifier -artifact-path < the-wheel > -provenance attestation.intoto.jsonl -source github.com/google/sentencepiece -tag < the-tag >
تثبيت النقطة 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 التجزئة الأفضل وأخذ عينات التجزئة باستخدام --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
فقط الرموز التي تظهر أيضًا في المفردات (مع بعض التكرار على الأقل). تم توضيح خلفية هذه الميزة في صفحة الكلمات الفرعية 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