TransformTFXパイプラインコンポーネント

Transform TFXパイプラインコンポーネントは、 SchemaGenコンポーネントによって作成されたデータスキーマを使用して、 ExampleGenコンポーネントから出力されたtf.Examplesに対して特徴エンジニアリングを実行し、SavedModelと、変換前および変換後の両方のデータに関する統計の両方を出力します。実行されると、SavedModelはExampleGenコンポーネントから出力されたtf.Examplesを受け入れ、変換されたフィーチャデータを出力します。

  • 消費:ExampleGenコンポーネントのtf.Examples、およびSchemaGenコンポーネントのデータスキーマ。
  • エミット:トレーナーコンポーネントへのSavedModel、変換前および変換後の統計。

変換コンポーネントの構成

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は、データセットに対して特徴エンジニアリングを実行するためにTensorFlowTransformを広範囲に使用します。 TensorFlow Transformは、モデルに送られる前に、トレーニングプロセスの一部として、フィーチャデータを変換するための優れたツールです。一般的な機能変換には次のものがあります。

  • 埋め込み:高次元空間から低次元空間への意味のあるマッピングを見つけることにより、まばらな特徴(語彙によって生成された整数IDなど)を密な特徴に変換します。埋め込みの概要については、機械学習クラッシュコースの埋め込みユニットをご覧ください。
  • 語彙の生成:各一意の値をID番号にマップする語彙を作成することにより、文字列またはその他の非数値の特徴を整数に変換します。
  • 値の正規化:すべてが同様の範囲内に収まるように数値特徴を変換します。
  • バケット化:個別のバケットに値を割り当てることにより、連続値の特徴をカテゴリの特徴に変換します。
  • テキスト機能の強化:トークン、n-gram、エンティティ、感情などの生データから機能を生成して、機能セットを強化します。

TensorFlow Transformは、これらおよび他の多くの種類の変換のサポートを提供します。

  • 最新のデータから語彙を自動的に生成します。

  • データをモデルに送信する前に、データに対して任意の変換を実行します。 TensorFlow Transformは、モデルのTensorFlowグラフに変換を構築するため、トレーニング時と推論時に同じ変換が実行されます。すべてのトレーニングインスタンスにわたる機能の最大値など、データのグローバルプロパティを参照する変換を定義できます。

TFXを実行する前に、データを好きなように変換できます。ただし、TensorFlowトランスフォーム内でこれを行うと、トランスフォームはTensorFlowグラフの一部になります。このアプローチは、トレーニング/サービングスキューを回避するのに役立ちます。

モデリングコード内の変換では、FeatureColumnsを使用します。 FeatureColumnsを使用すると、バケット化、事前定義された語彙を使用する整数化、またはデータを見ずに定義できるその他の変換を定義できます。

対照的に、TensorFlow Transformは、事前に不明な値を計算するためにデータを完全にパスする必要がある変換用に設計されています。たとえば、語彙の生成には、データの完全なパスが必要です。

Apache Beamを使用して値を計算することに加えて、TensorFlow Transformを使用すると、ユーザーはこれらの値をTensorFlowグラフに埋め込んで、トレーニンググラフに読み込むことができます。たとえば、特徴を正規化する場合、 tft.scale_to_z_score関数は、特徴の平均と標準偏差を計算し、TensorFlowグラフで、平均を差し引いて標準偏差で除算する関数の表現も計算します。 TensorFlow Transformは、統計だけでなくTensorFlowグラフを出力することで、前処理パイプラインのオーサリングプロセスを簡素化します。

前処理はグラフとして表されるため、サーバー上で発生する可能性があり、トレーニングとサービスの間で一貫性があることが保証されます。この一貫性により、トレーニング/サービングスキューの1つの原因が排除されます。

