SIG TFX-Addonsコミュニティに参加して、TFXをさらに改善するのを手伝ってください! SIGTFXに参加-アドオン

MLメタデータによる優れたMLエンジニアリング

TensorFlow.orgで表示 GoogleColabで実行 GitHubでソースを表示ノートブックをダウンロード

ペンギンを分類するために本番MLパイプラインを設定するシナリオを想定します。パイプラインはトレーニングデータを取り込み、モデルをトレーニングして評価し、本番環境にプッシュします。

ただし、後でさまざまな種類のペンギンを含むより大きなデータセットでこのモデルを使用しようとすると、モデルが期待どおりに動作せず、種の分類が正しく開始されないことがわかります。

この時点で、あなたは知ることに興味があります:

  • 利用可能なアーティファクトが本番環境のモデルのみである場合、モデルをデバッグするための最も効率的な方法は何ですか?
  • モデルのトレーニングに使用されたトレーニングデータセットはどれですか?
  • どのトレーニング実行がこの誤ったモデルにつながったのですか?
  • モデルの評価結果はどこにありますか?
  • どこからデバッグを開始しますか?

MLメタデータ(MLMDは)あなたは、よりこれらの質問に答えるためにMLモデルに関連するメタデータを活用するライブラリです。有用な例えは、このメタデータをソフトウェア開発へのログインと同等であると考えることです。 MLMDを使用すると、MLパイプラインのさまざまなコンポーネントに関連するアーティファクトと系統を確実に追跡できます。

このチュートリアルでは、TFXパイプラインを設定して、ペンギンを体重、カルメンの長さと深さ、足ひれの長さに基づいて3つの種に分類するモデルを作成します。次に、MLMDを使用して、パイプラインコンポーネントの系統を追跡します。

ColabのTFXパイプライン

Colabは、本番環境とは大きく異なる軽量の開発環境です。本番環境では、データの取り込み、変換、モデルトレーニング、実行履歴など、複数の分散システムにまたがるさまざまなパイプラインコンポーネントが存在する場合があります。このチュートリアルでは、オーケストレーションとメタデータストレージに大きな違いがあることに注意してください。これらはすべてColab内でローカルに処理されます。コラボでTFX詳細については、こちらをご覧くださいここに

設定

まず、必要なパッケージをインストールしてインポートし、パスを設定して、データをダウンロードします。

アップグレードピップ

ローカルで実行しているときにシステムでPipをアップグレードしないようにするには、Colabで実行していることを確認してください。もちろん、ローカルシステムは個別にアップグレードできます。

try:
  import colab
  !pip install --upgrade pip
except:
  pass

TFXをインストールしてインポートする

pip install -q -U tfx

パッケージをインポートする

ランタイムを再起動しましたか?

上記のセルを初めて実行するときにGoogleColabを使用している場合は、[ランタイムの再起動]ボタンをクリックするか、[ランタイム]> [ランタイムの再起動...]メニューを使用してランタイムを再起動する必要があります。これは、Colabがパッケージをロードする方法が原因です。

import os
import tempfile
import urllib
import pandas as pd

import tensorflow_model_analysis as tfma
from tfx.orchestration.experimental.interactive.interactive_context import InteractiveContext
2021-07-24 09:25:58.004364: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0

TFXとMLMDのバージョンを確認してください。

from tfx import v1 as tfx
print('TFX version: {}'.format(tfx.__version__))
import ml_metadata as mlmd
print('MLMD version: {}'.format(mlmd.__version__))
TFX version: 1.0.0
MLMD version: 1.0.0

データセットをダウンロードする

このコラボでは、我々は、使用パーマーペンギンのデータセットで見つけることができるのGithubを。私たちは、不完全なレコードを残してデータセットを処理し、かつ低下islandsex列を、とにラベルを変換int32 。データセットには、ペンギンのカルメンの体重と長さおよび深さ、およびフリッパーの長さの334レコードが含まれています。このデータを使用して、ペンギンを3つの種のいずれかに分類します。

DATA_PATH = 'https://raw.githubusercontent.com/tensorflow/tfx/master/tfx/examples/penguin/data/labelled/penguins_processed.csv'
_data_root = tempfile.mkdtemp(prefix='tfx-data')
_data_filepath = os.path.join(_data_root, "penguins_processed.csv")
urllib.request.urlretrieve(DATA_PATH, _data_filepath)
('/tmp/tfx-dataduqrz_en/penguins_processed.csv',
 <http.client.HTTPMessage at 0x7fba1ebc0e10>)

