Dołącz do społeczności SIG TFX-Addons i pomóż ulepszyć TFX!
Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Lepsza inżynieria ML dzięki metadanym ML

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło w serwisie GitHub

Załóżmy scenariusz, w którym konfigurujesz produkcyjny potok ML do klasyfikowania pingwinów. Potok pobiera dane szkoleniowe, szkoli i ocenia model, a następnie wypycha go do produkcji.

Jednak gdy później spróbujesz użyć tego modelu z większym zbiorem danych zawierającym różne rodzaje pingwinów, zauważysz, że model nie zachowuje się zgodnie z oczekiwaniami i zaczyna niepoprawnie klasyfikować gatunki.

W tym momencie chcesz wiedzieć:

  • Jaki jest najbardziej efektywny sposób debugowania modelu, gdy jedynym dostępnym artefaktem jest model w produkcji?
  • Który zestaw danych szkoleniowych został użyty do trenowania modelu?
  • Który bieg treningowy doprowadził do tego błędnego modelu?
  • Gdzie są wyniki oceny modelu?
  • Od czego zacząć debugowanie?

ML Metadata (MLMD) to biblioteka, która wykorzystuje metadane powiązane z modelami ML, aby pomóc Ci odpowiedzieć na te pytania i nie tylko. Pomocną analogią jest myślenie o tych metadanych jako o ekwiwalencie logowania w rozwoju oprogramowania. MLMD umożliwia niezawodne śledzenie artefaktów i pochodzenia związanego z różnymi składnikami potoku ML.

W tym samouczku skonfigurujesz potok TFX, aby utworzyć model klasyfikujący pingwiny na trzy gatunki na podstawie masy ciała oraz długości i głębokości ich źdźbeł oraz długości płetw. Następnie za pomocą MLMD można śledzić pochodzenie komponentów rurociągu.

Rurociągi TFX w Colab

Colab to lekkie środowisko programistyczne, które znacznie różni się od środowiska produkcyjnego. W środowisku produkcyjnym możesz mieć różne składniki potoku, takie jak pozyskiwanie danych, transformacja, szkolenie modeli, historie uruchamiania itp. W wielu rozproszonych systemach. W tym samouczku należy pamiętać, że istnieją znaczące różnice w aranżacji i przechowywaniu metadanych - wszystko jest obsługiwane lokalnie w Colab. Dowiedz się więcej o TFX w Colab tutaj .

Ustawiać

Najpierw instalujemy i importujemy niezbędne pakiety, konfigurujemy ścieżki i pobieramy dane.

Upgrade Pip

Aby uniknąć aktualizacji Pipa w systemie podczas pracy lokalnie, upewnij się, że działamy w Colab. Systemy lokalne można oczywiście aktualizować oddzielnie.

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

Zainstaluj i zaimportuj TFX

pip install -q -U --use-feature=2020-resolver tfx

Po zainstalowaniu TFX należy ponownie uruchomić środowisko wykonawcze Colab. Wybierz opcję Runtime> Restart runtime z menu Colab. Wynika to ze sposobu, w jaki Colab ładuje paczki.

Nie kontynuuj dalszej części tego samouczka bez uprzedniego ponownego uruchomienia środowiska wykonawczego.

Importuj inne biblioteki

import os
import tempfile
import urllib
import pandas as pd

Importuj klasy komponentów TFX .

from tfx.components.evaluator.component import Evaluator
from tfx.components.example_gen.csv_example_gen.component import CsvExampleGen
from tfx.components.pusher.component import Pusher
from tfx.components.schema_gen.component import SchemaGen
from tfx.components.statistics_gen.component import StatisticsGen
from tfx.components.trainer.component import Trainer
from tfx.components.base import executor_spec
from tfx.components.trainer.executor import GenericExecutor
from tfx.orchestration.experimental.interactive.interactive_context import InteractiveContext
from tfx.proto import evaluator_pb2
from tfx.proto import pusher_pb2
from tfx.proto import trainer_pb2
from tfx.utils.dsl_utils import external_input

