Servindo um modelo do TensorFlow

Este tutorial mostra como usar os componentes do TensorFlow Serving para exportar um modelo treinado do TensorFlow e usar o tensorflow_model_server padrão para atendê-lo. Se você já conhece o TensorFlow Serving e deseja saber mais sobre como funcionam os componentes internos do servidor, consulte o tutorial avançado do TensorFlow Serving .

Este tutorial usa um modelo simples de regressão Softmax que classifica dígitos manuscritos. É muito semelhante ao apresentado no tutorial do TensorFlow sobre classificação de imagens usando o conjunto de dados Fashion MNIST .

O código deste tutorial consiste em duas partes:

  • Um arquivo Python, mnist_saved_model.py , que treina e exporta o modelo.

  • Um binário ModelServer que pode ser instalado usando Apt ou compilado a partir de um arquivo C++ ( main.cc ). O TensorFlow Serving ModelServer descobre novos modelos exportados e executa um serviço gRPC para atendê-los.

Antes de começar, primeiro instale o Docker .

Treinar e exportar modelo do TensorFlow

Para a fase de treinamento, o gráfico do TensorFlow é iniciado na sessão do TensorFlow sess , com o tensor de entrada (imagem) como x e o tensor de saída (pontuação Softmax) como y .

Em seguida, usamos o módulo SavedModelBuilder do TensorFlow para exportar o modelo. SavedModelBuilder salva um "instantâneo" do modelo treinado em um armazenamento confiável para que possa ser carregado posteriormente para inferência.

Para obter detalhes sobre o formato SavedModel, consulte a documentação em SavedModel README.md .

Em mnist_saved_model.py , a seguir está um pequeno trecho de código para ilustrar o processo geral de salvar um modelo em disco.

export_path_base = sys.argv[-1]
export_path = os.path.join(
    tf.compat.as_bytes(export_path_base),
    tf.compat.as_bytes(str(FLAGS.model_version)))
print('Exporting trained model to', export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
builder.add_meta_graph_and_variables(
    sess, [tf.compat.v1.saved_model.tag_constants.SERVING],
    signature_def_map={
        'predict_images':
            prediction_signature,
        tf.compat.v1.saved_model.signature_constants
            .DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            classification_signature,
    },
    main_op=tf.compat.v1.tables_initializer(),
    strip_default_attrs=True)
builder.save()

SavedModelBuilder.__init__ leva o seguinte argumento:

  • export_path é o caminho do diretório de exportação.

SavedModelBuilder criará o diretório se ele não existir. No exemplo, concatenamos o argumento da linha de comando e FLAGS.model_version para obter o diretório de exportação. FLAGS.model_version especifica a versão do modelo. Você deve especificar um valor inteiro maior ao exportar uma versão mais recente do mesmo modelo. Cada versão será exportada para um subdiretório diferente no caminho fornecido.

Você pode adicionar metagráficos e variáveis ​​ao construtor usando SavedModelBuilder.add_meta_graph_and_variables() com os seguintes argumentos:

  • sess é a sessão do TensorFlow que contém o modelo treinado que você está exportando.

  • tags é o conjunto de tags com as quais salvar o metagráfico. Nesse caso, como pretendemos utilizar o gráfico na veiculação, utilizamos a tag serve das constantes da tag SavedModel predefinidas. Para obter mais detalhes, consulte tag_constants.py e a documentação relacionada da API do TensorFlow .

  • signature_def_map especifica o mapa da chave fornecida pelo usuário para uma assinatura para um tensorflow::SignatureDef para adicionar ao metagráfico. A assinatura especifica que tipo de modelo está sendo exportado e os tensores de entrada/saída aos quais vincular ao executar a inferência.

    A chave de assinatura especial serving_default especifica a assinatura de serviço padrão. A chave def de assinatura de serviço padrão, juntamente com outras constantes relacionadas às assinaturas, são definidas como parte das constantes de assinatura SavedModel. Para obter mais detalhes, consulte assinatura_constants.py e a documentação relacionada da API do TensorFlow .

    Além disso, para ajudar a construir definições de assinatura facilmente, a API SavedModel fornece utilitários de definição de assinatura . Especificamente, no arquivo mnist_saved_model.py original, usamos signature_def_utils.build_signature_def() para construir predict_signature e classification_signature .

    Como exemplo de como predict_signature é definido, o utilitário usa os seguintes argumentos:

    • inputs={'images': tensor_info_x} especifica as informações do tensor de entrada.

    • outputs={'scores': tensor_info_y} especifica as informações do tensor de pontuações.

    • method_name é o método usado para a inferência. Para solicitações de previsão, deve ser definido como tensorflow/serving/predict . Para outros nomes de métodos, consulte assinatura_constants.py e a documentação relacionada da API do TensorFlow .

Observe que tensor_info_x e tensor_info_y têm a estrutura do buffer de protocolo tensorflow::TensorInfo definida aqui . Para criar facilmente informações sobre tensores, a API TensorFlow SavedModel também fornece utils.py , com documentação relacionada da API TensorFlow .

Além disso, observe que images e scores são nomes alternativos de tensor. Eles podem ser quaisquer strings exclusivas que você desejar e se tornarão os nomes lógicos dos tensores x e y aos quais você se refere para vinculação de tensor ao enviar solicitações de previsão posteriormente.

Por exemplo, se x se refere ao tensor com nome 'long_tensor_name_foo' e y se refere ao tensor com nome 'generated_tensor_name_bar', builder armazenará o nome lógico do tensor para mapeamento de nome real ('images' -> 'long_tensor_name_foo') e ('scores' ' -> 'generated_tensor_name_bar'). Isso permite que o usuário se refira a esses tensores com seus nomes lógicos ao executar a inferência.

Vamos executá-lo!

Primeiro, se ainda não fez isso, clone este repositório em sua máquina local:

git clone https://github.com/tensorflow/serving.git
cd serving

Limpe o diretório de exportação se ele já existir:

rm -rf /tmp/mnist

Agora vamos treinar o modelo:

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  /tmp/mnist

Isso deve resultar em uma saída semelhante a:

Training model...

...

Done training!
Exporting trained model to models/mnist
Done exporting!

Agora vamos dar uma olhada no diretório de exportação.

$ ls /tmp/mnist
1

Conforme mencionado acima, será criado um subdiretório para exportação de cada versão do modelo. FLAGS.model_version tem o valor padrão 1, portanto o subdiretório 1 correspondente é criado.

$ ls /tmp/mnist/1
saved_model.pb variables

Cada subdiretório de versão contém os seguintes arquivos:

  • saved_model.pb é o tensorflow::SavedModel serializado. Inclui uma ou mais definições gráficas do modelo, bem como metadados do modelo, como assinaturas.

  • variables ​​são arquivos que contêm as variáveis ​​serializadas dos gráficos.

Com isso, seu modelo do TensorFlow está exportado e pronto para ser carregado!

Carregar modelo exportado com TensorFlow ModelServer padrão

Use uma imagem de veiculação do Docker para carregar facilmente o modelo para veiculação:

docker run -p 8500:8500 \
--mount type=bind,source=/tmp/mnist,target=/models/mnist \
-e MODEL_NAME=mnist -t tensorflow/serving &

Teste o servidor

Podemos usar o utilitário mnist_client fornecido para testar o servidor. O cliente baixa os dados de teste MNIST, envia-os como solicitações ao servidor e calcula a taxa de erro de inferência.

tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
  --num_tests=1000 --server=127.0.0.1:8500

Isso deve gerar algo como

    ...
    Inference error rate: 11.13%

Esperamos cerca de 90% de precisão para o modelo Softmax treinado e obtemos uma taxa de erro de inferência de 11% para as primeiras 1.000 imagens de teste. Isso confirma que o servidor carrega e executa o modelo treinado com sucesso!