رمزگذاری با TF Text

مشاهده در TensorFlow.org در Google Colab اجرا شود در GitHub مشاهده کنید دانلود دفترچه یادداشت مدل های TF Hub را ببینید

بررسی اجمالی

توکن سازی فرآیندی است که در آن یک رشته به توکن تقسیم می شود. معمولاً این نشانه ها کلمات، اعداد و/یا علائم نگارشی هستند. tensorflow_text بسته فراهم می کند تعداد tokenizers موجود برای پیش پردازش متن مورد نیاز مدل های مبتنی بر متن خود را. با انجام توکن سازی در نمودار TensorFlow، دیگر نیازی به نگرانی در مورد تفاوت بین جریان کار آموزش و استنتاج و مدیریت اسکریپت های پیش پردازش نخواهید داشت.

این راهنما در مورد بسیاری از گزینه‌های توکن‌سازی ارائه‌شده توسط TensorFlow Text، زمانی که ممکن است بخواهید از یک گزینه بر روی گزینه دیگر استفاده کنید، و نحوه فراخوانی این توکن‌سازها از داخل مدل شما بحث می‌کند.

برپایی

pip install -q tensorflow-text
import requests
import tensorflow as tf
import tensorflow_text as tf_text

Splitter API

رابط اصلی عبارتند از Splitter و SplitterWithOffsets که روش تنها split و split_with_offsets . SplitterWithOffsets نوع (که گسترش Splitter ) شامل گزینه ای برای گرفتن آفست بایت. این به تماس گیرنده اجازه می دهد تا بداند کد ایجاد شده از کدام بایت های رشته اصلی ایجاد شده است.

Tokenizer و TokenizerWithOffsets نسخه تخصصی هستند Splitter که روش های راحتی فراهم tokenize و tokenize_with_offsets است.

به طور کلی، برای هر ورودی N بعدی، نشانه بازگشت در یک N + 1 بعدی هستند RaggedTensor با ابعاد درونی ترین از نشانه های نقشه برداری به رشته اصلی فردی است.

class Splitter {
  @abstractmethod
  def split(self, input)
}

class SplitterWithOffsets(Splitter) {
  @abstractmethod
  def split_with_offsets(self, input)
}

همچنین یک وجود دارد Detokenizer رابط. هر توکنایزری که این رابط را پیاده‌سازی می‌کند، می‌تواند یک تانسور ژنده‌دار N بعدی از توکن‌ها را بپذیرد، و معمولاً یک تانسور بعدی N-1 یا تانسور ژنده‌دار که توکن‌های داده‌شده را با هم مونتاژ کرده است، برمی‌گرداند.

class Detokenizer {
  @abstractmethod
  def detokenize(self, input)
}

توکن سازها

در زیر مجموعه ای از توکن سازها ارائه شده توسط TensorFlow Text است. ورودی های رشته ای UTF-8 فرض می شود. لطفا بررسی راهنمای یونیکد برای تبدیل رشته به UTF-8.

توکن سازهای کل کلمه

این نشانه‌سازها سعی می‌کنند یک رشته را با کلمات تقسیم کنند و بصری‌ترین راه برای تقسیم متن است.

WhitespaceTokenizer

text.WhitespaceTokenizer tokenizer اساسی ترین که تجزیه رشته ها در ICU تعریف کاراکترهای فضای سفید (به عنوان مثال. فاصله، tab، خط جدید) است. این اغلب برای ساخت سریع مدل های نمونه اولیه خوب است.

