TFテキストによるトークン化

TensorFlow.orgで表示GoogleColabで実行GitHubで表示 ノートブックをダウンロードTFハブモデルを参照してください

概要

トークン化は、文字列をトークンに分割するプロセスです。通常、これらのトークンは単語、数字、句読点です。 tensorflow_textパッケージには、テキストベースのモデルで必要なテキストを前処理に利用可能なトークナイザの数を提供します。 TensorFlowグラフでトークン化を実行することにより、トレーニングワークフローと推論ワークフローの違いや前処理スクリプトの管理について心配する必要がなくなります。

このガイドでは、TensorFlow Textが提供する多くのトークン化オプション、あるオプションを別のオプションで使用する場合、およびこれらのトークナイザーがモデル内からどのように呼び出されるかについて説明します。

設定

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

スプリッターAPI

主なインターフェイスは、 SplitterSplitterWithOffsets単方法有するsplitsplit_with_offsetsSplitterWithOffsets (拡張バリアントSplitter )バイトオフセットを取得するためのオプションが含まれています。これにより、呼び出し元は、作成されたトークンが元の文字列のどのバイトから作成されたかを知ることができます。

TokenizerTokenizerWithOffsets専門のバージョンである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)
}

トークナイザー

以下は、TensorFlowTextが提供する一連のトークナイザーです。文字列入力はUTF-8であると想定されています。確認してくださいUnicodeのガイドをUTF-8に文字列を変換します。

単語全体のトークナイザー

これらのトークナイザーは、文字列を単語ごとに分割しようとします。これは、テキストを分割するための最も直感的な方法です。

WhitespaceTokenizer

text.WhitespaceTokenizer ICU定義された空白文字(例えばスペース、タブ、改行)で文字列を分割し、最も基本的なトークナイザです。これは、プロトタイプモデルをすばやく構築するのに適していることがよくあります。

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のスクリプトの境界に基づいて文字列を分割します。使用されるスクリプトコードは、International Components for Unicode(ICU)UScriptCode値に対応しています。参照: http://icu-project.org/apiref/icu4c/uscript_8h.html

実際には、これはと似てWhitespaceTokenizerもお互いに言語のテキストを分離しながら(例えば。USCRIPT_LATIN、USCRIPT_CYRILLIC、など)は、最も明白な違いは、それは言語のテキストから句読点(USCRIPT_COMMON)を分割することであることで。これにより、縮約語も別々のトークンに分割されることに注意してください。

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

サブワードトークナイザー

サブワードトークナイザーは、より小さな語彙で使用でき、モデルがそれを作成するサブワードからの新しい単語に関する情報を持つことができます。

当社は、以下に簡単にサブワードトークン化オプションを議論するが、サブワードトークン化のチュートリアルでは、より深くなり、また、単語ファイルを生成する方法について説明します。

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サブトークンに分割するために使用することができます。

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コードポイントです。これは、バイグラムなどの文字ngramを作成する場合にも役立ちます。 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が現在不規則なテンソルをサポートしていないため、呼び出しを容易にするためにTFHubにデプロイされたモデルのラッパーです。モデルにトークン化を実行させることは、単語に分割したいがヒューリスティックガイドを提供するスペースがない場合に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

SplitMergeTokenizerSplitMergeFromLogitsTokenizer 、文字列を分割すべき場所を示す提供された値に基づいて文字列を分割の標的目的を持っています。これは、前のセグメンテーションの例のように独自のセグメンテーションモデルを構築するときに役立ちます。

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似ていますが、代わりに各文字が新しい文字列に分割したり、現在の1にマージする必要があるかどうかを予測ニューラルネットワークからロジット値のペアを受け入れます。

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

オフセット

文字列をトークン化する場合、元の文字列のどこからトークンが発生したかを知りたいことがよくあります。このため、実装の各トークナイザのため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]]

トークン化解除

実装のトークナイザ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!']]