Servire un modello TensorFlow

Questo tutorial mostra come utilizzare i componenti TensorFlow Serving per esportare un modello TensorFlow addestrato e utilizzare il tensorflow_model_server standard per servirlo. Se hai già familiarità con TensorFlow Serving e desideri saperne di più su come funzionano i componenti interni del server, consulta il tutorial avanzato di TensorFlow Serving .

Questo tutorial utilizza un semplice modello di regressione Softmax che classifica le cifre scritte a mano. È molto simile a quello introdotto nel tutorial di TensorFlow sulla classificazione delle immagini utilizzando il set di dati Fashion MNIST .

Il codice per questo tutorial è composto da due parti:

  • Un file Python, mnist_saved_model.py , che addestra ed esporta il modello.

  • Un binario ModelServer che può essere installato utilizzando Apt o compilato da un file C++ ( main.cc ). TensorFlow Serving ModelServer rileva nuovi modelli esportati ed esegue un servizio gRPC per servirli.

Prima di iniziare, installa Docker .

Addestra ed esporta il modello TensorFlow

Per la fase di training, il grafico TensorFlow viene avviato nella sessione TensorFlow sess , con il tensore di input (immagine) come x e il tensore di output (punteggio Softmax) come y .

Quindi utilizziamo il modulo SavedModelBuilder di TensorFlow per esportare il modello. SavedModelBuilder salva una "istantanea" del modello addestrato in un archivio affidabile in modo che possa essere caricato successivamente per l'inferenza.

Per dettagli sul formato SavedModel, consultare la documentazione su SavedModel README.md .

Da mnist_saved_model.py , quello che segue è un breve snippet di codice per illustrare il processo generale di salvataggio di un modello su 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__ accetta il seguente argomento:

  • export_path è il percorso della directory di esportazione.

SavedModelBuilder creerà la directory se non esiste. Nell'esempio, concateniamo l'argomento della riga di comando e FLAGS.model_version per ottenere la directory di esportazione. FLAGS.model_version specifica la versione del modello. Dovresti specificare un valore intero più grande quando esporti una versione più recente dello stesso modello. Ciascuna versione verrà esportata in una sottodirectory diversa nel percorso indicato.

Puoi aggiungere meta grafico e variabili al builder utilizzando SavedModelBuilder.add_meta_graph_and_variables() con i seguenti argomenti:

  • sess è la sessione TensorFlow che contiene il modello addestrato che stai esportando.

  • tags è l'insieme di tag con cui salvare il meta grafico. In questo caso, poiché intendiamo utilizzare il grafico nel servizio, utilizziamo il tag serve dalle costanti del tag SavedModel predefinite. Per ulteriori dettagli, consulta tag_constants.py e la relativa documentazione dell'API TensorFlow .

  • signature_def_map specifica la mappa della chiave fornita dall'utente per una firma su un tensorflow::SignatureDef da aggiungere al meta grafico. La firma specifica quale tipo di modello viene esportato e i tensori di input/output a cui associarsi durante l'esecuzione dell'inferenza.

    La chiave di firma speciale serving_default specifica la firma di servizio predefinita. La chiave di definizione della firma di servizio predefinita, insieme ad altre costanti relative alle firme, sono definite come parte delle costanti della firma SavedModel. Per ulteriori dettagli, consulta Signature_constants.py e la relativa documentazione dell'API TensorFlow .

    Inoltre, per aiutare a creare facilmente le def delle firme, l'API SavedModel fornisce le def util delle firme . Nello specifico, nel file mnist_saved_model.py originale, utilizziamo signature_def_utils.build_signature_def() per creare predict_signature e classification_signature .

    Come esempio di come viene definito predict_signature , l'util accetta i seguenti argomenti:

    • inputs={'images': tensor_info_x} specifica le informazioni sul tensore di input.

    • outputs={'scores': tensor_info_y} specifica le informazioni sul tensore dei punteggi.

    • method_name è il metodo utilizzato per l'inferenza. Per le richieste di previsione, deve essere impostato su tensorflow/serving/predict . Per altri nomi di metodi, consulta Signature_constants.py e la relativa documentazione dell'API TensorFlow .

Tieni presente che tensor_info_x e tensor_info_y hanno la struttura del buffer del protocollo tensorflow::TensorInfo definita qui . Per creare facilmente informazioni sui tensori, l'API TensorFlow SavedModel fornisce anche utils.py , con la relativa documentazione dell'API TensorFlow .

Inoltre, si noti che images e scores sono nomi alias di tensori. Possono essere qualunque stringa univoca desideri e diventeranno i nomi logici del tensore x a y fare riferimento per l'associazione del tensore quando invii richieste di previsione in un secondo momento.

Ad esempio, se x si riferisce al tensore con il nome 'long_tensor_name_foo' e y si riferisce al tensore con il nome 'generated_tensor_name_bar', builder memorizzerà il nome logico del tensore per la mappatura del nome reale ('images' -> 'long_tensor_name_foo') e ('scores ' -> 'generated_tensor_name_bar'). Ciò consente all'utente di fare riferimento a questi tensori con i loro nomi logici durante l'esecuzione dell'inferenza.

Eseguiamolo!

Innanzitutto, se non l'hai ancora fatto, clona questo repository sul tuo computer locale:

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

Cancella la directory di esportazione se esiste già:

rm -rf /tmp/mnist

Ora addestriamo il modello:

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

Ciò dovrebbe comportare un output simile a:

Training model...

...

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

Ora diamo un'occhiata alla directory di esportazione.

$ ls /tmp/mnist
1

Come accennato in precedenza, verrà creata una sottodirectory per esportare ciascuna versione del modello. FLAGS.model_version ha il valore predefinito pari a 1, pertanto viene creata la corrispondente sottodirectory 1 .

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

Ciascuna sottodirectory della versione contiene i seguenti file:

  • saved_model.pb è il tensorflow serializzato::SavedModel. Include una o più definizioni grafiche del modello, nonché metadati del modello come le firme.

  • variables sono file che contengono le variabili serializzate dei grafici.

Con ciò, il tuo modello TensorFlow viene esportato ed è pronto per essere caricato!

Carica il modello esportato con TensorFlow ModelServer standard

Utilizza un'immagine di servizio Docker per caricare facilmente il modello per la pubblicazione:

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

Testare il server

Possiamo utilizzare l'utilità mnist_client fornita per testare il server. Il client scarica i dati del test MNIST, li invia come richieste al server e calcola il tasso di errore di inferenza.

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

Questo dovrebbe produrre qualcosa di simile

    ...
    Inference error rate: 11.13%

Ci aspettiamo una precisione di circa il 90% per il modello Softmax addestrato e otteniamo un tasso di errore di inferenza dell'11% per le prime 1000 immagini di test. Ciò conferma che il server carica ed esegue correttamente il modello addestrato!