InteractiveContextを作成する

このノートブックにインタラクティブにTFXコンポーネントを実行するには、作成InteractiveContextInteractiveContext短命MLMDデータベースインスタンスで一時ディレクトリを使用しています。注への呼び出しことInteractiveContextコラボの環境以外では-OPSはありません。

一般的には、下のグループと同様のパイプラインを実行することをお勧めしContext

interactive_context = InteractiveContext()
WARNING:absl:InteractiveContext pipeline_root argument not provided: using temporary directory /tmp/tfx-interactive-2021-07-24T09_26_00.721922-9h873pwa as root for pipeline outputs.
WARNING:absl:InteractiveContext metadata_connection_config not provided: using SQLite ML Metadata database at /tmp/tfx-interactive-2021-07-24T09_26_00.721922-9h873pwa/metadata.sqlite.

TFXパイプラインを構築する

TFXパイプラインは、MLワークフローのさまざまな側面を実行するいくつかのコンポーネントで構成されています。このノートブックでは、作成して実行ExampleGenStatisticsGenSchemaGen 、およびTrainerコンポーネントを使用し、 EvaluatorPusher評価し、訓練されたモデルをプッシュするコンポーネントを。

参照してくださいチュートリアルコンポーネントTFXパイプラインコンポーネントの詳細について。

ExampleGenコンポーネントをインスタンス化して実行します

example_gen = tfx.components.CsvExampleGen(input_base=_data_root)
interactive_context.run(example_gen)
WARNING:apache_beam.runners.interactive.interactive_environment:Dependencies required for Interactive Beam PCollection visualization are not available, please use: `pip install apache-beam[interactive]` to install necessary dependencies to enable all data visualization features.
WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.
WARNING:apache_beam.io.tfrecordio:Couldn't find python-snappy so the implementation of _TFRecordUtil._masked_crc32c is not as fast as it could be.

StatisticsGenコンポーネントをインスタンス化して実行します

statistics_gen = tfx.components.StatisticsGen(
    examples=example_gen.outputs['examples'])
interactive_context.run(statistics_gen)
WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.

SchemaGenコンポーネントをインスタンス化して実行します

infer_schema = tfx.components.SchemaGen(
    statistics=statistics_gen.outputs['statistics'], infer_feature_shape=True)
interactive_context.run(infer_schema)
2021-07-24 09:26:04.200547: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type

トレーナーコンポーネントをインスタンス化して実行します

# Define the module file for the Trainer component
trainer_module_file = 'penguin_trainer.py'
%%writefile {trainer_module_file}

# Define the training algorithm for the Trainer module file
import os
from typing import List, Text

import tensorflow as tf
from tensorflow import keras

from tfx import v1 as tfx
from tfx_bsl.public import tfxio

from tensorflow_metadata.proto.v0 import schema_pb2

# Features used for classification - culmen length and depth, flipper length,
# body mass, and species.

_LABEL_KEY = 'species'

_FEATURE_KEYS = [
    'culmen_length_mm', 'culmen_depth_mm', 'flipper_length_mm', 'body_mass_g'
]


def _input_fn(file_pattern: List[Text],
              data_accessor: tfx.components.DataAccessor,
              schema: schema_pb2.Schema, batch_size: int) -> tf.data.Dataset:
  return data_accessor.tf_dataset_factory(
      file_pattern,
      tfxio.TensorFlowDatasetOptions(
          batch_size=batch_size, label_key=_LABEL_KEY), schema).repeat()


def _build_keras_model():
  inputs = [keras.layers.Input(shape=(1,), name=f) for f in _FEATURE_KEYS]
  d = keras.layers.concatenate(inputs)
  d = keras.layers.Dense(8, activation='relu')(d)
  d = keras.layers.Dense(8, activation='relu')(d)
  outputs = keras.layers.Dense(3)(d)
  model = keras.Model(inputs=inputs, outputs=outputs)
  model.compile(
      optimizer=keras.optimizers.Adam(1e-2),
      loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
      metrics=[keras.metrics.SparseCategoricalAccuracy()])
  return model