tokenizer = tf_text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py:206: batch_gather (from tensorflow.python.ops.array_ops) is deprecated and will be removed after 2017-10-25.
Instructions for updating:
`tf.batch_gather` is deprecated, please use `tf.gather` with `batch_dims=-1` instead.
[[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]

ممکن است متوجه کاستی این نشانه گذاری شوید این است که برای ساختن یک نشانه، علائم نگارشی با کلمه گنجانده شده است. به تقسیم کلمات و علائم نقطه گذاری به نشانه جداگانه، UnicodeScriptTokenizer باید استفاده شود.

UnicodeScriptTokenizer

UnicodeScriptTokenizer تجزیه رشته بر اساس مرزهای اسکریپت یونیکد. کدهای اسکریپت استفاده شده با مقادیر UScriptCode مؤلفه های بین المللی برای یونیکد (ICU) مطابقت دارد. نگاه کنید به: http://icu-project.org/apiref/icu4c/uscript_8h.html

در عمل، این است شبیه به WhitespaceTokenizer با ترین آنها تفاوت ظاهری که آن را نقطه گذاری (USCRIPT_COMMON) از متون زبان (به عنوان مثال. USCRIPT_LATIN، USCRIPT_CYRILLIC، و غیره) در حالی که همچنین جدا متون زبان از یکدیگر تقسیم می شود. توجه داشته باشید که این کار کلمات انقباضی را نیز به نشانه های جداگانه تقسیم می کند.

tokenizer = tf_text.UnicodeScriptTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b'can', b"'", b't', b'explain', b',', b'but', b'you', b'feel', b'it', b'.']]

توکن سازهای زیرکلمه

نشانه‌سازهای زیرکلمه‌ای را می‌توان با واژگان کوچک‌تری استفاده کرد و به مدل اجازه می‌دهد تا اطلاعاتی درباره کلمات جدید از زیرکلمه‌هایی که آن را ایجاد می‌کنند داشته باشد.

ما به طور خلاصه گزینه Subword از Tokenization در زیر مورد بحث، اما آموزش Subword از Tokenization می رود بیشتر در عمق و همچنین توضیح میدهد که چگونه برای تولید فایل های vocab است.

WordpieceTokenizer

توکن‌سازی WordPiece یک طرح توکن‌سازی مبتنی بر داده است که مجموعه‌ای از نشانه‌های فرعی را تولید می‌کند. این نشانه های فرعی ممکن است با تکواژهای زبانی مطابقت داشته باشند، اما اغلب اینطور نیست.

WordpieceTokenizer انتظار دارد که ورودی از قبل به توکن ها تقسیم شود. از آنجا که این پیش شرط، شما اغلب می خواهند به تقسیم با استفاده از WhitespaceTokenizer یا UnicodeScriptTokenizer از قبل.

tokenizer = tf_text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]

پس از رشته به نشانه تقسیم، WordpieceTokenizer را می توان به تقسیم به subtokens استفاده می شود.

url = "https://github.com/tensorflow/text/blob/master/tensorflow_text/python/ops/test_data/test_wp_en_vocab.txt?raw=true"
r = requests.get(url)
filepath = "vocab.txt"
open(filepath, 'wb').write(r.content)
52382
subtokenizer = tf_text.UnicodeScriptTokenizer(filepath)
subtokens = tokenizer.tokenize(tokens)
print(subtokens.to_list())
[[[b'What'], [b'you'], [b'know'], [b'you'], [b"can't"], [b'explain,'], [b'but'], [b'you'], [b'feel'], [b'it.']]]

BertTokenizer

BertTokenizer اجرای اصلی توکن سازی را از کاغذ BERT منعکس می کند. این مورد توسط WordpieceTokenizer پشتیبانی می‌شود، اما ابتدا وظایف اضافی مانند عادی‌سازی و نشانه‌گذاری به کلمات را نیز انجام می‌دهد.

tokenizer = tf_text.BertTokenizer(filepath, token_out_type=tf.string, lower_case=True)
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[[b'what'], [b'you'], [b'know'], [b'you'], [b'can'], [b"'"], [b't'], [b'explain'], [b','], [b'but'], [b'you'], [b'feel'], [b'it'], [b'.']]]

SentencepieceTokenizer

SentencepieceTokenizer یک توکنیزه کننده فرعی است که بسیار قابل تنظیم است. این توسط کتابخانه Sentencepiece پشتیبانی می شود. مانند BertTokenizer، می‌تواند شامل عادی‌سازی و تقسیم توکن قبل از تقسیم به زیر توکن‌ها باشد.

