Ajuda a proteger a Grande Barreira de Corais com TensorFlow em Kaggle Junte Desafio

Compilando TensorFlow ModelServer padrão

Este tutorial mostra como usar os componentes do TensorFlow Serving para criar o TensorFlow ModelServer padrão que descobre e fornece dinamicamente novas versões de um modelo treinado do TensorFlow. Se você só quer usar o servidor padrão para servir os seus modelos, consulte TensorFlow Servindo tutorial básico .

Este tutorial usa o modelo simples de regressão do Softmax apresentado no tutorial do TensorFlow para classificação de imagens manuscritas (dados MNIST). Se você não sabe o que TensorFlow ou MNIST é, ver a MNIST Para ML Beginners tutorial.

O código para este tutorial consiste em duas partes:

  • A Python arquivo mnist_saved_model.py que os trens e exportações múltiplas versões do modelo.

  • A C ++ arquivo main.cc que é o padrão TensorFlow ModelServer que descobre nova exportados modelos e executa um gRPC serviço para servi-los.

Este tutorial percorre as seguintes tarefas:

  1. Treine e exporte um modelo TensorFlow.
  2. Gerenciar modelo de versionamento com TensorFlow Servindo ServerCore .
  3. Configurar lotes usando SavedModelBundleSourceAdapterConfig .
  4. Sirva pedido com TensorFlow Servindo ServerCore .
  5. Execute e teste o serviço.

Antes de começar, primeiro instalar Docker

Treine e exporte o modelo TensorFlow

Primeiro, se você 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/models

Treine (com 100 iterações) e exporte a primeira versão do modelo:

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=100 --model_version=1 /tmp/mnist

Treine (com 2.000 iterações) e exporte a segunda versão do modelo:

tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
  --training_iteration=2000 --model_version=2 /tmp/mnist

Como você pode ver na mnist_saved_model.py , o treinamento e exportação é feito da mesma maneira que é na TensorFlow Servindo tutorial básico . Para fins de demonstração, você está intencionalmente diminuindo as iterações de treinamento para a primeira execução e exportando-as como v1, enquanto o treina normalmente para a segunda execução e exporta-as como v2 para o mesmo diretório pai - como esperamos que o último alcance melhor precisão de classificação devido ao treinamento mais intensivo. Você deverá ver a formação de dados para cada corrida de treinamento em sua /tmp/mnist diretório:

$ ls /tmp/mnist
1  2

ServerCore

Agora imagine que v1 e v2 do modelo são gerados dinamicamente no tempo de execução, conforme novos algoritmos estão sendo experimentados ou quando o modelo é treinado com um novo conjunto de dados. Em um ambiente de produção, você pode querer construir um servidor que possa suportar distribuição gradual, em que a v2 pode ser descoberta, carregada, experimentada, monitorada ou revertida enquanto atende a v1. Como alternativa, você pode desativar a v1 antes de ativar a v2. O TensorFlow Serving é compatível com as duas opções - enquanto uma é boa para manter a disponibilidade durante a transição, a outra é boa para minimizar o uso de recursos (por exemplo, RAM).

TensorFlow Servindo Manager faz exatamente isso. Ele lida com todo o ciclo de vida dos modelos do TensorFlow, incluindo carregamento, disponibilização e descarga, bem como transições de versão. Neste tutorial, você vai construir seu servidor no topo de uma TensorFlow Servindo ServerCore , que envolve internamente um AspiredVersionsManager .

int main(int argc, char** argv) {
  ...

  ServerCore::Options options;
  options.model_server_config = model_server_config;
  options.servable_state_monitor_creator = &CreateServableStateMonitor;
  options.custom_model_config_loader = &LoadCustomModelConfig;

  ::google::protobuf::Any source_adapter_config;
  SavedModelBundleSourceAdapterConfig
      saved_model_bundle_source_adapter_config;
  source_adapter_config.PackFrom(saved_model_bundle_source_adapter_config);
  (*(*options.platform_config_map.mutable_platform_configs())
      [kTensorFlowModelPlatform].mutable_source_adapter_config()) =
      source_adapter_config;

  std::unique_ptr<ServerCore> core;
  TF_CHECK_OK(ServerCore::Create(options, &core));
  RunServer(port, std::move(core));

  return 0;
}

