مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
این آموزش نشان می دهد که چگونه برای تولید یک فرهنگ لغت 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 .
در مورد جملات مثال بالا به چند نکته توجه کنید:
- آنها حروف کوچک هستند.
- در اطراف علائم نگارشی فضاهایی وجود دارد.
- مشخص نیست که از نرمال سازی یونیکد استفاده می شود یا نه.
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
تابع واژگان تولید کند.
آرگومان های زیادی وجود دارد که می توانید برای تنظیم رفتار آن تنظیم کنید. برای این آموزش، بیشتر از پیش فرض ها استفاده می کنید. اگر شما می خواهید برای کسب اطلاعات بیشتر در مورد گزینه، برای اولین بار در مورد خواندن الگوریتم ، و سپس نگاهی به کد .
این حدود 2 دقیقه طول می کشد.
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
به طوری که آنها را می توان با آموزش های دیگر وارد شده است.
توکن سازی سفارشی
آموزش پایین دست هر دو انتظار متن token ها که شامل [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 از پایین به بالا است، بر اساس رمزگذاری بایت جفت . مانند 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
.
در نهایت، یا یک نشانه فرعی در دایره لغات خود پیدا می کنیم، یا به یک نشانه فرعی منفرد می رسیم. (به طور کلی، ما فرض کنیم که هر شخصیت در فرهنگ لغت ما است، اگر چه ممکن است این مورد برای شخصیت های نادر یونیکد نیست. اگر ما یک شخصیت نادر یونیکد که در واژگان روبرو می شوند ما به سادگی بر روی نقشه کل کلمه به <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
اگر شما نیاز به دسترسی به، یا کنترل بیشتری روی واژگان ارزش آن را اشاره کرد که شما می توانید در جدول 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)