Ver no TensorFlow.org | Executar no Google Colab | Ver fonte no GitHub | Baixar caderno |
Suponha que você configure um pipeline de ML de produção para classificar os pinguins. O pipeline ingere seus dados de treinamento, treina e avalia um modelo e o envia para produção.
No entanto, quando você tenta mais tarde usar este modelo com um conjunto de dados maior que contém diferentes tipos de pinguins, você observa que seu modelo não se comporta como esperado e começa a classificar as espécies incorretamente.
Neste ponto, você está interessado em saber:
- Qual é a maneira mais eficiente de depurar o modelo quando o único artefato disponível é o modelo em produção?
- Qual conjunto de dados de treinamento foi usado para treinar o modelo?
- Qual corrida de treinamento levou a esse modelo errado?
- Onde estão os resultados da avaliação do modelo?
- Onde começar a depuração?
ML Metadados (MLMD) é uma biblioteca que aproveita os metadados associados a modelos ML para ajudá-lo a responder a estas perguntas e muito mais. Uma analogia útil é pensar nesses metadados como o equivalente a registrar no desenvolvimento de software. O MLMD permite que você rastreie de maneira confiável os artefatos e a linhagem associados aos vários componentes do pipeline de ML.
Neste tutorial, você configura um Pipeline TFX para criar um modelo que classifica os pinguins em três espécies com base na massa corporal e no comprimento e profundidade de seus colmos e no comprimento de suas nadadeiras. Em seguida, você usa o MLMD para rastrear a linhagem dos componentes do pipeline.
Pipelines TFX em Colab
Colab é um ambiente de desenvolvimento leve que difere significativamente de um ambiente de produção. Na produção, você pode ter vários componentes de pipeline, como ingestão de dados, transformação, treinamento de modelo, históricos de execução, etc. em vários sistemas distribuídos. Para este tutorial, você deve estar ciente de que existem diferenças significativas no armazenamento de Orquestração e Metadados - tudo é tratado localmente no Colab. Saiba mais sobre TFX em Colab aqui .
Configurar
Primeiro, instalamos e importamos os pacotes necessários, configuramos caminhos e baixamos dados.
Atualizar Pip
Para evitar a atualização do Pip em um sistema quando executado localmente, verifique se estamos executando no Colab. É claro que os sistemas locais podem ser atualizados separadamente.
try:
import colab
!pip install --upgrade pip
except:
pass
Instale e importe TFX
pip install -q -U tfx
Pacotes de importação
Você reiniciou o tempo de execução?
Se você estiver usando o Google Colab, na primeira vez que executar a célula acima, você deve reiniciar o tempo de execução clicando acima do botão "RESTART RUNTIME" ou usando o menu "Runtime> Restart runtime ...". Isso ocorre devido à maneira como o Colab carrega os pacotes.
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
Verifique as versões TFX e 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.4.0 MLMD version: 1.4.0
Baixe o conjunto de dados
Neste colab, usamos o conjunto de dados Palmer Pinguins que pode ser encontrado no Github . Nós processou o conjunto de dados, deixando de fora todos os registros incompletos, e cai island
e sex
colunas, e convertido rótulos para int32
. O conjunto de dados contém 334 registros da massa corporal e do comprimento e profundidade dos colmos dos pinguins e do comprimento de suas nadadeiras. Você usa esses dados para classificar os pinguins em uma das três espécies.
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-datal9104odr/penguins_processed.csv', <http.client.HTTPMessage at 0x7f9c6d8d2290>)
Crie um InteractiveContext
Para executar componentes TFX interativamente neste notebook, criar um InteractiveContext
. O InteractiveContext
usa um diretório temporário com uma instância efêmera banco de dados MLMD. Note-se que as chamadas para InteractiveContext
há-ops fora do ambiente Colab.
Em geral, é uma boa prática para grupo corridas de dutos semelhantes sob um Context
.
interactive_context = InteractiveContext()
WARNING:absl:InteractiveContext pipeline_root argument not provided: using temporary directory /tmp/tfx-interactive-2021-12-05T11_15_56.285625-5hcexlo8 as root for pipeline outputs. WARNING:absl:InteractiveContext metadata_connection_config not provided: using SQLite ML Metadata database at /tmp/tfx-interactive-2021-12-05T11_15_56.285625-5hcexlo8/metadata.sqlite.
Construir o Pipeline TFX
Um pipeline TFX consiste em vários componentes que executam diferentes aspectos do fluxo de trabalho de ML. Neste caderno, você criar e executar os ExampleGen
, StatisticsGen
, SchemaGen
e Trainer
componentes e usar o Evaluator
e Pusher
componente para avaliar e empurrar o modelo treinado.
Consulte a componentes tutorial para mais informações sobre componentes de pipeline TFX.
Instancie e execute o componente 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.
Instancie e execute o componente 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.
Instancie e execute o componente SchemaGen
infer_schema = tfx.components.SchemaGen(
statistics=statistics_gen.outputs['statistics'], infer_feature_shape=True)
interactive_context.run(infer_schema)
WARNING: Logging before InitGoogleLogging() is written to STDERR I1205 11:16:00.941947 6108 rdbms_metadata_access_object.cc:686] No property is defined for the Type
Instancie e execute o componente 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 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
Execute o Trainer
componente.
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/tmpum1crtxy running install running install_lib copying build/lib/penguin_trainer.py -> /tmp/tmpum1crtxy 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/tmpum1crtxy/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4-py3.7.egg-info running install_scripts creating /tmp/tmpum1crtxy/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4.dist-info/WHEEL creating '/tmp/tmpo87nn6ey/tfx_user_code_Trainer-0.0+fef7c4ed90dc336ca26daee59d65660cf8da5fa988b2ca0c89df2f558fda10f4-py3-none-any.whl' and adding '/tmp/tmpum1crtxy' 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/tmpum1crtxy /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools. setuptools.SetuptoolsDeprecationWarning, listing git files failed - pretending there aren't any I1205 11:16:01.389324 6108 rdbms_metadata_access_object.cc:686] No property is defined for the Type I1205 11:16:01.392832 6108 rdbms_metadata_access_object.cc:686] No property is defined for the Type Processing /tmp/tfx-interactive-2021-12-05T11_15_56.285625-5hcexlo8/_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 Epoch 1/5 20/20 [==============================] - 1s 11ms/step - loss: 0.9891 - sparse_categorical_accuracy: 0.4300 - val_loss: 0.9594 - val_sparse_categorical_accuracy: 0.4800 Epoch 2/5 20/20 [==============================] - 0s 6ms/step - loss: 0.8369 - sparse_categorical_accuracy: 0.6350 - val_loss: 0.7484 - val_sparse_categorical_accuracy: 0.8200 Epoch 3/5 20/20 [==============================] - 0s 6ms/step - loss: 0.5289 - sparse_categorical_accuracy: 0.8350 - val_loss: 0.5068 - val_sparse_categorical_accuracy: 0.7800 Epoch 4/5 20/20 [==============================] - 0s 6ms/step - loss: 0.4481 - sparse_categorical_accuracy: 0.7800 - val_loss: 0.4125 - val_sparse_categorical_accuracy: 0.8600 Epoch 5/5 20/20 [==============================] - 0s 6ms/step - loss: 0.3068 - sparse_categorical_accuracy: 0.8650 - val_loss: 0.3279 - val_sparse_categorical_accuracy: 0.8300 2021-12-05 11:16:06.493168: 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-12-05T11_15_56.285625-5hcexlo8/Trainer/model/4/Format-Serving/assets INFO:tensorflow:Assets written to: /tmp/tfx-interactive-2021-12-05T11_15_56.285625-5hcexlo8/Trainer/model/4/Format-Serving/assets
Avalie e impulsione o modelo
Use o Evaluator
componente para avaliar e 'abençoar' o modelo antes de usar o Pusher
componente para empurrar o modelo para um diretório de servir.
_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)
I1205 11:16:07.075275 6108 rdbms_metadata_access_object.cc:686] No property is defined for the Type I1205 11:16:07.078761 6108 rdbms_metadata_access_object.cc:686] 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:114: 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:114: 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)
I1205 11:16:11.935312 6108 rdbms_metadata_access_object.cc:686] No property is defined for the Type
A execução do pipeline do TFX preenche o banco de dados MLMD. Na próxima seção, você usará a API MLMD para consultar esse banco de dados em busca de informações de metadados.
Consultar o banco de dados MLMD
O banco de dados MLMD armazena três tipos de metadados:
- Metadados sobre o pipeline e informações de linhagem associadas aos componentes do pipeline
- Metadados sobre artefatos que foram gerados durante a execução do pipeline
- Metadados sobre as execuções do pipeline
Um pipeline de ambiente de produção típico atende a vários modelos à medida que novos dados chegam. Ao encontrar resultados errôneos em modelos exibidos, você pode consultar o banco de dados MLMD para isolar os modelos errados. Você pode então rastrear a linhagem dos componentes do pipeline que correspondem a esses modelos para depurar seus modelos
Configurar o armazenamento de metadados (MD) com o InteractiveContext
definido anteriormente para consultar o banco de dados 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]
Crie algumas funções auxiliares para visualizar os dados do armazenamento 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)
Primeiro, consulta a loja MD para uma lista de todas as suas armazenados ArtifactTypes
.
display_types(store.get_artifact_types())
Em seguida, consulta todos os PushedModel
artefatos.
pushed_models = store.get_artifacts_by_type("PushedModel")
display_artifacts(store, pushed_models)
Consulte o armazenamento de MD para obter o modelo enviado mais recente. Este tutorial tem apenas um modelo enviado.
pushed_model = pushed_models[-1]
display_properties(store, pushed_model)
Uma das primeiras etapas na depuração de um modelo enviado é observar qual modelo treinado é enviado e quais dados de treinamento são usados para treinar esse modelo.
O MLMD fornece APIs de passagem para percorrer o gráfico de proveniência, que você pode usar para analisar a proveniência do modelo.
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)]
Consulte os artefatos pai para o modelo enviado.
parent_artifacts = get_one_hop_parent_artifacts(store, [pushed_model])
display_artifacts(store, parent_artifacts)
Consulte as propriedades do modelo.
exported_model = parent_artifacts[0]
display_properties(store, exported_model)
Consulte os artefatos upstream para o modelo.
model_parents = get_one_hop_parent_artifacts(store, [exported_model])
display_artifacts(store, model_parents)
Obtenha os dados de treinamento com os quais o modelo foi treinado.
used_data = model_parents[0]
display_properties(store, used_data)
Agora que você tem os dados de treinamento com os quais o modelo foi treinado, consulte o banco de dados novamente para encontrar a etapa de treinamento (execução). Consulte o armazenamento de MD para obter uma lista dos tipos de execução registrados.
display_types(store.get_execution_types())
A etapa de formação é a ExecutionType
chamado tfx.components.trainer.component.Trainer
. Percorra o armazenamento MD para obter a execução do treinador que corresponde ao modelo enviado.
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)
Resumo
Neste tutorial, você aprendeu como pode aproveitar o MLMD para rastrear a linhagem dos componentes do pipeline do TFX e resolver problemas.
Para saber mais sobre como usar o MLMD, verifique estes recursos adicionais: