Alt kelime belirteçleri

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çerir WordPieceTokenizer . 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:

  1. Onlar çok temiz metin çıktısı oluşturmak gibi saklıdır tokenlardan istiyorum [START] , [END] ve [PAD] .
  2. 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

  1. Yineleme girişi, her bir kelime sayısı çifti üzerinden, olarak belirtilen (w, c) .
  2. Her bir kelime için w olarak ifade her alt dize oluşturmak s . Örneğin, kelime için human ürettiğimiz {h, hu, hum, huma, human, ##u, ##um, ##uma, ##uman, ##m, ##ma, ##man, #a, ##an, ##n} .
  3. Bir alt-için-sayım karma ilk muhafaza, ve bunların her biri sayımını artırmak s göre c . Biz varsa Örneğin, (human, 113) ve (humas, 3) bizim girişte, bir sayım s = huma olacak 113+3=116 .
  4. Her alt dize sayıları topladığınızda, yinelerler üzerinde (s, c) çiftleri en uzun başlayarak s ilk.
  5. Herhangi tutun s bir sahiptir c > T . Örneğin, eğer T = 100 ve sahip (pers, 231); (dogs, 259); (##rint; 76) , o zaman tutacak pers ve dogs .
  6. Bir zaman s tutulur, onun ön eklerinin hepsi onun sayımı çıkarıyoruz. Bu, tüm sıralama nedeni s , 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 diyelim human ve biz almak (huma, 116) . Bunu biliyoruz 113 olanların 116 geldi human ve 3 geldi humas . Ancak, şimdi bu human bizim kelime içinde olduğunu, biz asla segmenti bilmek human içine huma ##n . Böylece bir kez human tutuldu, ardından huma sadece etkili bir sayıya sahipse 3 .

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 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:

  1. 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ğin unwanted -> {un, want, ed} ).

  2. 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)