def run_fn(fn_args: tfx.components.FnArgs):
  schema = schema_pb2.Schema()
  tfx.utils.parse_pbtxt_file(fn_args.schema_path, schema)
  train_dataset = _input_fn(
      fn_args.train_files, fn_args.data_accessor, schema, batch_size=10)
  eval_dataset = _input_fn(
      fn_args.eval_files, fn_args.data_accessor, schema, batch_size=10)
  model = _build_keras_model()
  model.fit(
      train_dataset,
      epochs=int(fn_args.train_steps / 20),
      steps_per_epoch=20,
      validation_data=eval_dataset,
      validation_steps=fn_args.eval_steps)
  model.save(fn_args.serving_model_dir, save_format='tf')
Writing penguin_trainer.py

実行Trainerコンポーネントを。

trainer = tfx.components.Trainer(
    module_file=os.path.abspath(trainer_module_file),
    examples=example_gen.outputs['examples'],
    schema=infer_schema.outputs['schema'],
    train_args=tfx.proto.TrainArgs(num_steps=100),
    eval_args=tfx.proto.EvalArgs(num_steps=50))
interactive_context.run(trainer)
running bdist_wheel
running build
running build_py
creating build
creating build/lib
copying penguin_trainer.py -> build/lib
installing to /tmp/tmpox9a4duz
running install
running install_lib
copying build/lib/penguin_trainer.py -> /tmp/tmpox9a4duz
running install_egg_info
running egg_info
creating tfx_user_code_Trainer.egg-info
writing tfx_user_code_Trainer.egg-info/PKG-INFO
writing dependency_links to tfx_user_code_Trainer.egg-info/dependency_links.txt
writing top-level names to tfx_user_code_Trainer.egg-info/top_level.txt
writing manifest file 'tfx_user_code_Trainer.egg-info/SOURCES.txt'
reading manifest file 'tfx_user_code_Trainer.egg-info/SOURCES.txt'
writing manifest file 'tfx_user_code_Trainer.egg-info/SOURCES.txt'
Copying tfx_user_code_Trainer.egg-info to /tmp/tmpox9a4duz/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4-py3.7.egg-info
running install_scripts
creating /tmp/tmpox9a4duz/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/WHEEL
creating '/tmp/tmpg1jzunkf/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4-py3-none-any.whl' and adding '/tmp/tmpox9a4duz' to it
adding 'penguin_trainer.py'
adding 'tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/METADATA'
adding 'tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/WHEEL'
adding 'tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/top_level.txt'
adding 'tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/RECORD'
removing /tmp/tmpox9a4duz
2021-07-24 09:26:04.716013: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type
2021-07-24 09:26:04.719884: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type
Processing /tmp/tfx-interactive-2021-07-24T09_26_00.721922-9h873pwa/_wheels/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4-py3-none-any.whl
Installing collected packages: tfx-user-code-Trainer
Successfully installed tfx-user-code-Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4
2021-07-24 09:26:06.256595: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcuda.so.1
2021-07-24 09:26:06.260327: E tensorflow/stream_executor/cuda/cuda_driver.cc:328] failed call to cuInit: CUDA_ERROR_SYSTEM_DRIVER_MISMATCH: system has unsupported display driver / cuda driver combination
2021-07-24 09:26:06.260361: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: kokoro-gcp-ubuntu-prod-559609198
2021-07-24 09:26:06.260368: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: kokoro-gcp-ubuntu-prod-559609198
2021-07-24 09:26:06.260480: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:200] libcuda reported version is: 470.57.2
2021-07-24 09:26:06.260502: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:204] kernel reported version is: 465.27.0
2021-07-24 09:26:06.260508: E tensorflow/stream_executor/cuda/cuda_diagnostics.cc:313] kernel version 465.27.0 does not match DSO version 470.57.2 -- cannot find working devices in this configuration
2021-07-24 09:26:06.260728: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Epoch 1/5
 1/20 [>.............................] - ETA: 6s - loss: 1.1316 - sparse_categorical_accuracy: 0.0000e+00