ServerCore::Create() leva um ServerCore :: parâmetro Opções. Aqui estão algumas opções comumente usadas:

  • ModelServerConfig que especifica modelos para ser carregado. Modelos são declarados, quer através model_config_list , que declara uma lista estática de modelos, ou através custom_model_config , que define uma forma personalizada para declarar uma lista de modelos que podem ficar atualizados em tempo de execução.
  • PlatformConfigMap que mapeia a partir do nome da plataforma (tal como tensorflow ) para o PlatformConfig , que é usada para criar o SourceAdapter . SourceAdapter adapta StoragePath (o caminho no qual uma versão do modelo é descoberto) para modelar Loader (cargas a versão do modelo de caminho de armazenamento e fornece interfaces de transição de estado para o Manager ). Se PlatformConfig contém SavedModelBundleSourceAdapterConfig , um SavedModelBundleSourceAdapter será criado, que vamos explicar mais tarde.

SavedModelBundle é um componente chave da TensorFlow Serviço. Ela representa um modelo TensorFlow carregado a partir de um determinado caminho e fornece o mesmo Session::Run interface como TensorFlow à inferência prazo. SavedModelBundleSourceAdapter adapta caminho de armazenamento para Loader<SavedModelBundle> modo que o modelo de vida pode ser gerido pelo Manager . Por favor note que SavedModelBundle é o sucessor do obsoleto SessionBundle . Os usuários são encorajados a usar SavedModelBundle como suporte para SessionBundle em breve será removido.

Com todos estes, ServerCore faz internamente o seguinte:

  • Instancia um FileSystemStoragePathSource que os caminhos de exportação monitores modelo declarou em model_config_list .
  • Instancia um SourceAdapter usando o PlatformConfigMap com a plataforma modelo declarou em model_config_list e liga o FileSystemStoragePathSource a ele. Desta forma, sempre que uma nova versão do modelo é descoberto sob o caminho de exportação, o SavedModelBundleSourceAdapter adapta-lo a um Loader<SavedModelBundle> .
  • Instancia uma implementação específica de Manager chamado AspiredVersionsManager que gerencia todas essas Loader instâncias criadas pela SavedModelBundleSourceAdapter . ServerCore exporta o Manager de interface, delegando as chamadas para AspiredVersionsManager .

Sempre que uma nova versão está disponível, este AspiredVersionsManager carrega a nova versão, e sob seu comportamento descarrega padrão do antigo. Se você deseja começar a personalizar, é recomendável entender os componentes que ele cria internamente e como configurá-los.

É importante mencionar que o TensorFlow Serving foi projetado do zero para ser muito flexível e extensível. Você pode construir vários plugins para o comportamento do sistema personalização, enquanto aproveitando componentes principais genéricos como ServerCore e AspiredVersionsManager . Por exemplo, você pode construir um plug-in de fonte de dados que monitora o armazenamento em nuvem em vez de armazenamento local, ou pode construir um plug-in de política de versão que faz a transição de versão de uma maneira diferente - na verdade, você pode até construir um plug-in de modelo personalizado que serve modelos não TensorFlow. Esses tópicos estão fora do escopo deste tutorial. No entanto, você pode consultar a fonte personalizada e personalizado veiculáveis tutoriais para mais informações.

Lote

Outro recurso típico de servidor que desejamos em um ambiente de produção é o envio em lote. Aceleradores de hardware modernos (GPUs, etc.) usados ​​para fazer inferência de aprendizado de máquina geralmente alcançam a melhor eficiência de computação quando as solicitações de inferência são executadas em grandes lotes.

De dosagem pode ser ligado através do fornecimento adequado SessionBundleConfig ao criar o SavedModelBundleSourceAdapter . Neste caso, definir as BatchingParameters com valores padrão muito bonito. O batching pode ser ajustado definindo valores de tempo limite personalizado, batch_size, etc. Para mais detalhes, consulte a BatchingParameters .

SessionBundleConfig session_bundle_config;
// Batching config
if (enable_batching) {
  BatchingParameters* batching_parameters =
      session_bundle_config.mutable_batching_parameters();
  batching_parameters->mutable_thread_pool_name()->set_value(
      "model_server_batch_threads");
}
*saved_model_bundle_source_adapter_config.mutable_legacy_config() =
    session_bundle_config;