from tensorflow_metadata.proto.v0 import anomalies_pb2
from tensorflow_metadata.proto.v0 import schema_pb2
from tensorflow_metadata.proto.v0 import statistics_pb2

import tensorflow_model_analysis as tfma

from tfx.components import ResolverNode
from tfx.dsl.experimental import latest_blessed_model_resolver
from tfx.types import Channel
from tfx.types.standard_artifacts import Model
from tfx.types.standard_artifacts import ModelBlessing

Zaimportuj bibliotekę MLMD.

import ml_metadata as mlmd
from ml_metadata.proto import metadata_store_pb2

Pobierz zestaw danych

W tej kolumnie używamy zestawu danych Palmer Penguins, który można znaleźć na Github . Przetworzyliśmy zbiór danych, pomijając niekompletne rekordy, int32 kolumny island i sex oraz przekonwertowaliśmy etykiety na int32 . Zbiór danych zawiera 334 zapisy dotyczące masy ciała oraz długości i głębokości źdźbeł pingwinów oraz długości ich płetw. Używasz tych danych do klasyfikowania pingwinów do jednego z trzech gatunków.

DATA_PATH = 'https://raw.githubusercontent.com/tensorflow/tfx/master/tfx/examples/penguin/data/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-datap7jk35hz/penguins_processed.csv',
 <http.client.HTTPMessage at 0x7fe4eef4c160>)

Utwórz InteractiveContext

Aby interaktywnie uruchamiać składniki TFX w tym notatniku, utwórz InteractiveContext . InteractiveContext używa katalogu tymczasowego z tymczasową instancją bazy danych MLMD. Zauważ, że wywołania InteractiveContext nie działają poza środowiskiem Colab.

Ogólnie rzecz biorąc, dobrą praktyką jest grupowanie podobnych przebiegów potoku w ramach Context .

interactive_context = InteractiveContext()
WARNING:absl:InteractiveContext pipeline_root argument not provided: using temporary directory /tmp/tfx-interactive-2021-02-11T13_16_43.521464-6hj93f0i as root for pipeline outputs.
WARNING:absl:InteractiveContext metadata_connection_config not provided: using SQLite ML Metadata database at /tmp/tfx-interactive-2021-02-11T13_16_43.521464-6hj93f0i/metadata.sqlite.

Skonstruuj potok TFX

Potok TFX składa się z kilku składników, które wykonują różne aspekty przepływu pracy ML. W tym notatniku utworzysz i uruchomisz składniki ExampleGen , StatisticsGen , SchemaGen i Trainer oraz używasz składników Evaluator and Pusher , aby ocenić i wypchnąć wyuczony model.

Więcej informacji na temat składników potoku TFX można znaleźć w samouczku dotyczącym składników.

Utwórz wystąpienie i uruchom składnik ExampleGen

input_data = external_input(_data_root)
example_gen = CsvExampleGen(input=input_data)
interactive_context.run(example_gen)
WARNING:absl:From <ipython-input-1-e4ef519b0b92>:1: external_input (from tfx.utils.dsl_utils) is deprecated and will be removed in a future version.
Instructions for updating:
external_input is deprecated, directly pass the uri to ExampleGen.
WARNING:absl:The "input" argument to the CsvExampleGen component has been deprecated by "input_base". Please update your usage as support for this argument will be removed soon.
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:apache_beam.io.tfrecordio:Couldn't find python-snappy so the implementation of _TFRecordUtil._masked_crc32c is not as fast as it could be.

Utwórz wystąpienie i uruchom składnik StatisticsGen

statistics_gen = StatisticsGen(examples=example_gen.outputs['examples'])
interactive_context.run(statistics_gen)

Utwórz wystąpienie i uruchom składnik SchemaGen

infer_schema = SchemaGen(
    statistics=statistics_gen.outputs['statistics'], infer_feature_shape=True)
