Comece a usar a validação de dados do TensorFlow

O TensorFlow Data Validation (TFDV) pode analisar dados de treinamento e exibição para:

A API principal dá suporte a cada parte da funcionalidade, com métodos de conveniência que se baseiam e podem ser chamados no contexto de notebooks.

Calculando estatísticas descritivas de dados

O TFDV pode calcular estatísticas descritivas que fornecem uma visão geral rápida dos dados em termos dos recursos presentes e das formas de suas distribuições de valor. Ferramentas como Visão geral de facetas podem fornecer uma visualização sucinta dessas estatísticas para facilitar a navegação.

Por exemplo, suponha que path aponte para um arquivo no formato TFRecord (que contém registros do tipo tensorflow.Example ). O snippet a seguir ilustra o cálculo de estatísticas usando TFDV:

    stats = tfdv.generate_statistics_from_tfrecord(data_location=path)

O valor retornado é um buffer de protocolo DatasetFeatureStatisticsList . O bloco de notas de exemplo contém uma visualização das estatísticas usando a visão geral de facetas :

    tfdv.visualize_statistics(stats)

Captura de tela da visualização de estatísticas

O exemplo anterior assume que os dados são armazenados em um arquivo TFRecord . O TFDV também oferece suporte ao formato de entrada CSV, com extensibilidade para outros formatos comuns. Você pode encontrar os decodificadores de dados disponíveis aqui . Além disso, o TFDV fornece a função de utilitário tfdv.generate_statistics_from_dataframe para usuários com dados na memória representados como um Pandas DataFrame.

Além de calcular um conjunto padrão de estatísticas de dados, o TFDV também pode calcular estatísticas para domínios semânticos (por exemplo, imagens, texto). Para habilitar o cálculo de estatísticas de domínio semântico, passe um objeto tfdv.StatsOptions com enable_semantic_domain_stats definido como True para tfdv.generate_statistics_from_tfrecord .

Executando no Google Cloud

Internamente, o TFDV usa a estrutura de processamento paralelo de dados do Apache Beam para escalar o cálculo de estatísticas em grandes conjuntos de dados. Para aplicativos que desejam uma integração mais profunda com o TFDV (por exemplo, anexar geração de estatísticas ao final de um pipeline de geração de dados, gerar estatísticas para dados em formato personalizado ), a API também expõe um Beam PTransform para geração de estatísticas.

Para executar o TFDV no Google Cloud, o arquivo roda TFDV deve ser baixado e fornecido aos trabalhadores do Dataflow. Baixe o arquivo wheel para o diretório atual da seguinte forma:

pip download tensorflow_data_validation \
  --no-deps \
  --platform manylinux2010_x86_64 \
  --only-binary=:all:

O snippet a seguir mostra um exemplo de uso do TFDV no Google Cloud:


import tensorflow_data_validation as tfdv
from apache_beam.options.pipeline_options import PipelineOptions, GoogleCloudOptions, StandardOptions, SetupOptions

PROJECT_ID = ''
JOB_NAME = ''
GCS_STAGING_LOCATION = ''
GCS_TMP_LOCATION = ''
GCS_DATA_LOCATION = ''
# GCS_STATS_OUTPUT_PATH is the file path to which to output the data statistics
# result.
GCS_STATS_OUTPUT_PATH = ''

PATH_TO_WHL_FILE = ''


# Create and set your PipelineOptions.
options = PipelineOptions()

# For Cloud execution, set the Cloud Platform project, job_name,
# staging location, temp_location and specify DataflowRunner.
google_cloud_options = options.view_as(GoogleCloudOptions)
google_cloud_options.project = PROJECT_ID
google_cloud_options.job_name = JOB_NAME
google_cloud_options.staging_location = GCS_STAGING_LOCATION
google_cloud_options.temp_location = GCS_TMP_LOCATION
options.view_as(StandardOptions).runner = 'DataflowRunner'

setup_options = options.view_as(SetupOptions)
# PATH_TO_WHL_FILE should point to the downloaded tfdv wheel file.
setup_options.extra_packages = [PATH_TO_WHL_FILE]

tfdv.generate_statistics_from_tfrecord(GCS_DATA_LOCATION,
                                       output_path=GCS_STATS_OUTPUT_PATH,
                                       pipeline_options=options)

Nesse caso, o protocolo de estatísticas gerado é armazenado em um arquivo TFRecord gravado em GCS_STATS_OUTPUT_PATH .

OBSERVAÇÃO Ao chamar qualquer uma das funções tfdv.generate_statistics_... (por exemplo, tfdv.generate_statistics_from_tfrecord ) no Google Cloud, você deve fornecer um output_path . Especificar Nenhum pode causar um erro.

