عرض على TensorFlow.org | تشغيل في Google Colab | عرض المصدر على جيثب | تحميل دفتر |
يوضح هذا البرنامج التعليمي كيفية إنشاء المفردات subword من مجموعة البيانات، واستخدامها لبناء text.BertTokenizer
من المفردات.
الميزة الرئيسية لمميزات الكلمة الفرعية هي أنه يقحم بين الترميز المستند إلى الكلمات والمستند إلى الأحرف. تحصل الكلمات الشائعة على فتحة في المفردات ، ولكن يمكن أن يتراجع الرمز المميز إلى قطع الكلمات والشخصيات الفردية لكلمات غير معروفة.
ملخص
و tensorflow_text
تتضمن حزمة تطبيقات TensorFlow العديد من tokenizers المشترك. يتضمن هذا ثلاثة رموز مميزة بنمط الكلمات الفرعية:
-
text.BertTokenizer
- وBertTokenizer
الفئة هي واجهة مستوى أعلى. ويشمل خوارزمية تقسيم رمزية بيرت وعلىWordPieceTokenizer
. فإنه يأخذ الجمل كمدخل وإرجاع معرفات رمزية. -
text.WordpieceTokenizer
- وWordPieceTokenizer
الفئة هي واجهة مستوى أقل. وتنفذ فقط خوارزمية WordPiece . يجب توحيد النص وتقسيمه إلى كلمات قبل تسميته. فإنه يأخذ الكلمات كمدخل وإرجاع معرفات رمزية. -
text.SentencepieceTokenizer
- وSentencepieceTokenizer
يتطلب الإعداد أكثر تعقيدا. يتطلب مُهيئته نموذج جملة مُدرَّب مسبقًا. رؤية مستودع جوجل / sentencepiece للحصول على تعليمات حول كيفية بناء واحد من هذه النماذج. يمكن أن تقبل الأحكام كمدخل عندما tokenizing.
يقوم هذا البرنامج التعليمي ببناء مفردات Wordpiece بطريقة من أعلى إلى أسفل ، بدءًا من الكلمات الموجودة. لا تعمل هذه العملية مع اليابانية أو الصينية أو الكورية لأن هذه اللغات لا تحتوي على وحدات واضحة متعددة الأحرف. لtokenize اللغات التالية conside باستخدام text.SentencepieceTokenizer
، text.UnicodeCharTokenizer
أو هذا النهج .
يثبت
pip install -q -U tensorflow-text
pip install -q tensorflow_datasets
import collections
import os
import pathlib
import re
import string
import sys
import tempfile
import time
import numpy as np
import matplotlib.pyplot as plt
import tensorflow_datasets as tfds
import tensorflow_text as text
import tensorflow as tf
tf.get_logger().setLevel('ERROR')
pwd = pathlib.Path.cwd()
قم بتنزيل مجموعة البيانات
جلب ترجمة بيانات البرتغالية / الانجليزية من tfds :
examples, metadata = tfds.load('ted_hrlr_translate/pt_to_en', with_info=True,
as_supervised=True)
train_examples, val_examples = examples['train'], examples['validation']
تنتج مجموعة البيانات هذه أزواج جمل برتغالية / إنجليزية:
for pt, en in train_examples.take(1):
print("Portuguese: ", pt.numpy().decode('utf-8'))
print("English: ", en.numpy().decode('utf-8'))
Portuguese: e quando melhoramos a procura , tiramos a única vantagem da impressão , que é a serendipidade . English: and when you improve searchability , you actually take away the one advantage of print , which is serendipity .
لاحظ بعض الأشياء حول أمثلة الجمل أعلاه:
- إنها صغيرة.
- توجد مسافات حول علامات الترقيم.
- ليس من الواضح ما إذا كان يتم استخدام تطبيع Unicode أم لا.
train_en = train_examples.map(lambda pt, en: en)
train_pt = train_examples.map(lambda pt, en: pt)
قم بتوليد المفردات
يولد هذا القسم مفردات لفظية من مجموعة بيانات. إذا كان لديك بالفعل ملف المفردات ونريد فقط أن نرى كيف لبناء text.BertTokenizer
أو text.Wordpiece
tokenizer معها ثم يمكنك تخطي إلى الأمام إلى أن tokenizer بناء القسم.
يتم تضمين رمز الجيل المفردات في tensorflow_text
حزمة نقطة. لا يتم استيراده افتراضيًا ، فأنت بحاجة إلى استيراده يدويًا:
from tensorflow_text.tools.wordpiece_vocab import bert_vocab_from_dataset as bert_vocab
و bert_vocab.bert_vocab_from_dataset
وظيفة توليد المفردات.
هناك العديد من الحجج التي يمكنك تعيينها لضبط سلوكها. في هذا البرنامج التعليمي ، ستستخدم الإعدادات الافتراضية في الغالب. إذا كنت ترغب في معرفة المزيد حول خيارات، وقراءة لأول مرة عن الخوارزمية ، ومن ثم إلقاء نظرة على رمز .
يستغرق هذا حوالي دقيقتين.
bert_tokenizer_params=dict(lower_case=True)
reserved_tokens=["[PAD]", "[UNK]", "[START]", "[END]"]
bert_vocab_args = dict(
# The target vocabulary size
vocab_size = 8000,
# Reserved tokens that must be included in the vocabulary
reserved_tokens=reserved_tokens,
# Arguments for `text.BertTokenizer`
bert_tokenizer_params=bert_tokenizer_params,
# Arguments for `wordpiece_vocab.wordpiece_tokenizer_learner_lib.learn`
learn_params={},
)
%%time
pt_vocab = bert_vocab.bert_vocab_from_dataset(
train_pt.batch(1000).prefetch(2),
**bert_vocab_args
)
CPU times: user 1min 30s, sys: 2.21 s, total: 1min 32s Wall time: 1min 28s
فيما يلي بعض الشرائح من المفردات الناتجة.
print(pt_vocab[:10])
print(pt_vocab[100:110])
print(pt_vocab[1000:1010])
print(pt_vocab[-10:])
['[PAD]', '[UNK]', '[START]', '[END]', '!', '#', '$', '%', '&', "'"] ['no', 'por', 'mais', 'na', 'eu', 'esta', 'muito', 'isso', 'isto', 'sao'] ['90', 'desse', 'efeito', 'malaria', 'normalmente', 'palestra', 'recentemente', '##nca', 'bons', 'chave'] ['##–', '##—', '##‘', '##’', '##“', '##”', '##⁄', '##€', '##♪', '##♫']
اكتب ملف مفردات:
def write_vocab_file(filepath, vocab):
with open(filepath, 'w') as f:
for token in vocab:
print(token, file=f)
write_vocab_file('pt_vocab.txt', pt_vocab)
استخدم هذه الوظيفة لتوليد مفردات من البيانات الإنجليزية:
%%time
en_vocab = bert_vocab.bert_vocab_from_dataset(
train_en.batch(1000).prefetch(2),
**bert_vocab_args
)
CPU times: user 1min 3s, sys: 2.21 s, total: 1min 6s Wall time: 1min 2s
print(en_vocab[:10])
print(en_vocab[100:110])
print(en_vocab[1000:1010])
print(en_vocab[-10:])
['[PAD]', '[UNK]', '[START]', '[END]', '!', '#', '$', '%', '&', "'"] ['as', 'all', 'at', 'one', 'people', 're', 'like', 'if', 'our', 'from'] ['choose', 'consider', 'extraordinary', 'focus', 'generation', 'killed', 'patterns', 'putting', 'scientific', 'wait'] ['##_', '##`', '##ย', '##ร', '##อ', '##–', '##—', '##’', '##♪', '##♫']
فيما يلي ملفا المفردات:
write_vocab_file('en_vocab.txt', en_vocab)
ls *.txt
en_vocab.txt pt_vocab.txt
بناء الرمز المميز
و text.BertTokenizer
يمكن تهيئة عن طريق تمرير مسار الملف المفردات كما الوسيطة الأولى (انظر القسم الخاص tf.lookup عن خيارات أخرى):
pt_tokenizer = text.BertTokenizer('pt_vocab.txt', **bert_tokenizer_params)
en_tokenizer = text.BertTokenizer('en_vocab.txt', **bert_tokenizer_params)
الآن يمكنك استخدامه لتشفير بعض النصوص. خذ مجموعة من 3 أمثلة من البيانات الإنجليزية:
for pt_examples, en_examples in train_examples.batch(3).take(1):
for ex in en_examples:
print(ex.numpy())
b'and when you improve searchability , you actually take away the one advantage of print , which is serendipity .' b'but what if it were active ?' b"but they did n't test for curiosity ."
تشغيله من خلال BertTokenizer.tokenize
الأسلوب. في البداية، وهذا يعود ل tf.RaggedTensor
بالفؤوس (batch, word, word-piece)
:
# Tokenize the examples -> (batch, word, word-piece)
token_batch = en_tokenizer.tokenize(en_examples)
# Merge the word and word-piece axes -> (batch, tokens)
token_batch = token_batch.merge_dims(-2,-1)
for ex in token_batch.to_list():
print(ex)
[72, 117, 79, 1259, 1491, 2362, 13, 79, 150, 184, 311, 71, 103, 2308, 74, 2679, 13, 148, 80, 55, 4840, 1434, 2423, 540, 15] [87, 90, 107, 76, 129, 1852, 30] [87, 83, 149, 50, 9, 56, 664, 85, 2512, 15]
إذا قمت باستبدال معرفات رمزية مع التمثيل نصهم (باستخدام tf.gather
) يمكنك أن ترى أنه في المثال الأول عبارة "searchability"
و "serendipity"
تم تتحلل إلى "search ##ability"
و "s ##ere ##nd ##ip ##ity"
:
# Lookup each token id in the vocabulary.
txt_tokens = tf.gather(en_vocab, token_batch)
# Join with spaces.
tf.strings.reduce_join(txt_tokens, separator=' ', axis=-1)
<tf.Tensor: shape=(3,), dtype=string, numpy= array([b'and when you improve search ##ability , you actually take away the one advantage of print , which is s ##ere ##nd ##ip ##ity .', b'but what if it were active ?', b"but they did n ' t test for curiosity ."], dtype=object)>
لإعادة تجميع الكلمات من الرموز المستخرجة، استخدم BertTokenizer.detokenize
الأسلوب:
words = en_tokenizer.detokenize(token_batch)
tf.strings.reduce_join(words, separator=' ', axis=-1)
<tf.Tensor: shape=(3,), dtype=string, numpy= array([b'and when you improve searchability , you actually take away the one advantage of print , which is serendipity .', b'but what if it were active ?', b"but they did n ' t test for curiosity ."], dtype=object)>
التخصيص والتصدير
هذا البرنامج التعليمي يبني tokenizer النص وdetokenizer المستخدمة من قبل محول البرنامج التعليمي. ويضيف هذا القسم طرق وخطوات المعالجة لتبسيط هذا البرنامج التعليمي، وصادرات tokenizers باستخدام tf.saved_model
بحيث يمكن استيرادها من قبل البرامج التعليمية الأخرى.
الترميز المخصص
الدروس المصب على حد سواء تتوقع النص برموز لتشمل [START]
و [END]
الرموز.
و reserved_tokens
حجز مساحة في بداية المفردات، لذلك [START]
و [END]
له نفس الأرقام القياسية لكل من اللغات:
START = tf.argmax(tf.constant(reserved_tokens) == "[START]")
END = tf.argmax(tf.constant(reserved_tokens) == "[END]")
def add_start_end(ragged):
count = ragged.bounding_shape()[0]
starts = tf.fill([count,1], START)
ends = tf.fill([count,1], END)
return tf.concat([starts, ragged, ends], axis=1)
words = en_tokenizer.detokenize(add_start_end(token_batch))
tf.strings.reduce_join(words, separator=' ', axis=-1)
<tf.Tensor: shape=(3,), dtype=string, numpy= array([b'[START] and when you improve searchability , you actually take away the one advantage of print , which is serendipity . [END]', b'[START] but what if it were active ? [END]', b"[START] but they did n ' t test for curiosity . [END]"], dtype=object)>
تفريغ مخصص
قبل تصدير الرموز المميزة ، هناك بعض الأشياء التي يمكنك تنظيفها في البرامج التعليمية النهائية:
- انهم يريدون لتوليد إخراج النص نظيفة، لذلك إسقاط الرموز محفوظة مثل
[START]
،[END]
و[PAD]
. - انهم المهتمة في سلاسل كاملة، لذلك تطبيق سلسلة الانضمام على طول
words
محور النتيجة.
def cleanup_text(reserved_tokens, token_txt):
# Drop the reserved tokens, except for "[UNK]".
bad_tokens = [re.escape(tok) for tok in reserved_tokens if tok != "[UNK]"]
bad_token_re = "|".join(bad_tokens)
bad_cells = tf.strings.regex_full_match(token_txt, bad_token_re)
result = tf.ragged.boolean_mask(token_txt, ~bad_cells)
# Join them into strings.
result = tf.strings.reduce_join(result, separator=' ', axis=-1)
return result
en_examples.numpy()
array([b'and when you improve searchability , you actually take away the one advantage of print , which is serendipity .', b'but what if it were active ?', b"but they did n't test for curiosity ."], dtype=object)
token_batch = en_tokenizer.tokenize(en_examples).merge_dims(-2,-1)
words = en_tokenizer.detokenize(token_batch)
words
<tf.RaggedTensor [[b'and', b'when', b'you', b'improve', b'searchability', b',', b'you', b'actually', b'take', b'away', b'the', b'one', b'advantage', b'of', b'print', b',', b'which', b'is', b'serendipity', b'.'], [b'but', b'what', b'if', b'it', b'were', b'active', b'?'], [b'but', b'they', b'did', b'n', b"'", b't', b'test', b'for', b'curiosity', b'.']]>
cleanup_text(reserved_tokens, words).numpy()
array([b'and when you improve searchability , you actually take away the one advantage of print , which is serendipity .', b'but what if it were active ?', b"but they did n ' t test for curiosity ."], dtype=object)
يصدر
كتلة التعليمات البرمجية التالية يبني CustomTokenizer
فئة لاحتواء text.BertTokenizer
الحالات، منطق العرف، و @tf.function
مغلفة المطلوبة للتصدير.
class CustomTokenizer(tf.Module):
def __init__(self, reserved_tokens, vocab_path):
self.tokenizer = text.BertTokenizer(vocab_path, lower_case=True)
self._reserved_tokens = reserved_tokens
self._vocab_path = tf.saved_model.Asset(vocab_path)
vocab = pathlib.Path(vocab_path).read_text().splitlines()
self.vocab = tf.Variable(vocab)
## Create the signatures for export:
# Include a tokenize signature for a batch of strings.
self.tokenize.get_concrete_function(
tf.TensorSpec(shape=[None], dtype=tf.string))
# Include `detokenize` and `lookup` signatures for:
# * `Tensors` with shapes [tokens] and [batch, tokens]
# * `RaggedTensors` with shape [batch, tokens]
self.detokenize.get_concrete_function(
tf.TensorSpec(shape=[None, None], dtype=tf.int64))
self.detokenize.get_concrete_function(
tf.RaggedTensorSpec(shape=[None, None], dtype=tf.int64))
self.lookup.get_concrete_function(
tf.TensorSpec(shape=[None, None], dtype=tf.int64))
self.lookup.get_concrete_function(
tf.RaggedTensorSpec(shape=[None, None], dtype=tf.int64))
# These `get_*` methods take no arguments
self.get_vocab_size.get_concrete_function()
self.get_vocab_path.get_concrete_function()
self.get_reserved_tokens.get_concrete_function()
@tf.function
def tokenize(self, strings):
enc = self.tokenizer.tokenize(strings)
# Merge the `word` and `word-piece` axes.
enc = enc.merge_dims(-2,-1)
enc = add_start_end(enc)
return enc
@tf.function
def detokenize(self, tokenized):
words = self.tokenizer.detokenize(tokenized)
return cleanup_text(self._reserved_tokens, words)
@tf.function
def lookup(self, token_ids):
return tf.gather(self.vocab, token_ids)
@tf.function
def get_vocab_size(self):
return tf.shape(self.vocab)[0]
@tf.function
def get_vocab_path(self):
return self._vocab_path
@tf.function
def get_reserved_tokens(self):
return tf.constant(self._reserved_tokens)
بناء CustomTokenizer
لكل لغة:
tokenizers = tf.Module()
tokenizers.pt = CustomTokenizer(reserved_tokens, 'pt_vocab.txt')
tokenizers.en = CustomTokenizer(reserved_tokens, 'en_vocab.txt')
تصدير tokenizers باعتباره saved_model
:
model_name = 'ted_hrlr_translate_pt_en_converter'
tf.saved_model.save(tokenizers, model_name)
2021-11-02 15:20:31.762976: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
تحميل saved_model
واختبار طرق:
reloaded_tokenizers = tf.saved_model.load(model_name)
reloaded_tokenizers.en.get_vocab_size().numpy()
7010
tokens = reloaded_tokenizers.en.tokenize(['Hello TensorFlow!'])
tokens.numpy()
array([[ 2, 4006, 2358, 687, 1192, 2365, 4, 3]])
text_tokens = reloaded_tokenizers.en.lookup(tokens)
text_tokens
<tf.RaggedTensor [[b'[START]', b'hello', b'tens', b'##or', b'##f', b'##low', b'!', b'[END]']]>
round_trip = reloaded_tokenizers.en.detokenize(tokens)
print(round_trip.numpy()[0].decode('utf-8'))
hello tensorflow !
أرشفتها ل دروس الترجمة :
zip -r {model_name}.zip {model_name}
adding: ted_hrlr_translate_pt_en_converter/ (stored 0%) adding: ted_hrlr_translate_pt_en_converter/saved_model.pb (deflated 91%) adding: ted_hrlr_translate_pt_en_converter/variables/ (stored 0%) adding: ted_hrlr_translate_pt_en_converter/variables/variables.data-00000-of-00001 (deflated 51%) adding: ted_hrlr_translate_pt_en_converter/variables/variables.index (deflated 33%) adding: ted_hrlr_translate_pt_en_converter/assets/ (stored 0%) adding: ted_hrlr_translate_pt_en_converter/assets/pt_vocab.txt (deflated 57%) adding: ted_hrlr_translate_pt_en_converter/assets/en_vocab.txt (deflated 54%)
du -h *.zip
184K ted_hrlr_translate_pt_en_converter.zip
اختياري: الخوارزمية
تجدر الإشارة هنا إلى وجود نسختين من خوارزمية WordPiece: من أسفل إلى أعلى ومن أعلى إلى أسفل. في كلتا الحالتين ، يكون الهدف هو نفسه: "بالنظر إلى مجموعة التدريب وعدد من الرموز المطلوبة D ، فإن مشكلة التحسين هي اختيار D wordpiece بحيث تكون المجموعة الناتجة في حدها الأدنى في عدد قطع الكلمات عند تقسيمها وفقًا لنموذج قطع الكلمات المختار. "
الأصلي خوارزمية WordPiece من أسفل إلى أعلى ، ويستند على ترميز بايت الزوج . مثل BPE ، يبدأ بالحروف الأبجدية ، ويجمع بشكل متكرر الأحرف الكبيرة الشائعة لتشكيل قطع الكلمات والكلمات.
مولد المفردات TensorFlow نص في أعقاب تنفيذ أعلى إلى أسفل من بيرت . البدء بالكلمات وتقسيمها إلى مكونات أصغر حتى تصل إلى حد التردد ، أو لا يمكن تقسيمها أكثر. يصف القسم التالي هذا بالتفصيل. بالنسبة لليابانيين والصينية والكورية ، لا يعمل هذا النهج من أعلى إلى أسفل نظرًا لعدم وجود وحدات كلمات صريحة لتبدأ بها. بالنسبة لأولئك كنت في حاجة الى نهج مختلف .
اختيار المفردات
يأخذ من أعلى إلى أسفل WordPiece الجيل الخوارزمية في مجموعة من (كلمة، العد) أزواج وعتبة T
، وعائدات المفردات V
.
الخوارزمية تكرارية. يتم تشغيله ل k
التكرارات، حيث عادة k = 4
، ولكن فقط الأولين هي حقا مهمة. الثالث والرابع (وما بعده) متطابقان تمامًا مع الثاني. علما بأن كل خطوة من خطوات البحث الثنائي تشغيل الخوارزمية من الصفر ل k
التكرارات.
التكرارات الموضحة أدناه:
التكرار الأول
- أعاد على كل كلمة وزوج والعد في المدخلات، ويرمز لها
(w, c)
. - كل كلمة
w
، تولد كل فرعية، كما تدلs
. على سبيل المثال، لكلمةhuman
، فإننا توليد{h, hu, hum, huma, human, ##u, ##um, ##uma, ##uman, ##m, ##ma, ##man, #a, ##an, ##n}
. - الحفاظ على خريطة التجزئة فرعية إلى العد، وزيادة عدد كل
s
من قبلc
. على سبيل المثال، إذا كان لدينا(human, 113)
و(humas, 3)
في مساهمتنا، وعدد منs = huma
سوف يكون113+3=116
. - وعندما ننتهي من جمع تهم كل فرعية، أعاد على
(s, c)
أزواج بدءا من أطولs
أولا. - احتفظ بأي
s
التي لديهاc > T
. على سبيل المثال، إذاT = 100
ولدينا(pers, 231); (dogs, 259); (##rint; 76)
، ثم نحن من شأنه أن يبقيpers
وdogs
. - عندما يكون
s
يتم الاحتفاظ، طرح قبالة به عدد من كل البادئات لها. وهذا هو السبب لفرز كل منs
بواسطة طول في الخطوة 4. هذا هو جزء هام من الخوارزمية، لأن خلاف ذلك الكلمات التي تحسب مزدوجة. على سبيل المثال، دعونا تقول بأننا قد أبقىhuman
ونصل الى(huma, 116)
. ونحن نعلم أن113
من هؤلاء116
جاء منhuman
، و3
جاء منhumas
. ومع ذلك، الآن بعد أنhuman
هو في قاموسنا، ونحن نعلم نحن لن شريحةhuman
إلىhuma ##n
. هكذا مرة واحدةhuman
ظلت، ثمhuma
له سوى عد الفعال لل3
.
وهذه الخوارزمية توليد مجموعة من كلمة قطع s
(وكثير منها ستكون الكلمة بالكامل w
)، والتي يمكن أن نستخدمها لدينا المفردات WordPiece.
ومع ذلك ، هناك مشكلة: هذه الخوارزمية سوف تفرط بشدة في إنشاء أجزاء من الكلمات. والسبب هو أننا نطرح فقط عدد الرموز المميزة للبادئة. لذلك، إذا علينا أن نحافظ على كلمة human
، فإننا سوف اطرح قبالة العد ل h, hu, hu, huma
، ولكن ليس ل ##u, ##um, ##uma, ##uman
وهلم جرا. ولذا فإننا قد تولد كل من human
و ##uman
ككلمة قطعة، على الرغم من أن ##uman
لن يتم تطبيقها.
فلماذا لا يطرح من التهم لكل فرعية، وليس فقط كل بادئة؟ لأنه قد ينتهي بنا الأمر بطرح الأعداد عدة مرات. دعونا يقول الله بأننا معالجة s
بطول 5 وعلينا أن نحافظ على حد سواء (##denia, 129)
و (##eniab, 137)
، حيث 65
من تلك التهم جاءت من الكلمة undeniable
. إذا طرحنا الخروج من كل فرعية، فإننا طرح 65
من سلسلة فرعية ##enia
مرتين، على الرغم من أننا يجب طرح مرة واحدة فقط. ومع ذلك ، إذا طرحنا فقط من البادئات ، فسيتم طرحها مرة واحدة بشكل صحيح.
التكرار الثاني (والثالث ...)
لحل مشكلة التوليد المذكورة أعلاه ، نقوم بإجراء تكرارات متعددة للخوارزمية.
التكرار اللاحقة متطابقة مع الأولى، مع تمييز واحد مهم: في الخطوة 2، بدلا من النظر في كل فرعية، ونحن نطبق خوارزمية WordPiece tokenization باستخدام مفردات من التكرار السابق، والنظر فقط فرعية التي تبدأ في نقطة الانقسام.
على سبيل المثال، لنفرض أننا تنفيذ الخطوة 2 من الخوارزمية واجهت كلمة undeniable
. في التكرار الأول، فإننا نعتبر كل فرعية، على سبيل المثال، {u, un, und, ..., undeniable, ##n, ##nd, ..., ##ndeniable, ...}
.
الآن ، بالنسبة للتكرار الثاني ، سننظر فقط في مجموعة فرعية منها. لنفترض أنه بعد التكرار الأول ، فإن أجزاء الكلمات ذات الصلة هي:
un, ##deni, ##able, ##ndeni, ##iable
وWordPiece خوارزمية إرادة شريحة ذلك في un ##deni ##able
(راجع المقطع تطبيق WordPiece لمزيد من المعلومات). في هذه الحالة، وسوف ننظر فقط فرعية التي تبدأ عند نقطة تجزئة. ونحن لا تزال تنظر كل نهاية الموقف ممكن. حتى خلال التكرار الثاني، ومجموعة من s
ل undeniable
هو:
{u, un, und, unden, undeni, undenia, undeniab, undeniabl, undeniable, ##d, ##de, ##den, ##deni, ##denia, ##deniab, ##deniabl , ##deniable, ##a, ##ab, ##abl, ##able}
الخوارزمية متطابقة. في هذا المثال، في التكرار الأول، الخوارزمية تنتج suprious الرموز ##ndeni
و ##iable
. الآن ، لم يتم النظر في هذه الرموز المميزة أبدًا ، لذلك لن يتم إنشاؤها بواسطة التكرار الثاني. نقوم بإجراء العديد من التكرارات فقط للتأكد من تقارب النتائج (على الرغم من عدم وجود ضمان تقارب حرفي).
تطبيق WordPiece
بمجرد إنشاء مفردات WordPiece ، نحتاج إلى أن نكون قادرين على تطبيقها على البيانات الجديدة. الخوارزمية هي تطبيق جشع بسيط يطابق الأطول أولاً.
على سبيل المثال، والنظر في تقسيم كلمة undeniable
.
علينا أولا البحث undeniable
في القاموس WordPiece لدينا، وإذا كان في الوقت الحاضر، نحن القيام به. إن لم يكن، ونحن إنقاص نقطة النهاية التي كتبها حرف واحد، وتكرار، على سبيل المثال، undeniabl
.
في النهاية ، سنجد إما ترجمة فرعية في مفرداتنا ، أو ننتقل إلى حرف واحد مترجم. (بشكل عام، فإننا نفترض أن كل حرف في قاموسنا، على الرغم من أن هذا قد لا يكون الحال بالنسبة للأحرف Unicode نادرة. وإذا واجهتنا حرف Unicode النادر أن ليس في المفردات نحن ببساطة الخريطة بأكملها كلمة ل <unk>
).
في هذه الحالة، نجد un
في قاموسنا. هذه هي أول قطعة كلمة لدينا. ثم نقفز إلى نهاية un
وتكرار المعالجة، على سبيل المثال، في محاولة للعثور على ##deniable
، ثم ##deniabl
، وما إلى ذلك ويتكرر هذا حتى قمنا بتقسيم الكلمة بأكملها.
البديهة
بشكل حدسي ، يحاول ترميز WordPiece تحقيق هدفين مختلفين:
Tokenize البيانات في أقل عدد من القطع ممكن. من المهم أن تضع في اعتبارك أن خوارزمية WordPiece لا "تريد" تقسيم الكلمات. خلاف ذلك، فإنه سيكون مجرد تقسيم كل كلمة في شخصياته، على سبيل المثال،
human -> {h, ##u, ##m, ##a, #n}
. هذا هو الشيء الوحيد المهم أن يجعل مختلفة WordPiece من شق المورفولوجية، والتي سوف تقسيم الصرفية اللغوية حتى عن كلمات شائعة (على سبيل المثال،unwanted -> {un, want, ed}
).عندما يتعين تقسيم الكلمة إلى أجزاء ، قم بتقسيمها إلى أجزاء تحتوي على أقصى عدد في بيانات التدريب. على سبيل المثال، والسبب كلمة
undeniable
أن يكون الانقسام إلى{un, ##deni, ##able}
بدلا من البدائل مثل{unde, ##niab, ##le}
هو أن التهم عنun
و##able
في خاصة ستكون عالية جدًا ، نظرًا لأن هذه هي البادئات واللواحق الشائعة. على الرغم من أن عدد ل##le
يجب أن يكون أعلى من##able
، التهم انخفاضunde
و##niab
سيجعل هذا أقل "مرغوب فيه" tokenization إلى الخوارزمية.
اختياري: tf.lookup
إذا كنت بحاجة إلى الوصول إلى، أو المزيد من السيطرة على المفردات ومن الجدير بالذكر أنه يمكنك بناء جدول البحث نفسك وتمرير ذلك إلى BertTokenizer
.
عند تمرير سلسلة، BertTokenizer
يفعل ما يلي:
pt_lookup = tf.lookup.StaticVocabularyTable(
num_oov_buckets=1,
initializer=tf.lookup.TextFileInitializer(
filename='pt_vocab.txt',
key_dtype=tf.string,
key_index = tf.lookup.TextFileIndex.WHOLE_LINE,
value_dtype = tf.int64,
value_index=tf.lookup.TextFileIndex.LINE_NUMBER))
pt_tokenizer = text.BertTokenizer(pt_lookup)
الآن لديك وصول مباشر إلى جدول البحث المستخدم في الرمز المميز.
pt_lookup.lookup(tf.constant(['é', 'um', 'uma', 'para', 'não']))
<tf.Tensor: shape=(5,), dtype=int64, numpy=array([7765, 85, 86, 87, 7765])>
أنت لا تحتاج إلى استخدام ملف المفردات، tf.lookup
لديها خيارات مهيئ أخرى. إذا كان لديك المفردات في الذاكرة التي يمكن استخدامها lookup.KeyValueTensorInitializer
:
pt_lookup = tf.lookup.StaticVocabularyTable(
num_oov_buckets=1,
initializer=tf.lookup.KeyValueTensorInitializer(
keys=pt_vocab,
values=tf.range(len(pt_vocab), dtype=tf.int64)))
pt_tokenizer = text.BertTokenizer(pt_lookup)