日付を保存! Google I / Oが5月18日から20日に戻ってきます今すぐ登録
このページは Cloud Translation API によって翻訳されました。
Switch to English

テキストタスク用の一般的なSavedModelAPI

このページでは、方法について説明しTF2 SavedModelsテキスト関連のタスクのために実装する必要があり再利用可能なSavedModelのAPIを。 (これは、現在非推奨のTF1ハブ形式のテキスト共通署名を置き換えて拡張します。)

概要概要

テキスト埋め込みテキストの密な表現、またはテキスト特徴ベクトルとも呼ばれます)を計算するためのAPIがいくつかあります。

  • テキスト入力からのテキスト埋め込み用のAPIは、文字列のバッチを埋め込みベクトルのバッチにマップするSavedModelによって実装されます。これは非常に使いやすく、TFハブの多くのモデルで実装されています。ただし、これではTPUでモデルを微調整することはできません。

  • 前処理された入力を使用したテキスト埋め込みのAPIは同じタスクを解決しますが、2つの別々のSavedModelsによって実装されます。

    • tf.data入力パイプライン内で実行でき、文字列やその他の可変長データを数値テンソルに変換できるプリプロセッサ
    • プリプロセッサの結果を受け入れ、埋め込み計算のトレーニング可能な部分を実行するエンコーダ

    この分割により、トレーニングループに入力される前に、入力を非同期的に前処理することができます。特に、 TPUで実行および微調整できるエンコーダーを構築できます。

  • Transformerエンコーダーを使用したテキスト埋め込み用のAPIは、テキスト埋め込み用のAPIを、前処理された入力からBERTおよびその他のTransformerエンコーダーの特定のケースに拡張します。

    • プリプロセッサは、入力テキストの複数のセグメントからエンコーダ入力を構築するように拡張されています。

    • Transformerエンコーダーは、個々のトークンのコンテキスト認識埋め込みを公開します。

いずれの場合も、モデルのドキュメントに別段の定めがない限り、テキスト入力はUTF-8でエンコードされた文字列であり、通常はプレーンテキストです。

APIに関係なく、さまざまなモデルがさまざまな言語やドメインのテキストで事前にトレーニングされており、さまざまなタスクを念頭に置いています。したがって、すべてのテキスト埋め込みモデルがすべての問題に適しているわけではありません。

テキスト入力からのテキスト埋め込み

テキスト入力からのテキスト埋め込み用のSavedModelは、文字列Tensor of shape [batch_size]の入力のバッチを受け入れ、入力の密な表現(特徴ベクトル)を持つfloat32 Tensor of shape [batch_size, dim]マップします。

使用法の概要

obj = hub.load("path/to/model")
text_input = ["A long sentence.",
              "single-word",
              "http://example.com"]
embeddings = obj(text_input)

Reusable SavedModel APIから、モデルをトレーニングモード(ドロップアウトなど)で実行するにはキーワード引数obj(..., training=True)が必要な場合があり、 obj.variables.trainable_variables属性.variables.trainable_variables.regularization_lossesを提供することを.variables 。 。

Kerasでは、これはすべてによって処理されます

embeddings = hub.KerasLayer("path/to/model", trainable=...)(text_input)

分散トレーニング

テキスト埋め込みが配布戦略でトレーニングされるモデルの一部として使用される場合、 hub.load("path/to/model")またはhub.KerasLayer("path/to/model", ...) 、それぞれ、分散方式でモデルの変数を作成するには、DistributionStrategyスコープ内で発生する必要があります。例えば

  with strategy.scope():
    ...
    model = hub.load("path/to/model")
    ...

前処理された入力を使用したテキスト埋め込み

前処理された入力を含むテキスト埋め込みは、2つの別々のSavedModelsによって実装されます。

  • 形状[batch_size]文字列テンソルを数値テンソルの辞書にマップするプリプロセッサ
  • プリプロセッサによって返される、実行embbedding計算の訓練可能な部分をテンソルの辞書を受け付け、出力の辞書を返しエンコーダ。キー"default"下の出力は、形状[batch_size, dim] float32テンソルです。

これにより、入力パイプラインでプリプロセッサを実行できますが、より大きなモデルの一部としてエンコーダによって計算された埋め込みを微調整できます。特に、 TPUで実行および微調整できるエンコーダーを構築できます。

これは、プリプロセッサの出力に含まれるテンソルと、エンコーダの出力に含まれる"default"以外の追加のテンソル(存在する場合)の実装の詳細"default"

エンコーダのドキュメントでは、エンコーダで使用するプリプロセッサを指定する必要があります。通常、正しい選択は1つだけです。

使用法の概要

text_input = tf.constant(["A long sentence.",
                          "single-word",
                          "http://example.com"])
preprocessor = hub.load("path/to/preprocessor")  # Must match `encoder`.
encoder_inputs = preprocessor(text_input)

encoder = hub.load("path/to/encoder")
enocder_outputs = encoder(encoder_inputs)
embeddings = enocder_outputs["default"]

Reusable SavedModel APIから、エンコーダーをトレーニングモード(ドロップアウトなど)で実行するには、キーワード引数encoder(..., training=True)が必要な場合があり、 encoderは、 .trainable_variables.regularization_lossesて属性.variables.trainable_variables 、および.regularization_lossesを提供することを.variables 。 。

preprocessorモデルには.variablesが含まれている場合があり.variablesが、それ以上のトレーニングを目的としたものではありません。前処理はモードに依存しませんpreprocessor()training=...引数がある場合、効果はありません。

Kerasでは、これはすべてによって処理されます

encoder_inputs = hub.KerasLayer("path/to/preprocessor")(text_input)
encoder_outputs = hub.KerasLayer("path/to/encoder", trainable=True)(encoder_inputs)
embeddings = encoder_outputs["default"]

分散トレーニング

エンコーダーが配布戦略でトレーニングされるモデルの一部として使用される場合、 hub.load("path/to/encoder") hub.KerasLayer("path/to/encoder", ...) hub.load("path/to/encoder")またはhub.KerasLayer("path/to/encoder", ...) 、それぞれ、内部で発生する必要があります

  with strategy.scope():
    ...

分散方式でエンコーダ変数を再作成するため。

同様に、プリプロセッサがトレーニング済みモデルの一部である場合(上記の簡単な例のように)、配布戦略スコープの下でロードする必要もあります。しかし、プリプロセッサが入力パイプラインに使用されている場合(例えば、に渡された呼び出し可能にtf.data.Dataset.map()そのロードは(もしあればその変数を配置するために、流通戦略の範囲外で行われる必要があります)ホストCPU上。

Transformerエンコーダーによるテキスト埋め込み

テキストのトランスエンコーダはNに結合したいくつかのモデル固有の内、各シーケンスはトークン化テキストのN≥1つのセグメントを含む、入力シーケンスのバッチ上で動作します。 BERTとその拡張機能の多くでは、その境界は2であるため、単一のセグメントとセグメントのペアを受け入れます。

Transformerエンコーダーを使用したテキスト埋め込み用のAPIは、前処理された入力を使用したテキスト埋め込み用のAPIをこの設定に拡張します。

プリプロセッサ

Transformerエンコーダーを使用したテキスト埋め込み用のプリプロセッサーSavedModelは、前処理された入力を使用したテキスト埋め込み用のプリプロセッサーSavedModelのAPIを実装し(上記を参照)、単一セグメントのテキスト入力をエンコーダー入力に直接マッピングする方法を提供します。

また、プリプロセッサSavedModelは、呼び出し可能なサブオブジェクトが提供するtokenize (別々のセグメントごとに)トークン化とのためbert_pack_inputsエンコーダのための1つの入力シーケンスにNトークン化セグメントを梱包します。各サブオブジェクトは、 Reusable SavedModelAPIに従います

使用法の概要

テキストの2つのセグメントの具体例として、前提(最初のセグメント)が仮説(2番目のセグメント)を暗示しているかどうかを尋ねる文含意タスクを見てみましょう。

preprocessor = hub.load("path/to/preprocessor")

# Tokenize batches of both text inputs.
text_premises = tf.constant(["The quick brown fox jumped over the lazy dog.",
                             "Good day."])
tokenized_premises = preprocessor.tokenize(text_premises)
text_hypotheses = tf.constant(["The dog was lazy.",  # Implied.
                               "Axe handle!"])       # Not implied.
tokenized_hypotheses = preprocessor.tokenize(text_hypotheses)

# Pack input sequences for the Transformer encoder.
seq_length = 128
encoder_inputs = preprocessor.bert_pack_inputs(
    [tokenized_premises, tokenized_hypotheses],
    seq_length=seq_length)  # Optional argument.

Kerasでは、この計算は次のように表現できます。

tokenize = hub.KerasLayer(preprocessor.tokenize)
tokenized_hypotheses = tokenize(text_hypotheses)
tokenized_premises = tokenize(text_premises)

bert_pack_inputs = hub.KerasLayer(
    preprocessor.bert_pack_inputs,
    arguments=dict(seq_length=seq_length))  # Optional argument.
encoder_inputs = bert_pack_inputs([tokenized_premises, tokenized_hypotheses])

tokenize詳細

preprocessor.tokenize()呼び出しは、形状[batch_size]文字列Tensorを受け入れ、入力文字列を表すint32トークンIDの値を持つ形状[batch_size, ...] RaggedTensorを返します。 R≥1つの後にボロボロの次元が存在することができbatch_sizeが、ありません、他の均一な寸法。

  • r = 1の場合、形状は[batch_size, (tokens)]であり、各入力は単純にトークンのフラットシーケンスにトークン化されます。
  • r > 1の場合、 r -1の追加レベルのグループ化があります。たとえば、 tensorflow_text.BertTokenizerr = 2を使用してトークンを単語でグループ化し[batch_size, (words), (tokens_per_word)]形状[batch_size, (words), (tokens_per_word)]ます。これらの追加レベルがいくつ存在するか、およびそれらがどのグループを表すかは、手元のモデル次第です。

ユーザーは、トークン化された入力を変更できます(ただし、変更する必要はありません)。たとえば、エンコーダー入力のパッキングで適用されるseq_length制限に対応するためです。トークナイザー出力の余分な次元は、ここでは役立ちますが(たとえば、単語の境界を尊重するため)、次のステップでは意味がなくなります。

Reusable SavedModel APIに関しては、 preprocessor.tokenizeオブジェクトに.variablesが含まれている場合があり.variablesが、これ以上トレーニングすることを意図したものではありません。トークン化はモードに依存しません。preprocessor.tokenize preprocessor.tokenize()training=...引数がある場合、効果はありません。

bert_pack_inputs詳細

preprocessor.bert_pack_inputs()を呼び出すと、トークン化された入力のPythonリスト(入力セグメントごとに個別にバッチ処理されます)が受け入れられ、Transformerエンコーダーモデルの固定長入力シーケンスのバッチを表すTensorsのdictが返されます。

トークン化された各入力は、形状[batch_size, ...] int32 RaggedTensor [batch_size, ...]ここで、batch_sizeの後の不規則な次元の数rは、1またはpreprocessor.tokenize().出力と同じpreprocessor.tokenize(). (後者は便宜上のものです。余分な寸法は梱包前に平らにされます。)

パッキングは、エンコーダーが期待するように、入力セグメントの周りに特別なトークンを追加します。 bert_pack_inputs()呼び出しは、元のBERTモデルとその拡張機能の多くで使用されているパッキングスキームを正確に実装します。パックされたシーケンスは、1つのシーケンス開始トークンで始まり、その後にトークン化されたセグメントが続き、それぞれが1つのセグメント終了で終了します。トークン。 seq_lengthまでの残りの位置は、存在する場合、パディングトークンで埋められます。

パックされたシーケンスがseq_lengthを超える場合、 bert_pack_inputs()は、パックされたシーケンスがseq_length内に正確に収まるように、セグメントをほぼ同じサイズのプレフィックスに切り捨てます。

パッキングはモードに依存しませんpreprocessor.bert_pack_inputs()training=...引数がある場合、効果はありません。また、 preprocessor.bert_pack_inputsは変数を持ったり、微調整をサポートしたりすることは期待されていません。

エンコーダー

エンコーダーは、 Reusable SavedModel APIからのプロビジョニングを含め、前処理された入力(上記を参照)を使用したテキスト埋め込みのAPIと同じ方法で、 encoder_inputsのdictでencoder_inputsます

使用法の概要

enocder = hub.load("path/to/encoder")
enocder_outputs = encoder(encoder_inputs)

または同等にKerasで:

encoder = hub.KerasLayer("path/to/encoder", trainable=True)
encoder_outputs = encoder(encoder_inputs)

詳細

encoder_outputsは、次のキーを持つテンソルのdictです。

  • "sequence_output" :形状[batch_size, seq_length, dim] float32テンソルで[batch_size, seq_length, dim]パックされたすべての入力シーケンスの各トークンがコンテキストアウェアに埋め込まれています。
  • "pooled_output" :float32形状[batch_size, dim]テンソルで、各入力シーケンス全体が埋め込まれており、いくつかのトレーニング可能な方法でsequence_outputから導出されます。
  • 前処理された入力を使用したテキスト埋め込みのAPIで必要とされる"default" :各入力シーケンスの埋め込みを伴う形状[batch_size, dim] float32テンソル。 (これは、pooled_outputの単なるエイリアスである可能性があります。)

このAPI定義では、 encoder_inputsの内容は厳密には必要ありません。ただし、BERTスタイルの入力を使用するエンコーダーの場合、エンコーダーの交換とプリプロセッサーモデルの再利用の摩擦を最小限に抑えるために、(TensorFlow Model GardenのNLPモデリングツールキットから)次の名前を使用することをお勧めします。

  • "input_word_ids" :パックされた入力シーケンスのトークンID(つまり、シーケンスの開始トークン、セグメントの終了トークン、およびパディングを含む)を持つ形状[batch_size, seq_length] int32テンソル。
  • "input_mask" :形状[batch_size, seq_length] int32テンソルで[batch_size, seq_length]パディングの前に存在するすべての入力トークンの位置に値1があり、パディングトークンの値は0です。
  • "input_type_ids" :それぞれの位置に入力トークンを生成した入力セグメントのインデックスを持つ形状[batch_size, seq_length] int32テンソル。最初の入力セグメント(インデックス0)には、シーケンスの開始トークンとそのセグメントの終了トークンが含まれます。 2番目以降のセグメント(存在する場合)には、それらの応答性のあるセグメント終了トークンが含まれます。パディングトークンは再びインデックス0を取得します。

分散トレーニング

配布戦略スコープの内部または外部でプリプロセッサおよびエンコーダオブジェクトをロードする場合、前処理された入力を使用したテキスト埋め込みのAPIと同じルールが適用されます(上記を参照)。