Inferir um esquema sobre os dados

O esquema descreve as propriedades esperadas dos dados. Algumas dessas propriedades são:

  • quais recursos devem estar presentes
  • o tipo deles
  • o número de valores para um recurso em cada exemplo
  • a presença de cada recurso em todos os exemplos
  • os domínios esperados de recursos.

Resumindo, o esquema descreve as expectativas de dados "corretos" e pode, portanto, ser usado para detectar erros nos dados (descritos abaixo). Além disso, o mesmo esquema pode ser usado para configurar o TensorFlow Transform para transformações de dados. Observe que o esquema deve ser bastante estático, por exemplo, vários conjuntos de dados podem estar em conformidade com o mesmo esquema, enquanto as estatísticas (descritas acima) podem variar por conjunto de dados.

Como escrever um esquema pode ser uma tarefa tediosa, especialmente para conjuntos de dados com muitos recursos, o TFDV fornece um método para gerar uma versão inicial do esquema com base nas estatísticas descritivas:

    schema = tfdv.infer_schema(stats)

Em geral, o TFDV usa heurística conservadora para inferir propriedades de dados estáveis ​​das estatísticas, a fim de evitar o ajuste excessivo do esquema ao conjunto de dados específico. É altamente recomendável revisar o esquema inferido e refiná-lo conforme necessário , para capturar qualquer conhecimento de domínio sobre os dados que a heurística do TFDV possa ter perdido.

Por padrão, tfdv.infer_schema infere a forma de cada recurso necessário, se value_count.min for igual value_count.max para o recurso. Defina o argumento infer_feature_shape como False para desativar a inferência de forma.

O esquema em si é armazenado como um buffer de protocolo Schema e pode, portanto, ser atualizado/editado usando a API de buffer de protocolo padrão. O TFDV também fornece alguns métodos utilitários para facilitar essas atualizações. Por exemplo, suponha que o esquema contenha a seguinte estrofe para descrever um recurso de string obrigatório payment_type que aceita um único valor:

feature {
  name: "payment_type"
  value_count {
    min: 1
    max: 1
  }
  type: BYTES
  domain: "payment_type"
  presence {
    min_fraction: 1.0
    min_count: 1
  }
}

Para marcar que o recurso deve ser preenchido em pelo menos 50% dos exemplos:

    tfdv.get_feature(schema, 'payment_type').presence.min_fraction = 0.5

O notebook de exemplo contém uma visualização simples do esquema como uma tabela, listando cada recurso e suas principais características conforme codificadas no esquema.

Captura de tela da visualização do esquema

Verificando os dados quanto a erros

Dado um esquema, é possível verificar se um conjunto de dados está de acordo com as expectativas definidas no esquema ou se existem anomalias de dados . Você pode verificar se há erros em seus dados (a) no agregado em todo um conjunto de dados comparando as estatísticas do conjunto de dados com o esquema ou (b) verificando erros por exemplo.

Correspondência das estatísticas do conjunto de dados com um esquema

Para verificar se há erros no agregado, o TFDV compara as estatísticas do conjunto de dados com o esquema e marca as discrepâncias. Por exemplo:

    # Assume that other_path points to another TFRecord file
    other_stats = tfdv.generate_statistics_from_tfrecord(data_location=other_path)
    anomalies = tfdv.validate_statistics(statistics=other_stats, schema=schema)

O resultado é uma instância do buffer do protocolo Anomalies e descreve todos os erros em que as estatísticas não concordam com o esquema. Por exemplo, suponha que os dados em other_path contenham exemplos com valores para o recurso payment_type fora do domínio especificado no esquema.

Isso produz uma anomalia

   payment_type  Unexpected string values  Examples contain values missing from the schema: Prcard (<1%).

indicando que um valor fora do domínio foi encontrado nas estatísticas em < 1% dos valores de recursos.

Se isso era esperado, o esquema pode ser atualizado da seguinte maneira:

   tfdv.get_domain(schema, 'payment_type').value.append('Prcard')

Se a anomalia realmente indicar um erro de dados, os dados subjacentes devem ser corrigidos antes de serem usados ​​para treinamento.

Os vários tipos de anomalias que podem ser detectados por este módulo são listados aqui .

O caderno de exemplo contém uma visualização simples das anomalias como uma tabela, listando as características onde os erros são detectados e uma breve descrição de cada erro.

Captura de tela de anomalias

Verificando erros em uma base por exemplo