TensorFlow Transformを使用すると、ユーザーはTensorFlowコードを使用して前処理パイプラインを指定できます。これは、パイプラインがTensorFlowグラフと同じ方法で構築されることを意味します。このグラフでTensorFlowopsのみが使用されている場合、パイプラインは入力のバッチを受け入れ、出力のバッチを返す純粋なマップになります。このようなパイプラインは、 tf.Estimatorを使用するときにこのグラフをinput_fn内に配置することと同じです。分位数の計算などのフルパス操作を指定するために、TensorFlow Transformは、TensorFlow opsのように見えるanalyzersと呼ばれる特別な関数を提供しますが、実際には、Apache Beamによって実行される遅延計算を指定し、出力はグラフに挿入されます。絶え間ない。通常のTensorFlow操作は単一のバッチを入力として受け取り、そのバッチのみで計算を実行してバッチを出力しますが、 analyzerはすべてのバッチに対してグローバルリダクション(Apache Beamで実装)を実行し、結果を返します。

通常のTensorFlowopsとTensorFlowTransformアナライザーを組み合わせることで、ユーザーはデータを前処理するための複雑なパイプラインを作成できます。たとえば、 tft.scale_to_z_score関数は入力テンソルを受け取り、平均0と分散1を持つように正規化されたテンソルを返します。これは、内部でmeanアナライザーと変数varを呼び出すことによって行われます。これにより、入力テンソルの平均と分散に等しい定数がグラフに効果的に生成されます。次に、TensorFlow opsを使用して平均を減算し、標準偏差で除算します。

TensorFlow変換preprocessing_fn

TFX Transformコンポーネントは、データの読み取りと書き込みに関連するAPI呼び出しを処理し、出力SavedModelをディスクに書き込むことにより、Transformの使用を簡素化します。 TFXユーザーは、 preprocessing_fnと呼ばれる単一の関数を定義するだけで済みます。 preprocessing_fnで、テンソルの入力dictを操作してテンソルの出力dictを生成する一連の関数を定義します。以下に示すように、scale_to_0_1やcompute_and_apply_vocabulary TensorFlow Transform APIなどのヘルパー関数を見つけるか、通常の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 )に対する一連の操作を記述します。したがって、 preprocessing_fnを正しく書き込むには、データがテンソルとしてどのように表されるかを理解する必要があります。 preprocessing_fnへの入力は、スキーマによって決定されます。 SchemaプロトにはFeatureのリストが含まれており、Transformはこれらを「機能仕様」(「解析仕様」と呼ばれることもあります)に変換します。これは、キーが機能名であり、値がFixedLenFeatureまたはVarLenFeature (またはその他TensorFlow Transformで使用されないオプション)。

Schemaから機能仕様を推測するためのルールは次のとおりです。

  • shapeが設定された各featureは、形状とdefault_value=Nonetf.FixedLenFeatureになります。それ以外の場合、 presence.min_fraction1である必要があり、デフォルト値がない場合、 tf.FixedLenFeatureは機能が常に存在する必要があるため、エラーが発生します。
  • shapeが設定されていない各featureは、 VarLenFeatureになります。
  • sparse_featureは、 sizetf.SparseFeatureSparseFeatureメッセージのfixed_shapeフィールドとis_sortedフィールドによって決定されるis_sortedになります。
  • sparse_featureindex_featureまたはvalue_featureとして使用される機能には、機能仕様で生成された独自のエントリはありません。
  • featuretypeフィールド(またはsparse_featureプロトの値機能)と機能仕様のdtypeの間の対応は、次の表に示されています。
type dtype
schema_pb2.INT tf.int64
schema_pb2.FLOAT tf.float32
schema_pb2.BYTES tf.string

TensorFlowTransformを使用して文字列ラベルを処理する

通常、TensorFlow Transformを使用して語彙を生成し、その語彙を適用して文字列を整数に変換する必要があります。このワークフローに従うと、モデルで構築されたinput_fnは整数化された文字列を出力します。ただし、ラベルは例外です。モデルが出力(整数)ラベルを文字列にマップできるようにするために、モデルは、ラベルの可能な値のリストとともに文字列ラベルを出力するためにinput_fnを必要とします。たとえば、ラベルがcatdogの場合、 input_fnの出力はこれらの生の文字列である必要があり、キー["cat", "dog"]をパラメーターとして推定器に渡す必要があります(以下の詳細を参照)。

文字列ラベルの整数へのマッピングを処理するには、TensorFlowTransformを使用して語彙を生成する必要があります。これを以下のコードスニペットで示します。

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,
      ...)

変換前および変換後の統計の構成

上記のように、変換コンポーネントは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を使用して追加できます。