Mã hóa bằng văn bản TF

Xem trên TensorFlow.org Chạy trong Google Colab Xem trên GitHub Tải xuống sổ ghi chép Xem các mẫu TF Hub

Tổng quat

Token hóa là quá trình chia nhỏ một chuỗi thành các mã thông báo. Thông thường, những mã thông báo này là từ, số và / hoặc dấu chấm câu. Các tensorflow_text gói cung cấp một số tokenizers sẵn cho tiền xử lý văn bản theo yêu cầu của mô hình dựa trên văn bản của bạn. Bằng cách thực hiện mã hóa trong đồ thị TensorFlow, bạn sẽ không cần phải lo lắng về sự khác biệt giữa quy trình đào tạo và suy luận và quản lý các tập lệnh tiền xử lý.

Hướng dẫn này thảo luận về nhiều tùy chọn mã hóa được cung cấp bởi TensorFlow Text, khi bạn có thể muốn sử dụng tùy chọn này thay cho tùy chọn khác và cách các trình mã hóa này được gọi từ bên trong mô hình của bạn.

Thành lập

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

API Splitter

Các giao diện chính là SplitterSplitterWithOffsets mà có phương pháp đơn splitsplit_with_offsets . Các SplitterWithOffsets biến thể (kéo dài Splitter ) bao gồm một tùy chọn để nhận offsets byte. Điều này cho phép người gọi biết những byte nào trong chuỗi ban đầu mà mã thông báo đã tạo được tạo từ đó.

Các TokenizerTokenizerWithOffsets là phiên bản đặc biệt của Splitter cung cấp các phương pháp thuận tiện tokenizetokenize_with_offsets tương ứng.

Nói chung, đối với bất kỳ đầu vào N-chiều, các thẻ trở lại đang ở trong một N + 1 chiều RaggedTensor với kích thước nội hầu hết các thẻ lập bản đồ với dây cá nhân ban đầu.

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

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

Ngoài ra còn có một Detokenizer giao diện. Bất kỳ trình mã hóa nào triển khai giao diện này đều có thể chấp nhận tensor mã N-chiều rách nát và thường trả về tensor N-1 chiều hoặc tensor rách nát có các mã thông báo đã cho được lắp ráp lại với nhau.

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

Tokenizers

Dưới đây là bộ công cụ nướng bánh mì do TensorFlow Text cung cấp. Đầu vào chuỗi được giả định là UTF-8. Vui lòng xem lại hướng dẫn Unicode để chuyển đổi chuỗi sang UTF-8.

Toàn bộ từ tokenizers

Những trình mã hóa này cố gắng chia một chuỗi theo từng từ và là cách trực quan nhất để tách văn bản.

WhitespaceTokenizer

Các text.WhitespaceTokenizer là tokenizer cơ bản nhất mà chia tách chuỗi trên ICU định nghĩa ký tự khoảng trắng (ví dụ. Không gian, tab, dòng sản phẩm mới). Điều này thường tốt cho việc nhanh chóng tạo ra các mô hình nguyên mẫu.

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.']]

Bạn có thể nhận thấy một kết quả ngắn gọn của tokenizer này là dấu chấm câu được bao gồm trong từ để tạo nên một mã thông báo. Để chia các từ và dấu chấm câu vào thẻ riêng biệt, UnicodeScriptTokenizer nên được sử dụng.

UnicodeScriptTokenizer

Các UnicodeScriptTokenizer tách chuỗi dựa trên ranh giới kịch bản Unicode. Các mã tập lệnh được sử dụng tương ứng với các thành phần quốc tế cho các giá trị UScriptCode Unicode (ICU). Xem: http://icu-project.org/apiref/icu4c/uscript_8h.html

Trong thực tế, điều này cũng tương tự như WhitespaceTokenizer với sự khác biệt rõ ràng hạnh phúc nhất mà nó sẽ chia chấm câu (USCRIPT_COMMON) từ văn bản ngôn ngữ (ví dụ. USCRIPT_LATIN, USCRIPT_CYRILLIC, vv) trong khi cũng tách văn bản ngôn ngữ lẫn nhau. Lưu ý rằng điều này cũng sẽ chia các từ co lại thành các mã thông báo riêng biệt.

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'.']]

Tokenizers từ khóa phụ

Các tokenizer từ phụ có thể được sử dụng với vốn từ vựng nhỏ hơn và cho phép mô hình có một số thông tin về các từ mới từ các từ phụ tạo ra nó.

Chúng tôi hiểu sơ bộ về các tùy chọn Subword tokenization dưới đây, nhưng các hướng dẫn Subword tokenization đi sâu hơn và cũng giải thích làm thế nào để tạo ra các tập tin vocab.

WordpieceTokenizer

Mã hóa từ mảnh ghép là một sơ đồ mã hóa theo hướng dữ liệu tạo ra một tập hợp các mã thông báo phụ. Các mã thông báo phụ này có thể tương ứng với các morphemes ngôn ngữ, nhưng trường hợp này thường không xảy ra.

WordpieceTokenizer mong đợi dữ liệu đầu vào đã được chia thành các mã thông báo. Do điều kiện tiên quyết này, bạn sẽ thường xuyên muốn chia bằng cách sử dụng WhitespaceTokenizer hoặc UnicodeScriptTokenizer trước.

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.']]

Sau chuỗi được chia thành tokens, các WordpieceTokenizer có thể được sử dụng để chia thành 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 phản ánh việc triển khai mã hóa ban đầu từ giấy BERT. Điều này được hỗ trợ bởi WordpieceTokenizer, nhưng cũng thực hiện các tác vụ bổ sung như chuẩn hóa và mã hóa các từ trước tiên.

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'.']]]

Câu văn

Câu vănTokenizer là một trình mã thông báo phụ có khả năng định cấu hình cao. Điều này được hỗ trợ bởi thư viện Câu văn. Giống như BertTokenizer, nó có thể bao gồm chuẩn hóa và phân tách mã thông báo trước khi tách thành các mã thông báo phụ.

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'.']]

Bộ tách khác

UnicodeCharTokenizer

Điều này chia một chuỗi thành các ký tự UTF-8. Nó rất hữu ích cho các ngôn ngữ CJK không có khoảng cách giữa các từ.

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

Đầu ra là mã điểm mã Unicode. Điều này cũng có thể hữu ích để tạo các ngram ký tự, chẳng hạn như bigram. Để chuyển đổi lại thành ký tự 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

Đây là phần tóm tắt xung quanh các mô hình được triển khai cho TF Hub để thực hiện các cuộc gọi dễ dàng hơn vì TF Hub hiện không hỗ trợ các bộ căng dây bị rách. Việc có một mô hình thực hiện mã hóa đặc biệt hữu ích cho các ngôn ngữ CJK khi bạn muốn tách thành các từ, nhưng không có khoảng trống để cung cấp hướng dẫn heuristic. Tại thời điểm này, chúng tôi có một mô hình phân đoạn duy nhất cho tiếng Trung.

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']]

Có thể khó xem kết quả của chuỗi byte được mã hóa UTF-8. Giải mã các giá trị danh sách để giúp xem dễ dàng hơn.

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

Các SplitMergeTokenizer & SplitMergeFromLogitsTokenizer có một mục đích nhắm của tách một chuỗi dựa trên giá trị với điều kiện là chỉ ra nơi chuỗi nên chia. Điều này hữu ích khi xây dựng các mô hình phân đoạn của riêng bạn như ví dụ về Phân đoạn trước đó.

Đối với SplitMergeTokenizer , một giá trị từ 0 được sử dụng để chỉ sự bắt đầu của một chuỗi mới, và các giá trị của 1 cho thấy nhân vật này là một phần của chuỗi hiện hành.

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

Các SplitMergeFromLogitsTokenizer là tương tự, nhưng nó thay vì chấp nhận cặp giá trị logit từ một mạng lưới thần kinh mà dự đoán nếu mỗi nhân vật sẽ được tách ra thành một chuỗi mới hoặc sáp nhập vào hiện tại.

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

Các RegexSplitter có thể chuỗi phân khúc tại breakpoint tùy ý xác định bởi một biểu thức chính quy được cung cấp.

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.']]

Bù đắp

Khi mã hóa các chuỗi, người ta thường muốn biết mã thông báo bắt nguồn từ đâu trong chuỗi gốc. Vì lý do này, mỗi tokenizer mà cụ TokenizerWithOffsets có một phương pháp tokenize_with_offsets rằng sẽ trả lại offsets byte cùng với các thẻ. Start_offsets liệt kê các byte trong chuỗi ban đầu mà mỗi mã thông báo bắt đầu và end_offsets liệt kê các byte ngay sau điểm mà mỗi mã thông báo kết thúc. Để điều chỉnh lại, các hiệu số bắt đầu là bao gồm và các hiệu số cuối là loại trừ.

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

Giải phóng mặt bằng

Tokenizers mà thực hiện Detokenizer cung cấp một detokenize phương pháp mà cố gắng để kết hợp các chuỗi. Điều này có khả năng bị mất dữ liệu, do đó, chuỗi đã tách ra có thể không phải lúc nào cũng khớp chính xác với chuỗi gốc, được mã hóa trước.

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."]

Dữ liệu TF

Dữ liệu TF là một API mạnh mẽ để tạo đường dẫn đầu vào cho các mô hình đào tạo. Tokenizers hoạt động như mong đợi với 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!']]