Ao chegar lote completo, pedidos de inferência são mescladas internamente em uma única solicitação grande (tensor) e tensorflow::Session::Run() é invocado (que é onde o ganho de eficiência real em GPUs vem).

Servir com o gerente

Como mencionado acima, TensorFlow Servindo Manager é concebida para ser um componente genérico que pode lidar com a carga, que serve, de descarga e versão de transição de modelos gerados por sistemas de aprendizagem de máquina arbitrária. Suas APIs são construídas em torno dos seguintes conceitos-chave:

  • Veiculável: veiculável é qualquer objeto opaco que pode ser usado para servir as solicitações do cliente. O tamanho e a granularidade de um serviço são flexíveis, de modo que um único serviço pode incluir qualquer coisa, desde um único fragmento de uma tabela de consulta a um único modelo aprendido por máquina a uma tupla de modelos. Um serviço pode ser de qualquer tipo e interface.

  • Veiculáveis Versão: Servables são versionadas e TensorFlow Servindo Manager podem gerenciar uma ou mais versões de um que possa ser veiculado. O controle de versão permite que mais de uma versão de um serviço seja carregada simultaneamente, suportando implementação gradual e experimentação.

  • Veiculável Fluxo: Um fluxo que podem ser veiculados é a sequência de versões de um que possa ser veiculado, com o aumento do números de versão.

  • Modelo: Um modelo aprendeu-máquina é representado por um ou mais servables. Exemplos de servables são:

    • Sessão TensorFlow ou invólucros em torno deles, como SavedModelBundle .
    • Outros tipos de modelos aprendidos com a máquina.
    • Tabelas de consulta de vocabulário.
    • Incorporação de tabelas de pesquisa.

    Um modelo composto pode ser representado como vários serviços independentes ou como um único serviço composto. Um que possa ser veiculado pode também corresponder a uma fracção de um modelo, por exemplo, com uma tabela de pesquisa de grande Sharded em muitos Manager casos.

Para colocar tudo isso no contexto deste tutorial:

  • Modelos TensorFlow são representados por um tipo de que possa ser veiculado - SavedModelBundle . SavedModelBundle internamente consiste em um tensorflow:Session emparelhado com alguns metadados sobre o gráfico é carregado para a sessão e como executá-lo por inferência.

  • Há um diretório do sistema de arquivos contendo um fluxo de exportações do TensorFlow, cada uma em seu próprio subdiretório, cujo nome é um número de versão. O diretório externo pode ser considerado a representação serializada do stream de serviço para o modelo TensorFlow que está sendo servido. Cada exportação corresponde a um serviço que pode ser carregado.

  • AspiredVersionsManager monitora o fluxo de exportação, e gerencia o ciclo de vida de todos os SavedModelBundle servables dinamicamente.

TensorflowPredictImpl::Predict , em seguida, apenas:

  • Solicita SavedModelBundle do gerente (através ServerCore).
  • Usa as generic signatures para mapear nomes tensor lógicos em PredictRequest a nomes tensor reais e os valores se ligam a tensores.
  • Executa inferência.

Teste e execute o servidor

Copie a primeira versão da exportação para a pasta monitorada:

mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored

Em seguida, inicie o servidor:

docker run -p 8500:8500 \
  --mount type=bind,source=/tmp/monitored,target=/models/mnist \
  -t --entrypoint=tensorflow_model_server tensorflow/serving --enable_batching \
  --port=8500 --model_name=mnist --model_base_path=/models/mnist &

O servidor emitirá mensagens de log a cada segundo que dizem "Aspiring version for servable ...", o que significa que ele encontrou a exportação e está rastreando sua existência contínua.

Vamos executar o cliente com --concurrency=10 . Isso enviará solicitações simultâneas ao servidor e, assim, acionará sua lógica de envio em lote.

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

O que resulta em uma saída semelhante a:

...
Inference error rate: 13.1%

Em seguida, copiamos a segunda versão da exportação para a pasta monitorada e executamos novamente o teste:

cp -r /tmp/mnist/2 /tmp/monitored
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
  --num_tests=1000 --server=127.0.0.1:8500 --concurrency=10

O que resulta em uma saída semelhante a:

...
Inference error rate: 9.5%

Isso confirma que seu servidor descobre automaticamente a nova versão e a usa para servir!