সাবওয়ার্ড টোকেনাইজার

TensorFlow.org এ দেখুন Google Colab-এ চালান GitHub-এ উৎস দেখুন নোটবুক ডাউনলোড করুন

এই টিউটোরিয়ালটি কিভাবে প্রমান একটি ডেটাসেটের থেকে একটি subword শব্দভান্ডার উৎপন্ন, এবং এটি ব্যবহার নির্মাণের text.BertTokenizer শব্দভান্ডার থেকে।

একটি সাবওয়ার্ড টোকেনাইজারের প্রধান সুবিধা হল এটি শব্দ-ভিত্তিক এবং অক্ষর-ভিত্তিক টোকেনাইজেশনের মধ্যে ইন্টারপোলেট করে। সাধারণ শব্দগুলি শব্দভাণ্ডারে একটি স্লট পায়, কিন্তু টোকেনাইজার অজানা শব্দগুলির জন্য শব্দের টুকরো এবং পৃথক অক্ষরগুলিতে ফিরে যেতে পারে।

ওভারভিউ

tensorflow_text প্যাকেজ অনেক সাধারণ tokenizers এর TensorFlow বাস্তবায়নের অন্তর্ভুক্ত করা হয়েছে। এর মধ্যে তিনটি সাবওয়ার্ড-স্টাইল টোকেনাইজার রয়েছে:

  • text.BertTokenizer - BertTokenizer বর্গ একটি উচ্চ স্তরের ইন্টারফেস। এটা তোলে বার্ট এর টোকেন বিভাজন এলগরিদম এবং অন্তর্ভুক্ত WordPieceTokenizer । এটা তোলে ইনপুট হিসাবে বাক্য নেয় এবং টোকেন-ID- র ফেরৎ।
  • text.WordpieceTokenizer - WordPieceTokenizer বর্গ একটি নিম্ন স্তরের ইন্টারফেসে হয়। এটা শুধুমাত্র প্রয়োগ WordPiece অ্যালগরিদম । টেক্সটটিকে কল করার আগে আপনাকে অবশ্যই মানসম্মত এবং শব্দে বিভক্ত করতে হবে। এটা তোলে ইনপুট হিসাবে শব্দ নেয় এবং টোকেন-ID- র ফেরৎ।
  • text.SentencepieceTokenizer - SentencepieceTokenizer একটি আরো জটিল সেটআপ দরকার। এর সূচনাকারীর জন্য একটি প্রাক-প্রশিক্ষিত বাক্যাংশ মডেল প্রয়োজন। দেখুন Google / sentencepiece সংগ্রহস্থলের কিভাবে এই একজন মডেল গড়ে তুলতে নির্দেশাবলীর জন্য। যখন tokenizing ইনপুট হিসাবে বাক্য গ্রহণ করতে পারে।

এই টিউটোরিয়ালটি বিদ্যমান শব্দ থেকে শুরু করে উপরের নিচের পদ্ধতিতে একটি Wordpiece শব্দভান্ডার তৈরি করে। এই প্রক্রিয়াটি জাপানি, চাইনিজ বা কোরিয়ানদের জন্য কাজ করে না কারণ এই ভাষায় স্পষ্ট মাল্টি-অক্ষর ইউনিট নেই। এইসব ভাষার conside ব্যবহার tokenize করার 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]

