Sirviendo un modelo TensorFlow

Este tutorial le muestra cómo usar los componentes de TensorFlow Serving para exportar un modelo de TensorFlow entrenado y usar el tensorflow_model_server estándar para servirlo. Si ya está familiarizado con TensorFlow Serving y desea saber más sobre cómo funcionan los componentes internos del servidor, consulte el tutorial avanzado de TensorFlow Serving .

Este tutorial utiliza un modelo de regresión Softmax simple que clasifica dígitos escritos a mano. Es muy similar al presentado en el tutorial de TensorFlow sobre clasificación de imágenes utilizando el conjunto de datos Fashion MNIST .

El código de este tutorial consta de dos partes:

  • Un archivo Python, mnist_saved_model.py , que entrena y exporta el modelo.

  • Un binario de ModelServer que puede instalarse usando Apt o compilarse desde un archivo C++ ( main.cc ). TensorFlow Serving ModelServer descubre nuevos modelos exportados y ejecuta un servicio gRPC para servirlos.

Antes de comenzar, primero instale Docker .

Entrenar y exportar el modelo TensorFlow

Para la fase de entrenamiento, el gráfico de TensorFlow se inicia en la sess de TensorFlow, con el tensor de entrada (imagen) como x y el tensor de salida (puntuación Softmax) como y .

Luego usamos el módulo SavedModelBuilder de TensorFlow para exportar el modelo. SavedModelBuilder guarda una "instantánea" del modelo entrenado en un almacenamiento confiable para poder cargarlo más tarde para realizar inferencias.

Para obtener detalles sobre el formato SavedModel, consulte la documentación en SavedModel README.md .

De mnist_saved_model.py , el siguiente es un breve fragmento de código para ilustrar el proceso general de guardar un modelo en el 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__ toma el siguiente argumento:

  • export_path es la ruta del directorio de exportación.

SavedModelBuilder creará el directorio si no existe. En el ejemplo, concatenamos el argumento de la línea de comando y FLAGS.model_version para obtener el directorio de exportación. FLAGS.model_version especifica la versión del modelo. Debe especificar un valor entero mayor al exportar una versión más reciente del mismo modelo. Cada versión se exportará a un subdirectorio diferente en la ruta indicada.

Puede agregar metagráficos y variables al generador usando SavedModelBuilder.add_meta_graph_and_variables() con los siguientes argumentos:

  • sess es la sesión de TensorFlow que contiene el modelo entrenado que está exportando.

  • tags es el conjunto de etiquetas con las que guardar el metagráfico. En este caso, dado que pretendemos utilizar el gráfico en la publicación, utilizamos la etiqueta serve de las constantes de etiqueta SavedModel predefinidas. Para obtener más detalles, consulte tag_constants.py y la documentación relacionada de la API de TensorFlow .

  • signature_def_map especifica el mapa de la clave proporcionada por el usuario para una firma en un tensorflow::SignatureDef para agregar al metagráfico. La firma especifica qué tipo de modelo se exporta y los tensores de entrada/salida a los que vincularse al ejecutar la inferencia.

    La clave de firma especial serving_default especifica la firma de publicación predeterminada. La clave de definición de firma de servicio predeterminada, junto con otras constantes relacionadas con las firmas, se definen como parte de las constantes de firma de SavedModel. Para obtener más detalles, consulte Signature_constants.py y la documentación relacionada de la API de TensorFlow .

    Además, para ayudar a crear definiciones de firma fácilmente, la API SavedModel proporciona utilidades de definición de firma . Específicamente, en el archivo mnist_saved_model.py original, usamos signature_def_utils.build_signature_def() para crear predict_signature y classification_signature .

    Como ejemplo de cómo se define predict_signature , la utilidad toma los siguientes argumentos:

    • inputs={'images': tensor_info_x} especifica la información del tensor de entrada.

    • outputs={'scores': tensor_info_y} especifica la información del tensor de puntuaciones.

    • method_name es el método utilizado para la inferencia. Para solicitudes de predicción, debe configurarse en tensorflow/serving/predict . Para conocer otros nombres de métodos, consulte Signature_constants.py y la documentación relacionada de la API de TensorFlow .

Tenga en cuenta que tensor_info_x y tensor_info_y tienen la estructura del búfer de protocolo tensorflow::TensorInfo definido aquí . Para crear fácilmente información tensorial, la API TensorFlow SavedModel también proporciona utils.py , con documentación relacionada con la API TensorFlow .

Además, tenga en cuenta que images y scores son nombres de alias de tensor. Pueden ser cualquier cadena única que desee y se convertirán en los nombres lógicos de los tensores x y los que hará referencia para la vinculación del tensor cuando envíe solicitudes de predicción más adelante.

Por ejemplo, si x se refiere al tensor con nombre 'long_tensor_name_foo' e y se refiere al tensor con nombre 'generated_tensor_name_bar', builder almacenará el nombre lógico del tensor en el mapeo del nombre real ('images' -> 'long_tensor_name_foo') y ('scores ' -> 'barra_nombre_tensor_generado'). Esto permite al usuario hacer referencia a estos tensores con sus nombres lógicos cuando ejecuta la inferencia.

¡Vamos a ejecutarlo!

Primero, si aún no lo has hecho, clona este repositorio en tu 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/mnist

Ahora entrenemos el modelo:

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

Esto debería dar como resultado un resultado similar al siguiente:

Training model...

...

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

Ahora echemos un vistazo al directorio de exportación.

$ ls /tmp/mnist
1

Como se mencionó anteriormente, se creará un subdirectorio para exportar cada versión del modelo. FLAGS.model_version tiene el valor predeterminado de 1, por lo tanto se crea el subdirectorio correspondiente 1 .

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

Cada subdirectorio de versión contiene los siguientes archivos:

  • saved_model.pb es el tensorflow serializado::SavedModel. Incluye una o más definiciones de gráficos del modelo, así como metadatos del modelo, como firmas.

  • variables son archivos que contienen las variables serializadas de los gráficos.

¡Con eso, su modelo de TensorFlow se exporta y está listo para ser cargado!

Cargue el modelo exportado con TensorFlow ModelServer estándar

Utilice una imagen de publicación de Docker para cargar fácilmente el modelo para publicar:

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

Probar el servidor

Podemos utilizar la utilidad mnist_client proporcionada para probar el servidor. El cliente descarga datos de prueba MNIST, los envía como solicitudes al servidor y calcula la tasa de error de inferencia.

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

Esto debería generar algo como

    ...
    Inference error rate: 11.13%

Esperamos alrededor del 90% de precisión para el modelo Softmax entrenado y obtenemos una tasa de error de inferencia del 11% para las primeras 1000 imágenes de prueba. ¡Esto confirma que el servidor carga y ejecuta el modelo entrenado correctamente!