Посмотреть на 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 +--мерном 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. Пожалуйста , ознакомьтесь с руководством Unicode для преобразования строк в кодировку UTF-8.
Токенизаторы целого слова
Эти токенизаторы пытаются разбить строку по словам и являются наиболее интуитивно понятным способом разделения текста.
WhitespaceTokenizer
text.WhitespaceTokenizer
является самым основным токенизатором который разделяет строки на ОЯТ определенные символы пробелов (напр. Пробел, табуляция, новая строка). Это часто полезно для быстрого создания моделей-прототипов.
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
разбивает строки , основанные на границах сценария Unicode. Используемые коды скриптов соответствуют значениям UScriptCode международных компонентов Unicode (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'.']]
Токенизаторы подслов
Токенизаторы подслов могут использоваться с меньшим словарным запасом и позволяют модели получать некоторую информацию о новых словах из подслов, которые создают их.
Мы кратко обсудим возможные варианты подсловной лексемизации ниже, но учебник подсловной лексемизацию идет больше в глубине , а также объясняет , как генерировать файлы 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]]
На выходе будут кодовые точки Unicode. Это также может быть полезно для создания символьных нграмм, таких как биграммы. Чтобы преобразовать обратно в символы 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
имеют целенаправленную целью разделения строки на основе предоставленных значений , которые указывают , где строка должна быть разделена. Это полезно при построении ваших собственных моделей сегментации, подобных предыдущему примеру сегментации.
Для 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!']]