আপনি তাদের টেক্সট উপস্থাপনা সহ টোকেন ID- র প্রতিস্থাপন হলে ( 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 তাই তারা অন্যান্য টিউটোরিয়াল দ্বারা আমদানিকৃত করা যেতে পারে।

কাস্টম টোকেনাইজেশন

স্রোতবরাবর টিউটোরিয়াল উভয় tokenized পাঠ্য অন্তর্ভুক্ত আশা [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)>

কাস্টম ডিটোকেনাইজেশন

টোকেনাইজার রপ্তানি করার আগে ডাউনস্ট্রিম টিউটোরিয়ালের জন্য আপনি কিছু জিনিস পরিষ্কার করতে পারেন:

  1. তারা পরিষ্কার টেক্সট আউটপুট গঠন করি, সুতরাং মত সংরক্ষিত টোকেন ড্রপ করতে চান [START] , [END] এবং [PAD]
  2. তারা সম্পূর্ণ স্ট্রিং প্রতি আগ্রহ দেখিয়েছেন, তাই একটি স্ট্রিং বরাবর যোগদানের আবেদন 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 TEXT এর শব্দভান্ডার জেনারেটর থেকে টপ-ডাউন বাস্তবায়ন নিম্নরূপ বার্ট । শব্দ দিয়ে শুরু করে এবং সেগুলোকে ছোট ছোট উপাদানে ভেঙ্গে ফেলুন যতক্ষণ না তারা ফ্রিকোয়েন্সি থ্রেশহোল্ডে আঘাত করে, বা আরও ভাঙা যায় না। পরবর্তী বিভাগে এটি বিস্তারিতভাবে বর্ণনা করা হয়েছে। জাপানি, চাইনিজ এবং কোরিয়ানদের জন্য এই টপ-ডাউন পদ্ধতিটি কাজ করে না যেহেতু শুরু করার জন্য কোন সুস্পষ্ট শব্দ ইউনিট নেই। তাদের জন্য আপনি একটি প্রয়োজন ভিন্ন পদ্ধতি

শব্দভান্ডার নির্বাচন করা

টপ-ডাউন WordPiece প্রজন্ম আলগোরিদিম (শব্দ, সংখ্যা) যুগল ও একটি থ্রেশহোল্ড একটি সেট লাগে T , এবং আয় একটি শব্দভান্ডার V

অ্যালগরিদম পুনরাবৃত্তিমূলক। এটা তোলে জন্য চালানো হয় k পুনরাবৃত্তিও, যেখানে সাধারণত k = 4 , কিন্তু শুধুমাত্র প্রথম দুই সত্যিই গুরুত্বপূর্ণ। তৃতীয় এবং চতুর্থ (এবং এর পরেও) দ্বিতীয়টির সাথে একই রকম। নোট বাইনারি সার্চের প্রতিটি ধাপের জন্য গোড়া থেকে অ্যালগরিদম রান যে k পুনরাবৃত্তিও।

নীচে বর্ণিত পুনরাবৃত্তি:

প্রথম পুনরাবৃত্তি

  1. পুনরুক্তি প্রতিটি শব্দ এবং ইনপুট মধ্যে গণনা যুগল উপর, যেমন প্রকাশ (w, c)
  2. প্রতিটি শব্দের জন্য w , যে সাবস্ট্রিং, যেমন প্রকাশ উৎপন্ন s । যেমন, শব্দ জন্য human , আমরা উৎপন্ন {h, hu, hum, huma, human, ##u, ##um, ##uma, ##uman, ##m, ##ma, ##man, #a, ##an, ##n}
  3. একটি সাবস্ট্রিং টু গণনা হ্যাশ মানচিত্র বজায় রাখুন, এবং প্রতিটি গণনা বাড়ায় s দ্বারা c । যেমন, আমরা যদি আছে (human, 113) এবং (humas, 3) আমাদের ইনপুট এ, গণনা s = huma হতে হবে 113+3=116
  4. একবার আমরা যে সাবস্ট্রিং এর গন্য সংগৃহীত করেছি, বারবার উপর (s, c) দীর্ঘতম দিয়ে শুরু জোড়া s প্রথম।
  5. কোন রাখুন s একটি আছে যা c > T । যেমন, যদি T = 100 এবং আমরা আছে (pers, 231); (dogs, 259); (##rint; 76) , তাহলে আমরা রাখা হবে pers এবং dogs
  6. যখন একটি 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 শব্দভান্ডার তৈরি হয়ে গেলে, আমাদের এটিকে নতুন ডেটাতে প্রয়োগ করতে সক্ষম হতে হবে। অ্যালগরিদম হল একটি সাধারণ লোভী দীর্ঘতম-ম্যাচ-প্রথম অ্যাপ্লিকেশন।

উদাহরণ হিসেবে বলা যায়, শব্দ segmenting বিবেচনা undeniable

আমরা প্রথম লুকআপ undeniable আমাদের WordPiece অভিধানে, এবং যদি এটা বর্তমান, আমরা কাজ সম্পন্ন হয়। যদি তা না হয়, আমরা এক অক্ষর, এবং পুনরাবৃত্তি, যেমন, দ্বারা শেষ বিন্দু হ্রাস undeniabl

অবশেষে, আমরা হয় আমাদের শব্দভান্ডারে একটি সাবটোকেন খুঁজে পাব, অথবা একটি একক অক্ষর সাবটোকেনে নেমে যাব। (সাধারণভাবে, আমরা ধরে নিই যে যে চরিত্র, আমাদের শব্দভান্ডার রয়েছে যদিও এই শক্তি বিরল ইউনিকোড অক্ষর কেনার ক্ষেত্রে না। আমরা একটি বিরল ইউনিকোড অক্ষর শব্দভান্ডার মধ্যে নয় সম্মুখীন হলে কেবলমাত্র আমরা সমগ্র শব্দ ম্যাপ <unk> )।

এই ক্ষেত্রে, আমরা খুঁজে un আমাদের শব্দভান্ডার হবে। তাই যে আমাদের প্রথম শব্দ টুকরা. তারপর আমরা শেষে লাফ un এবং প্রক্রিয়াকরণ পুনরাবৃত্তি, যেমন, খুঁজতে চেষ্টা ##deniable , তাহলে ##deniabl , ইত্যাদি যতক্ষণ না আমরা সমগ্র শব্দ ভাগ করেছি এই পুনরাবৃত্তি করা হয়।

অন্তর্দৃষ্টি

স্বজ্ঞাতভাবে, WordPiece টোকেনাইজেশন দুটি ভিন্ন উদ্দেশ্য সন্তুষ্ট করার চেষ্টা করছে:

  1. যতটা সম্ভব টুকরা অন্তত সংখ্যা ডেটা Tokenize। এটা মনে রাখা গুরুত্বপূর্ণ যে WordPiece অ্যালগরিদম শব্দগুলিকে বিভক্ত করতে "চায় না"। অন্যথায়, এটি ঠিক এর অক্ষর, যেমন, প্রতিটি শব্দ বিভক্ত হবে human -> {h, ##u, ##m, ##a, #n} । এই এক সমালোচনামূলক জিনিস যে অঙ্গসংস্থান splitters, যা এমনকি সাধারণ শব্দ জন্য ভাষাগত morphemes বিভক্ত থেকে WordPiece বিভিন্ন তোলে (যেমন, unwanted -> {un, want, ed} )।

  2. যখন একটি শব্দকে টুকরো টুকরো করে বিভক্ত করতে হয়, তখন সেটিকে টুকরো টুকরো করে বিভক্ত করুন যার প্রশিক্ষণ ডেটাতে সর্বাধিক গণনা রয়েছে। উদাহরণস্বরূপ, কারণ শব্দ 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)