TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
Bu öğretici bir veri kümesinden bir alt-kelime kelime oluşturmak ve bir inşa etmek nasıl kullanılacağını gösterir text.BertTokenizer
kelime arası.
Bir alt sözcük belirteçleştiricinin ana avantajı, sözcük tabanlı ve karakter tabanlı belirteçleştirme arasında enterpolasyon yapmasıdır. Yaygın kelimeler, kelime dağarcığında bir yer alır, ancak belirteç, bilinmeyen kelimeler için kelime parçalarına ve bireysel karakterlere geri dönebilir.
genel bakış
tensorflow_text
paketi birçok ortak tokenizers ait TensorFlow uygulamaları içermektedir. Bu, üç alt kelime stili belirteç içerir:
-
text.BertTokenizer
-BertTokenizer
sınıfı daha yüksek bir seviyede bir arabirimdir. Bu Bert'in belirteç bölme algoritmasını ve bir içerirWordPieceTokenizer
. Bu girdi olarak cümleler alır ve belirteç kimlikleri döndürür. -
text.WordpieceTokenizer
-WordPieceTokenizer
sınıfı daha düşük seviyeli bir arabirimdir. Sadece uygulayan WordPiece algoritması . Aramadan önce metni standartlaştırmalı ve sözcüklere ayırmalısınız. Bu girdi olarak kelime alır ve belirteç kimlikleri döndürür. -
text.SentencepieceTokenizer
-SentencepieceTokenizer
daha karmaşık bir kurulum gerektirir. Başlatıcısı, önceden eğitilmiş bir cümle modeli gerektirir. Bkz google / sentencepiece deposunu bu modellerin biri nasıl oluşturulacağı ile ilgili talimatlar için. Tokenizing zaman girdi olarak cümleler kabul edebilir.
Bu öğretici, mevcut sözcüklerden başlayarak yukarıdan aşağıya bir Sözcük Parçası sözcük dağarcığı oluşturur. Bu işlem Japonca, Çince veya Korece için çalışmaz çünkü bu diller çok karakterli net birimlere sahip değildir. Conside kullanarak bu dilleri tokenize için text.SentencepieceTokenizer
, text.UnicodeCharTokenizer
veya bu yaklaşımı .
Kurmak
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()
Veri kümesini indirin
Dan Portekizce / İngilizce çeviri veri kümesi Getirme 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']
Bu veri kümesi Portekizce/İngilizce cümle çiftleri üretir:
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 .
Yukarıdaki örnek cümleler hakkında birkaç şeye dikkat edin:
- Onlar küçük harf.
- Noktalama işaretlerinin etrafında boşluklar var.
- Unicode normalleştirmenin kullanılıp kullanılmadığı veya ne olduğu açık değil.
train_en = train_examples.map(lambda pt, en: en)
train_pt = train_examples.map(lambda pt, en: pt)
kelime dağarcığı oluştur
Bu bölüm, bir veri kümesinden bir sözcük dağarcığı oluşturur. Zaten bir kelime dosyası var ve sadece nasıl oluşturulacağını görmek istiyorsanız text.BertTokenizer
veya text.Wordpiece
o zaman ileride atlayabilirsiniz ile dizgeciklerini Build'a tokenizer bölümü.
Kelime nesil kod dahildir tensorflow_text
pip paketinin. Varsayılan olarak içe aktarılmaz, manuel olarak içe aktarmanız gerekir:
from tensorflow_text.tools.wordpiece_vocab import bert_vocab_from_dataset as bert_vocab
bert_vocab.bert_vocab_from_dataset
fonksiyonu kelime üretecektir.
Davranışını ayarlamak için ayarlayabileceğiniz birçok argüman vardır. Bu eğitim için çoğunlukla varsayılanları kullanacaksınız. Eğer diğer seçeneklerle ilgili bilgi edinmek istiyorsanız, ilk hakkında okumak algoritma ve sonra bir göz kod .
Bu yaklaşık 2 dakika sürer.
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
İşte ortaya çıkan kelime dağarcığının bazı dilimleri.
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'] ['##–', '##—', '##‘', '##’', '##“', '##”', '##⁄', '##€', '##♪', '##♫']
Bir kelime dosyası yazın:
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)
İngilizce verilerden bir kelime hazinesi oluşturmak için bu işlevi kullanın:
%%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'] ['##_', '##`', '##ย', '##ร', '##อ', '##–', '##—', '##’', '##♪', '##♫']
İşte iki kelime dosyası:
write_vocab_file('en_vocab.txt', en_vocab)
ls *.txt
en_vocab.txt pt_vocab.txt
Belirteç oluştur
text.BertTokenizer
(Bkz ilk argüman olarak kelime dosyanın yolunu geçirerek başlatılabilir tf.lookup diğer seçenekler için):
pt_tokenizer = text.BertTokenizer('pt_vocab.txt', **bert_tokenizer_params)
en_tokenizer = text.BertTokenizer('en_vocab.txt', **bert_tokenizer_params)
Artık bazı metinleri kodlamak için kullanabilirsiniz. İngilizce verilerden bir grup 3 örnek alın:
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 ."
Aracılığıyla Run BertTokenizer.tokenize
yöntemiyle. Başlangıçta, bu, bir geri tf.RaggedTensor
eksenleri (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]
Onların metin temsiller ile belirteç kimlikleri değiştirin (kullanarak tf.gather
) sözcükleri ilk örnekteki görebiliriz "searchability"
ve "serendipity"
ayrılacak olan "search ##ability"
ve "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)>
Ekstre belirteçleri kelimeleri yeniden birleştirmek için, kullanımı BertTokenizer.detokenize
yöntemi:
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)>
Özelleştirme ve dışa aktarma
Bu öğretici tarafından kullanılan metin dizgeciklerini ve detokenizer oluşturur Trafo öğretici. Bu bölümde kullanarak yöntemler ve bu öğretici basitleştirmek için işlem basamaklarını ve ihracat tokenizers ekler tf.saved_model
diğer öğreticiler tarafından ithal edilebilmesi için.
Özel jetonlaştırma
Mansap öğreticiler hem simgeleştirilmiş metin dahil bekliyoruz [START]
ve [END]
belirteçleri.
reserved_tokens
kelime başındaki rezerv alanı, bu yüzden [START]
ve [END]
her iki dilde aynı dizinlere sahip:
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)>
Özel detokenizasyon
Belirteçleri dışa aktarmadan önce, aşağı akış öğreticileri için temizleyebileceğiniz birkaç şey vardır:
- Onlar çok temiz metin çıktısı oluşturmak gibi saklıdır tokenlardan istiyorum
[START]
,[END]
ve[PAD]
. - O kadar birlikte katılmak bir dize uygulamak, tam dizeleri ilgilendiğiniz
words
sonucun ekseni.
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)
İhracat
Aşağıdaki kod bloğu oluşturur CustomTokenizer
içermesi sınıf text.BertTokenizer
örneklerini özel mantık ve @tf.function
ihracat için gerekli sarmalayıcılarını.
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)
Bir İnşa CustomTokenizer
her dil için:
tokenizers = tf.Module()
tokenizers.pt = CustomTokenizer(reserved_tokens, 'pt_vocab.txt')
tokenizers.en = CustomTokenizer(reserved_tokens, 'en_vocab.txt')
Bir şekilde tokenizers aktarın 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.
Yükle saved_model
ve yöntemler test:
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 !
İçin Arşivle çevirisi öğreticiler :
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
İsteğe bağlı: Algoritma
Burada, WordPiece algoritmasının iki versiyonu olduğunu belirtmekte fayda var: Aşağıdan yukarıya ve yukarıdan aşağıya. Her iki durumda da amaç aynıdır: "Bir eğitim derlemi ve bir dizi arzu edilen simge D verildiğinde, optimizasyon problemi, seçilen sözcük parçası modeline göre bölümlere ayrıldığında ortaya çıkan sözcük parçası sayısında minimum olacak şekilde D sözcük parçalarını seçmektir. "
Orijinal aşağıdan yukarı WordPiece algoritması dayanmaktadır bayt çift kodlama . BPE gibi, alfabe ile başlar ve kelime parçaları ve kelimeler oluşturmak için ortak bigramları yinelemeli olarak birleştirir.
TensorFlow metin en kelime jeneratör gelen yukarıdan aşağıya uygulanmasını izler bert . Sözcüklerle başlayıp, bunları frekans eşiğine ulaşana veya daha fazla parçalanamayana kadar daha küçük bileşenlere ayırın. Bir sonraki bölüm bunu ayrıntılı olarak açıklamaktadır. Japonca, Çince ve Korece için bu yukarıdan aşağıya yaklaşım işe yaramaz çünkü başlangıçta açık bir kelime birimi yoktur. Olanlar için bir ihtiyaç farklı bir yaklaşım .
Kelime seçimi
WordPiece yukarıdan aşağıya üretme algoritması (kelime, sayısı) çifti ve bir eşik kümesi alır T
, ve duruma göre bir kelime V
.
Algoritma yinelemelidir. Bu aday olan k
tipik tekrarlamalar, k = 4
, ama sadece ilk iki gerçekten önemlidir. Üçüncü ve dördüncü (ve ötesi) sadece ikinci ile aynıdır. Not ikili aramanın her adımı için sıfırdan algoritmayı çalışır k
tekrarlamalar.
Aşağıda açıklanan yinelemeler:
İlk yineleme
- Yineleme girişi, her bir kelime sayısı çifti üzerinden, olarak belirtilen
(w, c)
. - Her bir kelime için
w
olarak ifade her alt dize oluşturmaks
. Örneğin, kelime içinhuman
ürettiğimiz{h, hu, hum, huma, human, ##u, ##um, ##uma, ##uman, ##m, ##ma, ##man, #a, ##an, ##n}
. - Bir alt-için-sayım karma ilk muhafaza, ve bunların her biri sayımını artırmak
s
görec
. Biz varsa Örneğin,(human, 113)
ve(humas, 3)
bizim girişte, bir sayıms = huma
olacak113+3=116
. - Her alt dize sayıları topladığınızda, yinelerler üzerinde
(s, c)
çiftleri en uzun başlayaraks
ilk. - Herhangi tutun
s
bir sahiptirc > T
. Örneğin, eğerT = 100
ve sahip(pers, 231); (dogs, 259); (##rint; 76)
, o zaman tutacakpers
vedogs
. - Bir zaman
s
tutulur, onun ön eklerinin hepsi onun sayımı çıkarıyoruz. Bu, tüm sıralama nedenis
, aksi kelime çift sayılır, çünkü, bu algoritmanın, bir kritik bir parçasıdır, adım 4'te uzunluğu. Örneğin, biz tuttuk diyelimhuman
ve biz almak(huma, 116)
. Bunu biliyoruz113
olanların116
geldihuman
ve3
geldihumas
. Ancak, şimdi buhuman
bizim kelime içinde olduğunu, biz asla segmenti bilmekhuman
içinehuma ##n
. Böylece bir kezhuman
tutuldu, ardındanhuma
sadece etkili bir sayıya sahipse3
.
Bu algoritma sözcüğü parçalardan oluşan bir set oluşturur s
(tam kelimelerle olacak birçok w
bizim WordPiece kelime olarak kullanabilirsiniz).
Ancak bir sorun var: Bu algoritma kelime parçalarını aşırı derecede aşırı üretecek. Bunun nedeni, yalnızca önek belirteçlerinin sayısını çıkarmamızdır. Kelimesini tutmak nedenle, human
, biz sayımı kapalı düşeriz h, hu, hu, huma
, ancak için ##u, ##um, ##uma, ##uman
vb. Biz de oluşturabilir Yani human
ve ##uman
rağmen kelime parçaları olarak, ##uman
hiçbir zaman uygulanmaz.
Peki neden sadece her önek, her alt dizeyi sayıları çıkarıyoruz değil? Çünkü o zaman sayıları birden çok kez çıkarmamız gerekebilir. En bizler işleme diyelim s
uzunluğu 5 ve biz de tutmak (##denia, 129)
ve (##eniab, 137)
, 65
bu sayımların kelimesinden geldi undeniable
. Her alt dize kapalı çıkarma, biz çıkarmak istiyorum 65
alt dize gelen ##enia
yalnızca bir kez çıkarma gerektiğini rağmen, iki kere. Ancak, yalnızca öneklerden çıkarırsak, doğru olarak yalnızca bir kez çıkarılır.
İkinci (ve üçüncü ...) yineleme
Yukarıda bahsedilen aşırı üretim sorununu çözmek için algoritmanın birden çok yinelemesini gerçekleştiriyoruz.
Daha sonraki yineleme önemli bir ayrım ile birinci aynıdır: 2. adımda, yerine her alt dize dikkate nedeniyle, önceki yineleme gelen kelime kullanarak WordPiece dizgeciklere algoritmasını uygulamak ve sadece bölünmüş noktada başlar alt dizeleri düşünün.
Örneğin, biz algoritmanın Adım 2'yi uygulamak ve kelime karşılaşıyorsanız diyelim undeniable
. İlk yineleme, biz her alt dize, dikkate alacağını örneğin {u, un, und, ..., undeniable, ##n, ##nd, ..., ##ndeniable, ...}
.
Şimdi, ikinci yineleme için bunların yalnızca bir alt kümesini ele alacağız. Diyelim ki ilk yinelemeden sonra ilgili kelime parçaları:
un, ##deni, ##able, ##ndeni, ##iable
İçine WordPiece algoritması olacak segmenti, bu un ##deni ##able
(Bakınız uygulama WordPiece daha fazla bilgi için). Bu durumda, sadece bir segmentasyon noktada başlar alt dizeleri ele alacağız. Biz hala mümkün olan her uç konumu dikkate alacaktır. Yani ikinci tekrarında sırasında, set s
için undeniable
geçerli:
{u, un, und, unden, undeni, undenia, undeniab, undeniabl, undeniable, ##d, ##de, ##den, ##deni, ##denia, ##deniab, ##deniabl , ##deniable, ##a, ##ab, ##abl, ##able}
Algoritma aksi takdirde aynıdır. Bu örnekte, birinci tekrarda, algoritma suprious belirteçleri üretir ##ndeni
ve ##iable
. Şimdi, bu belirteçler hiçbir zaman dikkate alınmaz, bu nedenle ikinci yineleme tarafından üretilmezler. Sonuçların yakınsadığından emin olmak için birkaç yineleme gerçekleştiririz (gerçek yakınsama garantisi olmamasına rağmen).
WordPiece'i uygulama
Bir WordPiece sözlüğü oluşturulduktan sonra, onu yeni verilere uygulayabilmemiz gerekir. Algoritma, basit bir açgözlü en uzun eşleşme ilk uygulamasıdır.
Örneğin, kelime segmentlere düşünün undeniable
.
Biz ilk arama undeniable
bizim WordPiece sözlükte, ve 's görülse bile, işimiz biter. Değilse, bir karakter ve tekrar, örneğin tarafından bitiş noktasını azaltma undeniabl
.
Sonunda, ya kelime dağarcığımızda bir alt belirteç bulacağız ya da tek bir karakter alt belirtecine ineceğiz. (Genel olarak, bu kudreti nadir Unicode karakterleri için geçerli olmayabilir rağmen her karakter, bizim kelime olduğunu varsayalım. Biz sözlüğünde olmayan bir nadir Unicode karakter karşılaşırsanız biz sadece kelimenin tamamını eşlemek <unk>
).
Bu durumda, biz bulmak un
bizim kelime içinde. Yani bu bizim ilk kelime parçamız. Sonra sonuna atlamak un
ve bulmaya, örneğin, işleme tekrar ##deniable
sonra, ##deniabl
biz kelimenin tamamını bölümlere ayırdıktan kadar bu tekrarlanır vb.
Sezgi
Sezgisel olarak, WordPiece belirteci iki farklı hedefi karşılamaya çalışıyor:
Mümkün olan parçaların en az sayıda veri simgeleştirir. WordPiece algoritmasının sözcükleri bölmeyi "istemediğini" akılda tutmak önemlidir. Aksi takdirde, sadece kendi karakterler, örneğin içine her kelime ayıracak
human -> {h, ##u, ##m, ##a, #n}
. Bu bile yaygın sözcükler için dilsel morfemler bölecek morfolojik bölücülerin, gelen WordPiece farklı kılan bir kritik şeydir (örneğinunwanted -> {un, want, ed}
).Bir kelimenin parçalara ayrılması gerektiğinde, onu eğitim verilerinde maksimum sayıya sahip parçalara bölün. Örneğin, kelime nedeni
undeniable
içine bölünmüş olurdu{un, ##deni, ##able}
yerine gibi alternatiflere göre{unde, ##niab, ##le}
olduğuna ilişkin sayımlarıun
ve##able
içinde özellikle çok yüksek olacaktır, çünkü bunlar yaygın ön ekler ve son eklerdir. İçin sayım rağmen##le
daha yüksek olmalıdır##able
, düşük sayımlarıunde
ve##niab
bu algoritmaya daha az "arzu" dizgeciklere yapacaktır.
İsteğe bağlı: tf.lookup
Eğer 's değerinde Eğer arama masayı kendini inşa etmek ve bu geçebilir belirterek kelime üzerinde erişimi ya da daha fazla kontrol gerekiyorsa BertTokenizer
.
Bir dize geçirdiğinizde, BertTokenizer
aşağıdakileri yapar:
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)
Artık belirteçte kullanılan arama tablosuna doğrudan erişiminiz var.
pt_lookup.lookup(tf.constant(['é', 'um', 'uma', 'para', 'não']))
<tf.Tensor: shape=(5,), dtype=int64, numpy=array([7765, 85, 86, 87, 7765])>
Bir kelime dosyasını kullanmak gerekmez tf.lookup
diğer başlatıcı seçenekleri vardır. Eğer bellekte kelime varsa kullanabilirsiniz 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)