2021-07-24 09:26:06.711432: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
2021-07-24 09:26:06.713005: I tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2000179999 Hz
20/20 [==============================] - 1s 10ms/step - loss: 1.0774 - sparse_categorical_accuracy: 0.4050 - val_loss: 1.0396 - val_sparse_categorical_accuracy: 0.4700
Epoch 2/5
20/20 [==============================] - 0s 5ms/step - loss: 0.9500 - sparse_categorical_accuracy: 0.5350 - val_loss: 0.8672 - val_sparse_categorical_accuracy: 0.7800
Epoch 3/5
20/20 [==============================] - 0s 4ms/step - loss: 0.7380 - sparse_categorical_accuracy: 0.7700 - val_loss: 0.5768 - val_sparse_categorical_accuracy: 0.7800
Epoch 4/5
20/20 [==============================] - 0s 4ms/step - loss: 0.4604 - sparse_categorical_accuracy: 0.8100 - val_loss: 0.4236 - val_sparse_categorical_accuracy: 0.7800
Epoch 5/5
20/20 [==============================] - 0s 4ms/step - loss: 0.3520 - sparse_categorical_accuracy: 0.8150 - val_loss: 0.3400 - val_sparse_categorical_accuracy: 0.7800
2021-07-24 09:26:07.824456: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tfx-interactive-2021-07-24T09_26_00.721922-9h873pwa/Trainer/model/4/Format-Serving/assets
INFO:tensorflow:Assets written to: /tmp/tfx-interactive-2021-07-24T09_26_00.721922-9h873pwa/Trainer/model/4/Format-Serving/assets

モデルを評価してプッシュする

使用するEvaluator評価および使用する前に、モデルを「祝福」するコンポーネントをPusher提供するディレクトリにモデルをプッシュするコンポーネントを。

_serving_model_dir = os.path.join(tempfile.mkdtemp(),
                                  'serving_model/penguins_classification')
eval_config = tfma.EvalConfig(
    model_specs=[
        tfma.ModelSpec(label_key='species', signature_name='serving_default')
    ],
    metrics_specs=[
        tfma.MetricsSpec(metrics=[
            tfma.MetricConfig(
                class_name='SparseCategoricalAccuracy',
                threshold=tfma.MetricThreshold(
                    value_threshold=tfma.GenericValueThreshold(
                        lower_bound={'value': 0.6})))
        ])
    ],
    slicing_specs=[tfma.SlicingSpec()])
evaluator = tfx.components.Evaluator(
    examples=example_gen.outputs['examples'],
    model=trainer.outputs['model'],
    schema=infer_schema.outputs['schema'],
    eval_config=eval_config)