interactive_context.run(infer_schema)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_data_validation/utils/stats_util.py:247: 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.6/site-packages/tensorflow_data_validation/utils/stats_util.py:247: 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)`

Utwórz instancję i uruchom komponent Trainer

# 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.components.trainer.executor import TrainerFnArgs
from tfx.components.trainer.fn_args_utils import FnArgs

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

_FEATURES = {
    'culmen_length_mm': tf.io.FixedLenFeature([], dtype=tf.float32),
    'culmen_depth_mm': tf.io.FixedLenFeature([], dtype=tf.float32),
    'flipper_length_mm': tf.io.FixedLenFeature([], dtype=tf.float32),
    'body_mass_g': tf.io.FixedLenFeature([], dtype=tf.float32),
    'species': tf.io.FixedLenFeature([], dtype=tf.int64)
}

_LABEL_KEY = 'species'

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


def _gzip_reader_fn(filenames):
  return tf.data.TFRecordDataset(filenames, compression_type='GZIP')


def _input_fn(file_pattern: List[Text], batch_size: int = 200):
  dataset = tf.data.experimental.make_batched_features_dataset(
      file_pattern=file_pattern,
      batch_size=batch_size,
      features=_FEATURES,
      reader=_gzip_reader_fn,
      label_key=_LABEL_KEY)

  return dataset


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, activation='softmax')(d)
  model = keras.Model(inputs=inputs, outputs=outputs)
  model.compile(
      optimizer='adam',
      loss='sparse_categorical_crossentropy',
      metrics=[keras.metrics.SparseCategoricalAccuracy()])
  return model


def run_fn(fn_args: TrainerFnArgs):
  train_dataset = _input_fn(fn_args.train_files, batch_size=10)
  eval_dataset = _input_fn(fn_args.eval_files, 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

Uruchom komponent Trainer .

trainer = Trainer(
    module_file=os.path.abspath(trainer_module_file),
    custom_executor_spec=executor_spec.ExecutorClassSpec(GenericExecutor),
    examples=example_gen.outputs['examples'],
    schema=infer_schema.outputs['schema'],
    train_args=trainer_pb2.TrainArgs(num_steps=100),
    eval_args=trainer_pb2.EvalArgs(num_steps=50))
interactive_context.run(trainer)
WARNING:absl:From <ipython-input-1-d2af3312f9a2>:3: The name tfx.components.base.executor_spec.ExecutorClassSpec is deprecated. Please use tfx.dsl.components.base.executor_spec.ExecutorClassSpec instead.
Epoch 1/5
20/20 [==============================] - 1s 33ms/step - loss: 1.0484 - sparse_categorical_accuracy: 0.4277 - val_loss: 1.0130 - val_sparse_categorical_accuracy: 0.4700
Epoch 2/5
20/20 [==============================] - 0s 8ms/step - loss: 1.0075 - sparse_categorical_accuracy: 0.4838 - val_loss: 0.9657 - val_sparse_categorical_accuracy: 0.6900
Epoch 3/5
20/20 [==============================] - 0s 8ms/step - loss: 0.9473 - sparse_categorical_accuracy: 0.7441 - val_loss: 0.9347 - val_sparse_categorical_accuracy: 0.7700
Epoch 4/5
20/20 [==============================] - 0s 8ms/step - loss: 0.8869 - sparse_categorical_accuracy: 0.8405 - val_loss: 0.9047 - val_sparse_categorical_accuracy: 0.7700
Epoch 5/5
20/20 [==============================] - 0s 8ms/step - loss: 0.8597 - sparse_categorical_accuracy: 0.8060 - val_loss: 0.8736 - val_sparse_categorical_accuracy: 0.7700
INFO:tensorflow:Assets written to: /tmp/tfx-interactive-2021-02-11T13_16_43.521464-6hj93f0i/Trainer/model/4/serving_model_dir/assets
INFO:tensorflow:Assets written to: /tmp/tfx-interactive-2021-02-11T13_16_43.521464-6hj93f0i/Trainer/model/4/serving_model_dir/assets

Oceń i wypchnij model

Użyj komponentu Evaluator , aby ocenić i „pobłogosławić” model przed użyciem komponentu Pusher do przekazania modelu do katalogu udostępniania.

_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 = Evaluator(
    examples=example_gen.outputs['examples'],
    model=trainer.outputs['model'],
    schema=infer_schema.outputs['schema'],
    eval_config=eval_config)
interactive_context.run(evaluator)
pusher = Pusher(
    model=trainer.outputs['model'],
    model_blessing=evaluator.outputs['blessing'],
    push_destination=pusher_pb2.PushDestination(
        filesystem=pusher_pb2.PushDestination.Filesystem(
            base_directory=_serving_model_dir)))
interactive_context.run(pusher)

Uruchomienie potoku TFX wypełnia bazę danych MLMD. W następnej sekcji użyjesz interfejsu API MLMD do wysłania zapytania do tej bazy danych w celu uzyskania informacji o metadanych.

Zapytanie do bazy danych MLMD

Baza danych MLMD przechowuje trzy typy metadanych:

  • Metadane dotyczące rurociągu i informacji o rodowodzie skojarzonych z komponentami rurociągu
  • Metadane dotyczące artefaktów, które zostały wygenerowane podczas działania potoku
  • Metadane dotyczące wykonania potoku

Typowy potok środowiska produkcyjnego obsługuje wiele modeli w miarę napływania nowych danych. Gdy napotkasz błędne wyniki w obsługiwanych modelach, możesz wysłać zapytanie do bazy danych MLMD, aby wyodrębnić błędne modele. Następnie można prześledzić pochodzenie składników potoku, które odpowiadają tym modelom, aby debugować modele

Skonfiguruj magazyn metadanych (MD) z wcześniej zdefiniowanym InteractiveContext aby wykonać zapytanie w bazie danych 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]

Utwórz kilka funkcji pomocniczych, aby wyświetlić dane z magazynu 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)

Najpierw wyślij zapytanie do magazynu MD w celu uzyskania listy wszystkich przechowywanych ArtifactTypes .

display_types(store.get_artifact_types())

Następnie PushedModel zapytanie dotyczące wszystkich artefaktów PushedModel .

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

Zapytaj sklep MD o najnowszy wypchnięty model. Ten samouczek zawiera tylko jeden przekazany model.

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

Jednym z pierwszych kroków w debugowaniu wypchniętego modelu jest sprawdzenie, który wytrenowany model jest wypychany i które dane szkoleniowe są używane do trenowania tego modelu.

MLMD udostępnia interfejsy API przechodzenia przez wykres pochodzenia, którego można użyć do analizy pochodzenia modelu.

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 == metadata_store_pb2.Event.OUTPUT)
  artifacts_ids = set(
      event.artifact_id
      for event in store.get_events_by_execution_ids(executions_ids)
      if event.type == metadata_store_pb2.Event.INPUT) 
  return [artifact for artifact in store.get_artifacts_by_id(artifacts_ids)]

Zapytaj o artefakty nadrzędne dla wypchniętego modelu.

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

Zapytaj o właściwości modelu.

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

Zapytaj o artefakty nadrzędne dla modelu.

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

Pobierz dane szkoleniowe, z którymi trenował model.

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

Teraz, gdy masz już dane szkoleniowe, z którymi trenował model, ponownie przeprowadź zapytanie do bazy danych, aby znaleźć krok szkoleniowy (wykonanie). Zapytaj magazyn MD o listę zarejestrowanych typów wykonania.

display_types(store.get_execution_types())

tfx.components.trainer.component.Trainer szkolenia jest tfx.components.trainer.component.Trainer ExecutionType nazwie tfx.components.trainer.component.Trainer . Przejdź przez sklep MD, aby uzyskać bieg trenera, który odpowiada modelowi wypchniętemu.

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 == metadata_store_pb2.Event.OUTPUT)
  return store.get_executions_by_id(executions_ids)[0]

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

Podsumowanie

W tym samouczku dowiedziałeś się, jak wykorzystać MLMD do śledzenia pochodzenia składników potoku TFX i rozwiązywania problemów.

Aby dowiedzieć się więcej o korzystaniu z MLMD, zapoznaj się z tymi dodatkowymi zasobami: