O componente de pipeline do InfraValidator TFX

InfraValidator é um componente TFX usado como uma camada de alerta antecipado antes de colocar um modelo em produção. O nome validador “infra” vem do fato de estar validando o modelo no modelo real que atende a “infraestrutura”. Se o Evaluator deve garantir o desempenho do modelo, o InfraValidator deve garantir que o modelo esteja mecanicamente correto e evitar que modelos ruins sejam empurrados.

Como funciona?

O InfraValidator pega o modelo, inicia um servidor de modelo em sandbox com o modelo e verifica se ele pode ser carregado com êxito e, opcionalmente, consultado. O resultado da infra-validação será gerado na saída blessing da mesma forma que o Avaliador .

O InfraValidator se concentra na compatibilidade entre o binário do servidor do modelo (por exemplo, TensorFlow Serving ) e o modelo a ser implantado. Apesar do nome validador "infra", é responsabilidade do usuário configurar o ambiente corretamente, e o infra validador apenas interage com o servidor modelo no ambiente configurado pelo usuário para verificar se funciona bem. Configurar este ambiente corretamente garantirá que a aprovação ou falha na validação de infra será um indicativo de se o modelo seria utilizável no ambiente de serviço de produção. Isto implica alguns dos seguintes, mas não está limitado a:

  1. O InfraValidator está usando o mesmo modelo binário de servidor que será usado na produção. Este é o nível mínimo para o qual o ambiente de infravalidação deve convergir.
  2. O InfraValidator está usando os mesmos recursos (por exemplo, quantidade de alocação e tipo de CPU, memória e aceleradores) que serão usados ​​na produção.
  3. O InfraValidator está usando o mesmo modelo de configuração de servidor que será usado na produção.

Dependendo da situação, os usuários podem escolher até que ponto o InfraValidator deve ser idêntico ao ambiente de produção. Tecnicamente, um modelo pode ser infravalidado em um ambiente Docker local e então servido em um ambiente completamente diferente (por exemplo, cluster Kubernetes) sem problemas. No entanto, o InfraValidator não terá verificado esta divergência.

Modo de operação

Dependendo da configuração, a infra-validação é feita em um dos seguintes modos:

  • Modo LOAD_ONLY : verifica se o modelo foi carregado com sucesso na infraestrutura de serviço ou não. OU
  • Modo LOAD_AND_QUERY : modo LOAD_ONLY mais o envio de algumas solicitações de amostra para verificar se o modelo é capaz de servir inferências. O InfraValidator não se importa se a previsão estava correta ou não. Só importa se a solicitação foi bem-sucedida ou não.

Como faço para usá-lo?

Normalmente o InfraValidator é definido próximo a um componente Evaluator, e sua saída é alimentada em um Pusher. Se o InfraValidator falhar, o modelo não será enviado.

evaluator = Evaluator(
    model=trainer.outputs['model'],
    examples=example_gen.outputs['examples'],
    baseline_model=model_resolver.outputs['model'],
    eval_config=tfx.proto.EvalConfig(...)
)

infra_validator = InfraValidator(
    model=trainer.outputs['model'],
    serving_spec=tfx.proto.ServingSpec(...)
)

pusher = Pusher(
    model=trainer.outputs['model'],
    model_blessing=evaluator.outputs['blessing'],
    infra_blessing=infra_validator.outputs['blessing'],
    push_destination=tfx.proto.PushDestination(...)
)

Configurando um componente InfraValidator.

Existem três tipos de protos para configurar o InfraValidator.

ServingSpec

ServingSpec é a configuração mais importante para o InfraValidator. Ele define:

  • que tipo de servidor modelo executar
  • onde executá-lo

Para tipos de servidores modelo (chamados de binário de serviço), oferecemos suporte

As seguintes plataformas de serviço são atualmente suportadas:

  • Docker local (o Docker deve ser instalado com antecedência)
  • Kubernetes (suporte limitado apenas para KubeflowDagRunner)

A escolha do serviço binário e da plataforma de serviço é feita especificando um bloco oneof do ServingSpec . Por exemplo, para usar o binário TensorFlow Serving em execução no cluster Kubernetes, os campos tensorflow_serving e kubernetes devem ser definidos.

infra_validator=InfraValidator(
    model=trainer.outputs['model'],
    serving_spec=tfx.proto.ServingSpec(
        tensorflow_serving=tfx.proto.TensorFlowServing(
            tags=['latest']
        ),
        kubernetes=tfx.proto.KubernetesConfig()
    )
)

Para configurar ainda mais ServingSpec , verifique a definição do protobuf .

ValidationSpec

Configuração opcional para ajustar os critérios de infravalidação ou fluxo de trabalho.

infra_validator=InfraValidator(
    model=trainer.outputs['model'],
    serving_spec=tfx.proto.ServingSpec(...),
    validation_spec=tfx.proto.ValidationSpec(
        # How much time to wait for model to load before automatically making
        # validation fail.
        max_loading_time_seconds=60,
        # How many times to retry if infra validation fails.
        num_tries=3
    )
)

Todos os campos ValidationSpec possuem um valor padrão sólido. Confira mais detalhes na definição do protobuf .

RequestSpec

Configuração opcional para especificar como construir solicitações de amostra ao executar a validação de infra no modo LOAD_AND_QUERY . Para usar o modo LOAD_AND_QUERY , é necessário especificar as propriedades de execução request_spec , bem como examples de canais de entrada na definição do componente.

infra_validator = InfraValidator(
    model=trainer.outputs['model'],
    # This is the source for the data that will be used to build a request.
    examples=example_gen.outputs['examples'],
    serving_spec=tfx.proto.ServingSpec(
        # Depending on what kind of model server you're using, RequestSpec
        # should specify the compatible one.
        tensorflow_serving=tfx.proto.TensorFlowServing(tags=['latest']),
        local_docker=tfx.proto.LocalDockerConfig(),
    ),
    request_spec=tfx.proto.RequestSpec(
        # InfraValidator will look at how "classification" signature is defined
        # in the model, and automatically convert some samples from `examples`
        # artifact to prediction RPC requests.
        tensorflow_serving=tfx.proto.TensorFlowServingRequestSpec(
            signature_names=['classification']
        ),
        num_examples=10  # How many requests to make.
    )
)

Produzindo um SavedModel com aquecimento

(Da versão 0.30.0)

Como o InfraValidator valida o modelo com solicitações reais, ele pode facilmente reutilizar essas solicitações de validação como solicitações de aquecimento de um SavedModel. O InfraValidator fornece uma opção ( RequestSpec.make_warmup ) para exportar um SavedModel com aquecimento.

infra_validator = InfraValidator(
    ...,
    request_spec=tfx.proto.RequestSpec(..., make_warmup=True)
)

Em seguida, o artefato InfraBlessing de saída conterá um SavedModel com aquecimento e também poderá ser enviado pelo Pusher , assim como o artefato Model .

Limitações

O InfraValidator atual ainda não está completo e tem algumas limitações.

  • Somente o formato do modelo TensorFlow SavedModel pode ser validado.
  • Ao executar o TFX no Kubernetes, o pipeline deve ser executado pelo KubeflowDagRunner dentro do Kubeflow Pipelines. O servidor modelo será iniciado no mesmo cluster Kubernetes e no mesmo namespace que o Kubeflow está usando.
  • O InfraValidator se concentra principalmente em implantações no TensorFlow Serving e, embora ainda seja útil, é menos preciso para implantações no TensorFlow Lite e TensorFlow.js ou em outras estruturas de inferência.
  • Há um suporte limitado no modo LOAD_AND_QUERY para a assinatura do método Predict (que é o único método exportável no TensorFlow 2). O InfraValidator requer que a assinatura do Predict consuma um tf.Example serializado como a única entrada.

    @tf.function
    def parse_and_run(serialized_example):
      features = tf.io.parse_example(serialized_example, FEATURES)
      return model(features)
    
    model.save('path/to/save', signatures={
      # This exports "Predict" method signature under name "serving_default".
      'serving_default': parse_and_run.get_concrete_function(
          tf.TensorSpec(shape=[None], dtype=tf.string, name='examples'))
    })