Transform TFX パイプライン コンポーネントは、 SchemaGenコンポーネントによって作成されたデータ スキーマを使用して、 ExampleGenコンポーネントから出力された tf.Examples に対して特徴量エンジニアリングを実行し、SavedModel と、変換前および変換後のデータの両方に関する統計の両方を出力します。実行されると、SavedModel は ExampleGen コンポーネントから出力された tf.Examples を受け入れ、変換された特徴データを出力します。
- ExampleGen コンポーネントからの tf.Examples、および SchemaGen コンポーネントからのデータ スキーマを使用します。
- 出力: SavedModel を Trainer コンポーネント、変換前および変換後の統計。
変換コンポーネントの構成
preprocessing_fn
を作成したら、python モジュールで定義する必要があります。これは入力として Transform コンポーネントに提供されます。このモジュールは Transform によってロードされ、 preprocessing_fn
という名前の関数が検出され、Transform によって前処理パイプラインの構築に使用されます。
transform = Transform(
examples=example_gen.outputs['examples'],
schema=schema_gen.outputs['schema'],
module_file=os.path.abspath(_taxi_transform_module_file))
さらに、 TFDVベースの変換前または変換後の統計計算にオプションを提供することもできます。これを行うには、同じモジュール内でstats_options_updater_fn
を定義します。
変換と TensorFlow 変換
Transform は、データセットに対して特徴量エンジニアリングを実行するためにTensorFlow Transformを広範囲に利用します。 TensorFlow Transform は、特徴データをモデルに送信する前にトレーニング プロセスの一部として変換するための優れたツールです。一般的な特徴変換には次のものがあります。
- 埋め込み: 高次元空間から低次元空間への意味のあるマッピングを見つけることによって、疎な特徴 (語彙によって生成される整数 ID など) を密な特徴に変換します。埋め込みの概要については、機械学習クラッシュ コースの「埋め込み」単元を参照してください。
- 語彙生成: それぞれの一意の値を ID 番号にマップする語彙を作成することにより、文字列またはその他の非数値特徴を整数に変換します。
- 値の正規化: 数値の特徴を変換して、すべてが同様の範囲内に収まるようにします。
- バケット化: 値を離散バケットに割り当てることにより、連続値特徴をカテゴリ特徴に変換します。
- テキスト機能の強化: トークン、N グラム、エンティティ、センチメントなどの生データから機能を生成して、機能セットを強化します。
TensorFlow Transform は、これらおよび他の多くの種類の変換のサポートを提供します。
最新のデータから語彙を自動的に生成します。
データをモデルに送信する前に、データに対して任意の変換を実行します。 TensorFlow Transform は、モデルの TensorFlow グラフに変換を構築するため、トレーニング時と推論時に同じ変換が実行されます。すべてのトレーニング インスタンスにわたる特徴の最大値など、データのグローバル プロパティを参照する変換を定義できます。
TFX を実行する前に、データを自由に変換できます。ただし、TensorFlow Transform 内でこれを実行すると、変換は TensorFlow グラフの一部になります。このアプローチは、トレーニング/サービスの偏りを回避するのに役立ちます。
モデリング コード内の変換では、FeatureColumn を使用します。 FeatureColumns を使用すると、バケット化、事前定義された語彙を使用した整数化、またはデータを確認せずに定義できるその他の変換を定義できます。
対照的に、TensorFlow Transform は、事前に不明な値を計算するためにデータのフル パスを必要とする変換用に設計されています。たとえば、語彙の生成にはデータの完全なパスが必要です。
Apache Beam を使用して値を計算することに加えて、TensorFlow Transform を使用すると、ユーザーはこれらの値を TensorFlow グラフに埋め込むことができ、トレーニング グラフにロードできます。たとえば、特徴を正規化する場合、 tft.scale_to_z_score
関数は特徴の平均と標準偏差を計算し、平均を減算して標準偏差で割る関数の TensorFlow グラフでの表現も計算します。 TensorFlow Transform は、統計だけでなく TensorFlow グラフを出力することにより、前処理パイプラインの作成プロセスを簡素化します。
前処理はグラフとして表現されるため、サーバー上で実行でき、トレーニングとサービスの間で一貫性が保証されます。この一貫性により、トレーニング/サービスの偏りの原因の 1 つが排除されます。
TensorFlow Transform を使用すると、ユーザーは TensorFlow コードを使用して前処理パイプラインを指定できます。これは、パイプラインが TensorFlow グラフと同じ方法で構築されることを意味します。このグラフで TensorFlow 演算のみが使用されている場合、パイプラインは入力のバッチを受け入れ、出力のバッチを返す純粋なマップになります。このようなパイプラインは、 tf.Estimator
API を使用するときにこのグラフをinput_fn
内に配置することと同じになります。分位数の計算などのフルパス操作を指定するために、TensorFlow Transform は、TensorFlow 操作のように見えるanalyzers
と呼ばれる特別な関数を提供しますが、実際には Apache Beam によって実行される遅延計算を指定し、出力はグラフに挿入されます。絶え間ない。通常の TensorFlow 演算は単一のバッチを入力として受け取り、そのバッチのみで何らかの計算を実行してバッチを出力しますが、 analyzer
すべてのバッチに対してグローバル リダクション (Apache Beam で実装) を実行し、結果を返します。
通常の TensorFlow 演算と TensorFlow Transform アナライザーを組み合わせることで、ユーザーは複雑なパイプラインを作成してデータを前処理できます。たとえば、 tft.scale_to_z_score
関数は入力テンソルを受け取り、平均0
と分散1
を持つように正規化されたテンソルを返します。これは、内部でmean
アナライザーとvar
アナライザーを呼び出すことによって行われ、入力テンソルの平均と分散に等しい定数をグラフ内に効果的に生成します。次に、TensorFlow 演算を使用して平均を減算し、標準偏差で除算します。
TensorFlow Transform preprocessing_fn
TFX Transform コンポーネントは、データの読み取りと書き込みに関連する API 呼び出しを処理し、出力 SavedModel をディスクに書き込むことにより、Transform の使用を簡素化します。 TFX ユーザーは、 preprocessing_fn
と呼ばれる単一関数を定義するだけで済みます。 preprocessing_fn
では、テンソルの入力 dict を操作して tensor の出力 dict を生成する一連の関数を定義します。 TensorFlow Transform API のscale_to_0_1 や compute_and_apply_vocabulary などのヘルパー関数を見つけることも、以下に示すように通常の TensorFlow 関数を使用することもできます。
def preprocessing_fn(inputs):
"""tf.transform's callback function for preprocessing inputs.
Args:
inputs: map from feature keys to raw not-yet-transformed features.
Returns:
Map from string feature key to transformed feature operations.
"""
outputs = {}
for key in _DENSE_FLOAT_FEATURE_KEYS:
# If sparse make it dense, setting nan's to 0 or '', and apply zscore.
outputs[_transformed_name(key)] = transform.scale_to_z_score(
_fill_in_missing(inputs[key]))
for key in _VOCAB_FEATURE_KEYS:
# Build a vocabulary for this feature.
outputs[_transformed_name(
key)] = transform.compute_and_apply_vocabulary(
_fill_in_missing(inputs[key]),
top_k=_VOCAB_SIZE,
num_oov_buckets=_OOV_SIZE)
for key in _BUCKET_FEATURE_KEYS:
outputs[_transformed_name(key)] = transform.bucketize(
_fill_in_missing(inputs[key]), _FEATURE_BUCKET_COUNT)
for key in _CATEGORICAL_FEATURE_KEYS:
outputs[_transformed_name(key)] = _fill_in_missing(inputs[key])
# Was this passenger a big tipper?
taxi_fare = _fill_in_missing(inputs[_FARE_KEY])
tips = _fill_in_missing(inputs[_LABEL_KEY])
outputs[_transformed_name(_LABEL_KEY)] = tf.where(
tf.is_nan(taxi_fare),
tf.cast(tf.zeros_like(taxi_fare), tf.int64),
# Test if the tip was > 20% of the fare.
tf.cast(
tf.greater(tips, tf.multiply(taxi_fare, tf.constant(0.2))), tf.int64))
return outputs
preprocessing_fn への入力を理解する
preprocessing_fn
は、テンソル (つまり、 Tensor
、 SparseTensor
、またはRaggedTensor
) に対する一連の操作を記述します。 preprocessing_fn
正しく定義するには、データがテンソルとしてどのように表現されるかを理解する必要があります。 preprocessing_fn
への入力はスキーマによって決まります。 Schema
プロトは最終的に、データ解析に使用される「機能仕様」 (「解析仕様」と呼ばれることもあります) に変換されます。変換ロジックの詳細については、こちらを参照してください。
TensorFlow Transform を使用して文字列ラベルを処理する
通常、TensorFlow Transform を使用して語彙を生成し、その語彙を適用して文字列を整数に変換したいと考えます。このワークフローに従うと、モデル内に構築されたinput_fn
整数化された文字列を出力します。ただし、ラベルは例外です。モデルが出力 (整数) ラベルを文字列にマッピングできるようにするには、文字列ラベルとラベルの可能な値のリストを出力するためのinput_fn
必要です。たとえば、ラベルがcat
とdog
場合、 input_fn
の出力はこれらの生の文字列である必要があり、キー["cat", "dog"]
パラメーターとして推定器に渡す必要があります (詳細は以下を参照)。
文字列ラベルの整数へのマッピングを処理するには、TensorFlow Transform を使用して語彙を生成する必要があります。以下のコード スニペットでこれを示します。
def _preprocessing_fn(inputs):
"""Preprocess input features into transformed features."""
...
education = inputs[features.RAW_LABEL_KEY]
_ = tft.vocabulary(education, vocab_filename=features.RAW_LABEL_KEY)
...
上記の前処理関数は、生の入力フィーチャ (これも前処理関数の出力の一部として返されます) を受け取り、それに対してtft.vocabulary
を呼び出します。これにより、モデル内でアクセスできるeducation
用の語彙が生成されます。
この例では、ラベルを変換し、変換されたラベルの語彙を生成する方法も示します。特に、生のラベルeducation
取得し、ラベルを整数に変換せずに、(頻度による) 上位 5 つのラベルを除くすべてのラベルをUNKNOWN
に変換します。
モデル コードでは、分類子にtft.vocabulary
によって生成された語彙をlabel_vocabulary
引数として指定する必要があります。これは、まずこの語彙をヘルパー関数を使用してリストとして読み取ることによって行われます。これを以下のスニペットに示します。コード例では上で説明した変換されたラベルが使用されていますが、ここでは生のラベルを使用するコードを示します。
def create_estimator(pipeline_inputs, hparams):
...
tf_transform_output = trainer_util.TFTransformOutput(
pipeline_inputs.transform_dir)
# vocabulary_by_name() returns a Python list.
label_vocabulary = tf_transform_output.vocabulary_by_name(
features.RAW_LABEL_KEY)
return tf.contrib.learn.DNNLinearCombinedClassifier(
...
n_classes=len(label_vocab),
label_vocabulary=label_vocab,
...)
変換前および変換後の統計の構成
前述したように、Transform コンポーネントは TFDV を呼び出して、変換前と変換後の両方の統計を計算します。 TFDV は、オプションのStatsOptionsオブジェクトを入力として受け取ります。ユーザーは、このオブジェクトを構成して、特定の追加統計 (NLP 統計など) を有効にしたり、検証されるしきい値 (最小/最大トークン頻度など) を設定したりすることができます。これを行うには、モジュール ファイルでstats_options_updater_fn
を定義します。
def stats_options_updater_fn(stats_type, stats_options):
...
if stats_type == stats_options_util.StatsType.PRE_TRANSFORM:
# Update stats_options to modify pre-transform statistics computation.
# Most constraints are specified in the schema which can be accessed
# via stats_options.schema.
if stats_type == stats_options_util.StatsType.POST_TRANSFORM
# Update stats_options to modify post-transform statistics computation.
# Most constraints are specified in the schema which can be accessed
# via stats_options.schema.
return stats_options
変換後の統計には、特徴の前処理に使用される語彙の知識が役立つことがよくあります。語彙名とパスのマッピングは、TFT で生成されたすべての語彙の StatsOptions (したがって TFDV) に提供されます。さらに、外部で作成された語彙のマッピングは、(i) StatsOptions 内でvocab_paths
辞書を直接変更するか、(ii) tft.annotate_asset
を使用することによって追加できます。