url = "https://github.com/tensorflow/text/blob/master/tensorflow_text/python/ops/test_data/test_oss_model.model?raw=true"
sp_model = requests.get(url).content
tokenizer = tf_text.SentencepieceTokenizer(sp_model, out_type=tf.string)
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'\xe2\x96\x81What', b'\xe2\x96\x81you', b'\xe2\x96\x81know', b'\xe2\x96\x81you', b'\xe2\x96\x81can', b"'", b't', b'\xe2\x96\x81explain', b',', b'\xe2\x96\x81but', b'\xe2\x96\x81you', b'\xe2\x96\x81feel', b'\xe2\x96\x81it', b'.']]

تقسیم کننده های دیگر

UnicodeCharTokenizer

این یک رشته را به کاراکترهای UTF-8 تقسیم می کند. برای زبان های CJK که فاصله بین کلمات ندارند مفید است.

tokenizer = tf_text.UnicodeCharTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[87, 104, 97, 116, 32, 121, 111, 117, 32, 107, 110, 111, 119, 32, 121, 111, 117, 32, 99, 97, 110, 39, 116, 32, 101, 120, 112, 108, 97, 105, 110, 44, 32, 98, 117, 116, 32, 121, 111, 117, 32, 102, 101, 101, 108, 32, 105, 116, 46]]

خروجی کدهای یونیکد است. این می تواند برای ایجاد ngram های کاراکتر مانند bigrams نیز مفید باشد. برای تبدیل مجدد به کاراکترهای UTF-8.

characters = tf.strings.unicode_encode(tf.expand_dims(tokens, -1), "UTF-8")
bigrams = tf_text.ngrams(characters, 2, reduction_type=tf_text.Reduction.STRING_JOIN, string_separator='')
print(bigrams.to_list())
[[b'Wh', b'ha', b'at', b't ', b' y', b'yo', b'ou', b'u ', b' k', b'kn', b'no', b'ow', b'w ', b' y', b'yo', b'ou', b'u ', b' c', b'ca', b'an', b"n'", b"'t", b't ', b' e', b'ex', b'xp', b'pl', b'la', b'ai', b'in', b'n,', b', ', b' b', b'bu', b'ut', b't ', b' y', b'yo', b'ou', b'u ', b' f', b'fe', b'ee', b'el', b'l ', b' i', b'it', b't.']]

HubModuleTokenizer

از آنجایی که TF Hub در حال حاضر از تانسورهای ناهموار پشتیبانی نمی‌کند، این یک پوشش در اطراف مدل‌های مستقر در TF Hub است تا تماس‌ها را آسان‌تر کند. زمانی که می‌خواهید به کلمات تقسیم شوید، اما فضایی برای ارائه راهنمای اکتشافی ندارید، داشتن یک مدل برای توکن‌سازی به‌ویژه برای زبان‌های CJK مفید است. در حال حاضر، ما یک مدل تقسیم بندی واحد برای چینی ها داریم.

MODEL_HANDLE = "https://tfhub.dev/google/zh_segmentation/1"
segmenter = tf_text.HubModuleTokenizer(MODEL_HANDLE)
tokens = segmenter.tokenize(["新华社北京"])
print(tokens.to_list())
[[b'\xe6\x96\xb0\xe5\x8d\x8e\xe7\xa4\xbe', b'\xe5\x8c\x97\xe4\xba\xac']]

ممکن است مشاهده نتایج رشته های بایت کدگذاری شده UTF-8 دشوار باشد. مقادیر لیست را رمزگشایی کنید تا مشاهده آسان تر شود.

def decode_list(x):
  if type(x) is list:
    return list(map(decode_list, x))
  return x.decode("UTF-8")

def decode_utf8_tensor(x):
  return list(map(decode_list, x.to_list()))

print(decode_utf8_tensor(tokens))
[['新华社', '北京']]

SplitMergeTokenizer

SplitMergeTokenizer و SplitMergeFromLogitsTokenizer یک هدف هدفمند از تقسیم یک رشته بر اساس ارزش ارائه شده است که نشان می دهد که در آن رشته باید تقسیم شود. این هنگام ساختن مدل‌های تقسیم‌بندی خود مانند نمونه‌ی Segmentation قبلی مفید است.