interactive_context.run(evaluator)
2021-07-24 09:26:08.397533: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type
2021-07-24 09:26:08.400911: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type
WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_model_analysis/writers/metrics_plots_and_validations_writer.py:113: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`
pusher = tfx.components.Pusher(
    model=trainer.outputs['model'],
    model_blessing=evaluator.outputs['blessing'],
    push_destination=tfx.proto.PushDestination(
        filesystem=tfx.proto.PushDestination.Filesystem(
            base_directory=_serving_model_dir)))
interactive_context.run(pusher)
2021-07-24 09:26:12.698547: W ml_metadata/metadata_store/rdbms_metadata_access_object.cc:623] No property is defined for the Type

TFXパイプラインを実行すると、MLMDデータベースにデータが入力されます。次のセクションでは、MLMD APIを使用して、このデータベースにメタデータ情報を照会します。

MLMDデータベースを照会する

MLMDデータベースには、次の3種類のメタデータが格納されています。

  • パイプラインに関するメタデータとパイプラインコンポーネントに関連付けられた系統情報
  • パイプラインの実行中に生成されたアーティファクトに関するメタデータ
  • パイプラインの実行に関するメタデータ

一般的な本番環境のパイプラインは、新しいデータが到着すると複数のモデルに対応します。提供されたモデルで誤った結果が発生した場合は、MLMDデータベースにクエリを実行して、誤ったモデルを特定できます。次に、これらのモデルに対応するパイプラインコンポーネントの系統をトレースして、モデルをデバッグできます。

メタデータ(MD)ストアの設定InteractiveContext MLMDデータベースを照会するために事前に定義されました。

connection_config = interactive_context.metadata_connection_config
store = mlmd.MetadataStore(connection_config)

# All TFX artifacts are stored in the base directory
base_dir = connection_config.sqlite.filename_uri.split('metadata.sqlite')[0]

MDストアからのデータを表示するためのいくつかのヘルパー関数を作成します。

def display_types(types):
  # Helper function to render dataframes for the artifact and execution types
  table = {'id': [], 'name': []}
  for a_type in types:
    table['id'].append(a_type.id)
    table['name'].append(a_type.name)
  return pd.DataFrame(data=table)
def display_artifacts(store, artifacts):
  # Helper function to render dataframes for the input artifacts
  table = {'artifact id': [], 'type': [], 'uri': []}
  for a in artifacts:
    table['artifact id'].append(a.id)
    artifact_type = store.get_artifact_types_by_id([a.type_id])[0]
    table['type'].append(artifact_type.name)
    table['uri'].append(a.uri.replace(base_dir, './'))
  return pd.DataFrame(data=table)
def display_properties(store, node):
  # Helper function to render dataframes for artifact and execution properties
  table = {'property': [], 'value': []}
  for k, v in node.properties.items():
    table['property'].append(k)
    table['value'].append(
        v.string_value if v.HasField('string_value') else v.int_value)
  for k, v in node.custom_properties.items():
    table['property'].append(k)
    table['value'].append(
        v.string_value if v.HasField('string_value') else v.int_value)
  return pd.DataFrame(data=table)

まず、そのすべて保存されたリストのクエリMDストアArtifactTypes

display_types(store.get_artifact_types())

次に、クエリのすべてのPushedModelアーティファクト。

pushed_models = store.get_artifacts_by_type("PushedModel")
display_artifacts(store, pushed_models)

MDストアに最新のプッシュモデルを照会します。このチュートリアルには、プッシュされたモデルが1つだけあります。

pushed_model = pushed_models[-1]
display_properties(store, pushed_model)

プッシュされたモデルをデバッグする最初のステップの1つは、どのトレーニング済みモデルがプッシュされているかを確認し、そのモデルのトレーニングにどのトレーニングデータが使用されているかを確認することです。

MLMDは、モデルの来歴を分析するために使用できる来歴グラフをウォークスルーするためのトラバーサルAPIを提供します。

def get_one_hop_parent_artifacts(store, artifacts):
  # Get a list of artifacts within a 1-hop of the artifacts of interest
  artifact_ids = [artifact.id for artifact in artifacts]
  executions_ids = set(
      event.execution_id
      for event in store.get_events_by_artifact_ids(artifact_ids)
      if event.type == mlmd.proto.Event.OUTPUT)
  artifacts_ids = set(
      event.artifact_id
      for event in store.get_events_by_execution_ids(executions_ids)
      if event.type == mlmd.proto.Event.INPUT)
  return [artifact for artifact in store.get_artifacts_by_id(artifacts_ids)]

プッシュされたモデルの親アーティファクトをクエリします。

parent_artifacts = get_one_hop_parent_artifacts(store, [pushed_model])
display_artifacts(store, parent_artifacts)

モデルのプロパティをクエリします。

exported_model = parent_artifacts[0]
display_properties(store, exported_model)

モデルのアップストリームアーティファクトをクエリします。

model_parents = get_one_hop_parent_artifacts(store, [exported_model])
display_artifacts(store, model_parents)

モデルがトレーニングされたトレーニングデータを取得します。

used_data = model_parents[0]
display_properties(store, used_data)

モデルがトレーニングしたトレーニングデータが得られたので、データベースに再度クエリを実行して、トレーニングステップ(実行)を見つけます。 MDストアに、登録されている実行タイプのリストを照会します。

display_types(store.get_execution_types())

トレーニングステップがあるExecutionTypeという名前のtfx.components.trainer.component.Trainer 。 MDストアをトラバースして、プッシュされたモデルに対応するトレーナーを実行します。

def find_producer_execution(store, artifact):
  executions_ids = set(
      event.execution_id
      for event in store.get_events_by_artifact_ids([artifact.id])
      if event.type == mlmd.proto.Event.OUTPUT)
  return store.get_executions_by_id(executions_ids)[0]

trainer = find_producer_execution(store, exported_model)
display_properties(store, trainer)

概要

このチュートリアルでは、MLMDを活用してTFXパイプラインコンポーネントの系統を追跡し、問題を解決する方法について学習しました。

MLMDの使用方法の詳細については、次の追加リソースを確認してください。