O TFDV também oferece a opção de validar os dados por exemplo, em vez de comparar as estatísticas de todo o conjunto de dados com o esquema. O TFDV fornece funções para validar dados por exemplo e, em seguida, gerar estatísticas resumidas para os exemplos anômalos encontrados. Por exemplo:

   options = tfdv.StatsOptions(schema=schema)
   anomalous_example_stats = tfdv.validate_examples_in_tfrecord(
       data_location=input, stats_options=options)

O anomalous_example_stats que validate_examples_in_tfrecord retorna é um buffer de protocolo DatasetFeatureStatisticsList no qual cada conjunto de dados consiste no conjunto de exemplos que exibem uma anomalia específica. Você pode usar isso para determinar o número de exemplos em seu conjunto de dados que exibem uma determinada anomalia e as características desses exemplos.

Ambientes de Esquema

Por padrão, as validações pressupõem que todos os conjuntos de dados em um pipeline aderem a um único esquema. Em alguns casos, é necessária a introdução de pequenas variações de esquema, por exemplo, recursos usados ​​como rótulos são necessários durante o treinamento (e devem ser validados), mas estão ausentes durante a exibição.

Ambientes podem ser usados ​​para expressar tais requisitos. Em particular, os recursos no esquema podem ser associados a um conjunto de ambientes usando default_environment, in_environment e not_in_environment.

Por exemplo, se o recurso dicas estiver sendo usado como rótulo no treinamento, mas ausente nos dados de serviço. Sem o ambiente especificado, ele aparecerá como uma anomalia.

    serving_stats = tfdv.generate_statistics_from_tfrecord(data_location=serving_data_path)
    serving_anomalies = tfdv.validate_statistics(serving_stats, schema)

Captura de tela das anomalias de veiculação

Para corrigir isso, precisamos definir o ambiente padrão para todos os recursos como 'TREINAMENTO' e 'SERVIR' e excluir o recurso 'dicas' do ambiente de SERVIR.

    # All features are by default in both TRAINING and SERVING environments.
    schema.default_environment.append('TRAINING')
    schema.default_environment.append('SERVING')

    # Specify that 'tips' feature is not in SERVING environment.
    tfdv.get_feature(schema, 'tips').not_in_environment.append('SERVING')

    serving_anomalies_with_env = tfdv.validate_statistics(
        serving_stats, schema, environment='SERVING')

Verificando a distorção e desvio de dados

Além de verificar se um conjunto de dados está de acordo com as expectativas definidas no esquema, o TFDV também fornece funcionalidades para detectar:

  • desvio entre os dados de treinamento e veiculação
  • deriva entre diferentes dias de dados de treinamento

O TFDV executa essa verificação comparando as estatísticas de diferentes conjuntos de dados com base nos comparadores de desvio/distorção especificados no esquema. Por exemplo, para verificar se há alguma distorção entre o recurso 'payment_type' no treinamento e no conjunto de dados de exibição:

    # Assume we have already generated the statistics of training dataset, and
    # inferred a schema from it.
    serving_stats = tfdv.generate_statistics_from_tfrecord(data_location=serving_data_path)
    # Add a skew comparator to schema for 'payment_type' and set the threshold
    # of L-infinity norm for triggering skew anomaly to be 0.01.
    tfdv.get_feature(schema, 'payment_type').skew_comparator.infinity_norm.threshold = 0.01
    skew_anomalies = tfdv.validate_statistics(
        statistics=train_stats, schema=schema, serving_statistics=serving_stats)

OBSERVAÇÃO A norma L-infinity detectará apenas a inclinação para os recursos categóricos. Em vez de especificar um limite infinity_norm , especificar um limite jensen_shannon_divergence no skew_comparator detectaria a distorção para recursos numéricos e categóricos.

O mesmo que verificar se um conjunto de dados está em conformidade com as expectativas definidas no esquema, o resultado também é uma instância do buffer de protocolo Anomalies e descreve qualquer distorção entre os conjuntos de dados de treinamento e de serviço. Por exemplo, suponha que os dados de serviço contenham significativamente mais exemplos com o recurso payement_type tendo o valor Cash , isso produz uma anomalia de distorção

   payment_type  High L-infinity distance between serving and training  The L-infinity distance between serving and training is 0.0435984 (up to six significant digits), above the threshold 0.01. The feature value with maximum difference is: Cash

Se a anomalia realmente indicar uma distorção entre os dados de treinamento e de exibição, será necessária uma investigação mais aprofundada, pois isso pode ter um impacto direto no desempenho do modelo.

O notebook de exemplo contém um exemplo simples de verificação de anomalias baseadas em distorção.