برای SplitMergeTokenizer ، مقدار 0 استفاده شده است تا شروع یک رشته جدید، و ارزش 1 نشان می دهد شخصیت بخشی از رشته فعلی است.

strings = ["新华社北京"]
labels = [[0, 1, 1, 0, 1]]
tokenizer = tf_text.SplitMergeTokenizer()
tokens = tokenizer.tokenize(strings, labels)
print(decode_utf8_tensor(tokens))
[['新华社', '北京']]

SplitMergeFromLogitsTokenizer مشابه است، اما آن را به جای جفت ارزش لوجیت از یک شبکه عصبی که پیش بینی کند اگر هر یک از شخصیت باید به یک رشته جدید تقسیم و یا ادغام یک جریان را می پذیرد.

strings = [["新华社北京"]]
labels = [[[5.0, -3.2], [0.2, 12.0], [0.0, 11.0], [2.2, -1.0], [-3.0, 3.0]]]
tokenizer = tf_text.SplitMergeFromLogitsTokenizer()
tokenizer.tokenize(strings, labels)
print(decode_utf8_tensor(tokens))
[['新华社', '北京']]

RegexSplitter

RegexSplitter قادر به رشته بخش در نقاط شکست دلخواه تعریف شده توسط یک عبارت منظم ارائه شده است.

splitter = tf_text.RegexSplitter("\s")
tokens = splitter.split(["What you know you can't explain, but you feel it."], )
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]

افست

هنگام توکن کردن رشته‌ها، اغلب می‌خواهند بدانیم که رمز از کجا در رشته اصلی منشا گرفته است. به همین دلیل، هر tokenizer که پیاده سازی TokenizerWithOffsets یک روش tokenize_with_offsets که آفست بایت همراه با نشانه های بازگشت. start_offsets بایت‌های رشته اصلی را که هر نشانه از آن شروع می‌شود، فهرست می‌کند و end_offsets بایت‌ها را بلافاصله بعد از نقطه‌ای که هر نشانه به پایان می‌رسد فهرست می‌کند. برای بازنویسی، افست های شروع شامل و افست های پایانی انحصاری هستند.

tokenizer = tf_text.UnicodeScriptTokenizer()
(tokens, start_offsets, end_offsets) = tokenizer.tokenize_with_offsets(['Everything not saved will be lost.'])
print(tokens.to_list())
print(start_offsets.to_list())
print(end_offsets.to_list())
[[b'Everything', b'not', b'saved', b'will', b'be', b'lost', b'.']]
[[0, 11, 15, 21, 26, 29, 33]]
[[10, 14, 20, 25, 28, 33, 34]]

دتوکنیزاسیون

Tokenizers که اجرای Detokenizer را ارائه detokenize روش که تلاش برای ترکیب رشته ها. این احتمال تلف شدن را دارد، بنابراین رشته رمزگشایی شده ممکن است همیشه دقیقاً با رشته اصلی و از پیش توکن شده مطابقت نداشته باشد.

tokenizer = tf_text.UnicodeCharTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
strings = tokenizer.detokenize(tokens)
print(strings.numpy())
[[87, 104, 97, 116, 32, 121, 111, 117, 32, 107, 110, 111, 119, 32, 121, 111, 117, 32, 99, 97, 110, 39, 116, 32, 101, 120, 112, 108, 97, 105, 110, 44, 32, 98, 117, 116, 32, 121, 111, 117, 32, 102, 101, 101, 108, 32, 105, 116, 46]]
[b"What you know you can't explain, but you feel it."]

داده های TF

TF Data یک API قدرتمند برای ایجاد خط لوله ورودی برای مدل های آموزشی است. توکن سازها همانطور که انتظار می رود با API کار می کنند.

docs = tf.data.Dataset.from_tensor_slices([['Never tell me the odds.'], ["It's a trap!"]])
tokenizer = tf_text.WhitespaceTokenizer()
tokenized_docs = docs.map(lambda x: tokenizer.tokenize(x))
iterator = iter(tokenized_docs)
print(next(iterator).to_list())
print(next(iterator).to_list())
[[b'Never', b'tell', b'me', b'the', b'odds.']]
[[b"It's", b'a', b'trap!']]