En este instructivo, se muestra cómo usar los componentes de TensorFlow Serving para compilar el TensorFlow ModelServer estándar que descubre y entrega dinámicamente nuevas versiones de un modelo TensorFlow entrenado. Si lo que desea es utilizar el servidor estándar para servir a sus modelos, véase TensorFlow Sirviendo tutorial básico .
Este instructivo usa el modelo simple de regresión de Softmax presentado en el instructivo de TensorFlow para la clasificación de imágenes manuscritas (datos MNIST). Si usted no sabe lo que es TensorFlow o MNIST, ver el MNIST Por ML principiantes tutorial.
El código de este tutorial consta de dos partes:
Un archivo de Python mnist_saved_model.py que los trenes y las exportaciones de varias versiones del modelo.
Un archivo de C ++ main.cc que es el estándar TensorFlow ModelServer que descubre nuevos modelos exportados y dirige una GRPC servicio para servirlos.
Este tutorial recorre las siguientes tareas:
- Entrene y exporte un modelo de TensorFlow.
- Manejo de modelo de versiones con TensorFlow Sirviendo
ServerCore
. - Configurar procesamiento por lotes utilizando
SavedModelBundleSourceAdapterConfig
. - Servir pedido Servir con TensorFlow
ServerCore
. - Ejecute y pruebe el servicio.
Antes de comenzar, primero instalar acoplable
Entrenar y exportar el modelo de TensorFlow
Primero, si aún no lo ha hecho, clone este repositorio en su máquina local:
git clone https://github.com/tensorflow/serving.git
cd serving
Borre el directorio de exportación si ya existe:
rm -rf /tmp/models
Entrene (con 100 iteraciones) y exporte la primera versión del modelo:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=100 --model_version=1 /tmp/mnist
Entrene (con 2000 iteraciones) y exporte la segunda versión del modelo:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=2000 --model_version=2 /tmp/mnist
Como se puede ver en mnist_saved_model.py
, la formación y la exportación se realiza de la misma manera que se encuentra en la TensorFlow Sirviendo tutorial básico . Para fines de demostración, está marcando intencionalmente las iteraciones de entrenamiento para la primera ejecución y exportándolo como v1, mientras lo entrena normalmente para la segunda ejecución y lo exporta como v2 al mismo directorio principal, como esperamos que logre este último. mejor precisión de clasificación debido a un entrenamiento más intensivo. Debería ver la formación de datos para cada recorrido de entrenamiento en su /tmp/mnist
directorio:
$ ls /tmp/mnist
1 2
ServerCore
Ahora imagine que la v1 y la v2 del modelo se generan dinámicamente en tiempo de ejecución, mientras se experimentan nuevos algoritmos o cuando el modelo se entrena con un nuevo conjunto de datos. En un entorno de producción, es posible que desee crear un servidor que admita la implementación gradual, en el que v2 se puede descubrir, cargar, experimentar, monitorear o revertir mientras se entrega v1. Alternativamente, es posible que desee eliminar v1 antes de abrir v2. TensorFlow Serving admite ambas opciones, mientras que una es buena para mantener la disponibilidad durante la transición, la otra es buena para minimizar el uso de recursos (por ejemplo, RAM).
Sirviendo TensorFlow Manager
hace exactamente eso. Maneja el ciclo de vida completo de los modelos de TensorFlow, incluida la carga, el servicio y la descarga, así como las transiciones de versión. En este tutorial, se va a construir su servidor en la parte superior de un TensorFlow Sirviendo ServerCore
, que se envuelve en su interior un 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()
toma un parámetro ServerCore :: Opciones. A continuación, se muestran algunas opciones de uso común:
-
ModelServerConfig
que los modelos especifica para ser cargados. Los modelos se declaran ya sea a travésmodel_config_list
, que declara una lista estática de los modelos, o por medio decustom_model_config
, que define una forma personalizada para declarar una lista de modelos que pueden recibir información actualizada en tiempo de ejecución. -
PlatformConfigMap
que se asigna a partir del nombre de la plataforma (comotensorflow
) a laPlatformConfig
, que se utiliza para crear laSourceAdapter
.SourceAdapter
adaptaStoragePath
(la ruta donde se descubrió una versión del modelo) para modelarLoader
(cargas la versión del modelo de ruta de almacenamiento y proporciona interfaces de transición de estado para elManager
). SiPlatformConfig
contieneSavedModelBundleSourceAdapterConfig
, unSavedModelBundleSourceAdapter
se creará, que explicaremos más adelante.
SavedModelBundle
es un componente clave de TensorFlow porción. Representa un modelo TensorFlow cargado desde una trayectoria dada y proporciona la misma Session::Run
interfaz como TensorFlow a plazo inferencia. SavedModelBundleSourceAdapter
se adapta a la ruta de almacenamiento Loader<SavedModelBundle>
por lo que el modelo de vida puede ser gestionado por Manager
. Tenga en cuenta que SavedModelBundle
es el sucesor del obsoleto SessionBundle
. Se anima a los usuarios a utilizar SavedModelBundle
como el apoyo a SessionBundle
pronto será eliminado.
Con todo esto, ServerCore
hace internamente la siguiente:
- Instancia un
FileSystemStoragePathSource
que las rutas de exportación monitores modelo declaran enmodel_config_list
. - Instancia un
SourceAdapter
utilizando elPlatformConfigMap
con la plataforma modelo declaró enmodel_config_list
y conecta laFileSystemStoragePathSource
a ella. De esta manera, cada vez que una nueva versión del modelo se descubre bajo la ruta de exportación, laSavedModelBundleSourceAdapter
se adapta a unLoader<SavedModelBundle>
. - Crea la instancia de una implementación específica del
Manager
llamadaAspiredVersionsManager
que gestiona todos estosLoader
instancias creadas por elSavedModelBundleSourceAdapter
.ServerCore
exporta elManager
la interfaz mediante la delegación de las llamadas aAspiredVersionsManager
.
Cada vez que una nueva versión está disponible, este AspiredVersionsManager
carga la nueva versión, y bajo su comportamiento predeterminado de descarga el uno viejo. Si desea comenzar a personalizar, le recomendamos que comprenda los componentes que crea internamente y cómo configurarlos.
Vale la pena mencionar que TensorFlow Serving está diseñado desde cero para ser muy flexible y extensible. Usted puede construir varios plugins para el comportamiento del sistema para requisitos particulares, aprovechando al mismo tiempo los componentes básicos genéricos como ServerCore
y AspiredVersionsManager
. Por ejem modelos que no son de TensorFlow. Estos temas están fuera del alcance de este tutorial. Sin embargo, se puede hacer referencia a la fuente de la costumbre y la costumbre se pueden publicar y tutoriales para más información.
Por lotes
Otra característica típica del servidor que queremos en un entorno de producción es el procesamiento por lotes. Los aceleradores de hardware modernos (GPU, etc.) que se utilizan para realizar inferencias de aprendizaje automático generalmente logran la mejor eficiencia de cálculo cuando las solicitudes de inferencia se ejecutan en lotes grandes.
Preparación de lotes se puede activar proporcionando adecuada SessionBundleConfig
al crear el SavedModelBundleSourceAdapter
. En este caso, establecemos los BatchingParameters
con valores por defecto más o menos. El procesamiento por lotes se puede ajustar estableciendo valores personalizados de tiempo de espera, tamaño de lote, etc. Para más detalles, consulte 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;
Al llegar lote completo, solicitudes de inferencia se fusionan internamente en una sola petición grande (tensor), y tensorflow::Session::Run()
se invoca (que es donde el aumento de la eficiencia real de las GPU viene).
Sirva con el gerente
Como se mencionó anteriormente, TensorFlow Sirviendo Manager
está diseñado para ser un componente genérico que puede manejar la carga, que sirve, descarga y transición versión de modelos generados por los sistemas de aprendizaje de máquina arbitrarias. Sus API se basan en los siguientes conceptos clave:
Servable: servable es cualquier objeto opaco que puede ser utilizado para servir las peticiones de cliente. El tamaño y la granularidad de un servidor es flexible, de modo que un único servidor puede incluir cualquier cosa, desde un solo fragmento de una tabla de búsqueda hasta un solo modelo de aprendizaje automático y una tupla de modelos. Un servidor puede ser de cualquier tipo e interfaz.
Servable Versión: Servables están versionados y TensorFlow Sirviendo
Manager
puede administrar una o más versiones de un servable. El control de versiones permite que se cargue más de una versión de un servidor al mismo tiempo, lo que permite la implementación y la experimentación graduales.Servable Stream: Una corriente servable es la secuencia de versiones de un servable, con el aumento de números de versión.
Modelo: Un modelo de máquina-aprendido está representado por uno o más servables. Ejemplos de servibles son:
- TensorFlow sesión o envolturas alrededor de ellos, como
SavedModelBundle
. - Otros tipos de modelos de aprendizaje automático.
- Tablas de búsqueda de vocabulario.
- Incorporación de tablas de búsqueda.
Un modelo compuesto podría representarse como varios servidores independientes o como un solo servidor compuesto. A servable también puede corresponder a una fracción de un modelo, por ejemplo con una gran tabla de búsqueda fragmentados a través de muchos
Manager
instancias.- TensorFlow sesión o envolturas alrededor de ellos, como
Para poner todo esto en el contexto de este tutorial:
TensorFlow modelos están representados por un tipo de servable -
SavedModelBundle
.SavedModelBundle
interna consiste en unatensorflow:Session
emparejado con algunos metadatos acerca de lo que el gráfico se carga en la sesión y la forma de ejecutarlo para la inferencia.Hay un directorio del sistema de archivos que contiene un flujo de exportaciones de TensorFlow, cada una en su propio subdirectorio cuyo nombre es un número de versión. El directorio externo se puede considerar como la representación serializada de la transmisión servible para el modelo de TensorFlow que se entrega. Cada exportación corresponde a un servicio que se puede cargar.
AspiredVersionsManager
monitorea la corriente de exportación, y gestiona el ciclo de vida de todos losSavedModelBundle
servables dinámicamente.
TensorflowPredictImpl::Predict
entonces simplemente:
- Pide
SavedModelBundle
desde el gestor (a través de ServerCore). - Utiliza las
generic signatures
para asignar nombres lógicos tensor enPredictRequest
a los nombres reales de tensor y valores vinculados a los tensores. - Ejecuta inferencia.
Pruebe y ejecute el servidor
Copie la primera versión de la exportación a la carpeta monitoreada:
mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored
Luego inicie el 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 &
El servidor emitirá mensajes de registro cada segundo que dicen "Versión aspirante para servable ...", lo que significa que ha encontrado la exportación y está rastreando su existencia continua.
Vamos a ejecutar el cliente con --concurrency=10
. Esto enviará solicitudes simultáneas al servidor y, por lo tanto, activará su lógica de procesamiento por lotes.
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
Lo que da como resultado una salida que se ve así:
...
Inference error rate: 13.1%
Luego copiamos la segunda versión de la exportación a la carpeta monitoreada y volvemos a ejecutar la prueba:
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
Lo que da como resultado una salida que se ve así:
...
Inference error rate: 9.5%
¡Esto confirma que su servidor descubre automáticamente la nueva versión y la usa para servir!