A detecção de desvio entre diferentes dias de dados de treinamento pode ser feita de maneira semelhante

    # Assume we have already generated the statistics of training dataset for
    # day 2, and inferred a schema from it.
    train_day1_stats = tfdv.generate_statistics_from_tfrecord(data_location=train_day1_data_path)
    # Add a drift comparator to schema for 'payment_type' and set the threshold
    # of L-infinity norm for triggering drift anomaly to be 0.01.
    tfdv.get_feature(schema, 'payment_type').drift_comparator.infinity_norm.threshold = 0.01
    drift_anomalies = tfdv.validate_statistics(
        statistics=train_day2_stats, schema=schema, previous_statistics=train_day1_stats)

OBSERVAÇÃO A norma L-infinity detectará apenas a inclinação para os recursos categóricos. Em vez de especificar um limite infinity_norm , especificar um limite jensen_shannon_divergence no skew_comparator detectaria a distorção para recursos numéricos e categóricos.

Gravando conector de dados personalizado

Para calcular estatísticas de dados, o TFDV fornece vários métodos convenientes para lidar com dados de entrada em vários formatos (por exemplo, TFRecord de tf.train.Example , CSV etc.). Se o seu formato de dados não estiver nesta lista, você precisará escrever um conector de dados personalizado para ler os dados de entrada e conectá-lo à API principal do TFDV para calcular estatísticas de dados.

A API principal do TFDV para computação de estatísticas de dados é uma Beam PTransform que usa uma PCollection de lotes de exemplos de entrada (um lote de exemplos de entrada é representado como um Arrow RecordBatch) e gera uma PCollection contendo um único buffer de protocolo DatasetFeatureStatisticsList .

Depois de implementar o conector de dados personalizado que agrupa seus exemplos de entrada em um Arrow RecordBatch, você precisa conectá-lo à API tfdv.GenerateStatistics para calcular as estatísticas de dados. Tome TFRecord de tf.train.Example 's por exemplo. tfx_bsl fornece o conector de dados TFExampleRecord e abaixo está um exemplo de como conectá-lo com a API tfdv.GenerateStatistics .

import tensorflow_data_validation as tfdv
from tfx_bsl.public import tfxio
import apache_beam as beam
from tensorflow_metadata.proto.v0 import statistics_pb2

DATA_LOCATION = ''
OUTPUT_LOCATION = ''

with beam.Pipeline() as p:
    _ = (
    p
    # 1. Read and decode the data with tfx_bsl.
    | 'TFXIORead' >> (
          tfxio.TFExampleRecord(
              file_pattern=[DATA_LOCATION],
              telemetry_descriptors=['my', 'tfdv']).BeamSource())
    # 2. Invoke TFDV `GenerateStatistics` API to compute the data statistics.
    | 'GenerateStatistics' >> tfdv.GenerateStatistics()
    # 3. Materialize the generated data statistics.
    | 'WriteStatsOutput' >> WriteStatisticsToTFRecord(OUTPUT_LOCATION))

Computando estatísticas sobre fatias de dados

O TFDV pode ser configurado para calcular estatísticas sobre fatias de dados. O fatiamento pode ser ativado fornecendo funções de fatiamento que recebem um Arrow RecordBatch e geram uma sequência de tuplas de formulário (slice key, record batch) . O TFDV fornece uma maneira fácil de gerar funções de divisão baseadas em valor de recurso que podem ser fornecidas como parte de tfdv.StatsOptions ao computar estatísticas.

Quando o fatiamento está ativado, o proto DatasetFeatureStatisticsList de saída contém vários protos DatasetFeatureStatistics , um para cada fatia. Cada fatia é identificada por um nome exclusivo que é definido como o nome do conjunto de dados no proto DatasetFeatureStatistics . Por padrão, o TFDV calcula estatísticas para o conjunto de dados geral, além das fatias configuradas.

import tensorflow_data_validation as tfdv
from tensorflow_data_validation.utils import slicing_util

# Slice on country feature (i.e., every unique value of the feature).
slice_fn1 = slicing_util.get_feature_value_slicer(features={'country': None})

# Slice on the cross of country and state feature (i.e., every unique pair of
# values of the cross).
slice_fn2 = slicing_util.get_feature_value_slicer(
    features={'country': None, 'state': None})

# Slice on specific values of a feature.
slice_fn3 = slicing_util.get_feature_value_slicer(
    features={'age': [10, 50, 70]})

stats_options = tfdv.StatsOptions(
    slice_functions=[slice_fn1, slice_fn2, slice_fn3])