Dieses Tutorial zeigt Ihnen, wie Sie mithilfe von TensorFlow Serving-Komponenten den Standard-TensorFlow ModelServer erstellen, der neue Versionen eines trainierten TensorFlow-Modells dynamisch erkennt und bereitstellt. Wenn Sie nur den Standardserver für die Bereitstellung Ihrer Modelle verwenden möchten, lesen Sie das grundlegende Tutorial zu TensorFlow Serving .
In diesem Lernprogramm wird das einfache Softmax-Regressionsmodell verwendet, das im TensorFlow-Lernprogramm für die Klassifizierung handgeschriebener Bilder (MNIST-Daten) eingeführt wurde. Wenn Sie nicht wissen, was TensorFlow oder MNIST ist, lesen Sie das Tutorial MNIST für ML-Anfänger .
Der Code für dieses Tutorial besteht aus zwei Teilen:
Eine Python-Datei mnist_saved_model.py , die mehrere Versionen des Modells trainiert und exportiert.
Eine C ++ - Datei main.cc, die der Standard-TensorFlow ModelServer ist, der neue exportierte Modelle erkennt und einen gRPC- Dienst für deren Bereitstellung ausführt.
In diesem Tutorial werden die folgenden Aufgaben ausgeführt:
- Trainieren und exportieren Sie ein TensorFlow-Modell.
- Verwalten Sie die Modellversionierung mit TensorFlow Serving
ServerCore
. - Konfigurieren Sie die
SavedModelBundleSourceAdapterConfig
mitSavedModelBundleSourceAdapterConfig
. - Anfrage mit TensorFlow Serving
ServerCore
. - Führen Sie den Dienst aus und testen Sie ihn.
Bevor Sie beginnen, installieren Sie zuerst Docker
TensorFlow-Modell trainieren und exportieren
Wenn Sie dies noch nicht getan haben, klonen Sie dieses Repository zunächst auf Ihren lokalen Computer:
git clone https://github.com/tensorflow/serving.git
cd serving
Löschen Sie das Exportverzeichnis, falls es bereits vorhanden ist:
rm -rf /tmp/models
Trainiere (mit 100 Iterationen) und exportiere die erste Version des Modells:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=100 --model_version=1 /tmp/mnist
Trainiere (mit 2000 Iterationen) und exportiere die zweite Version des Modells:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=2000 --model_version=2 /tmp/mnist
Wie Sie in mnist_saved_model.py
, erfolgt das Training und Exportieren genauso wie im TensorFlow Serving-Lernprogramm . Zu Demonstrationszwecken wählen Sie absichtlich die Trainingsiterationen für den ersten Lauf herunter und exportieren sie als v1, während Sie sie normalerweise für den zweiten Lauf trainieren und als v2 in dasselbe übergeordnete Verzeichnis exportieren - wie wir es von letzterem erwarten Bessere Klassifizierungsgenauigkeit durch intensiveres Training. Sie sollten die Trainingsdaten für jeden Trainingslauf in Ihrem Verzeichnis /tmp/mnist
:
$ ls /tmp/mnist
1 2
ServerCore
Stellen Sie sich nun vor, v1 und v2 des Modells werden zur Laufzeit dynamisch generiert, wenn neue Algorithmen erprobt werden oder wenn das Modell mit einem neuen Datensatz trainiert wird. In einer Produktionsumgebung möchten Sie möglicherweise einen Server erstellen, der die schrittweise Einführung unterstützt, auf dem Version 2 während der Bereitstellung von Version 1 erkannt, geladen, experimentiert, überwacht oder zurückgesetzt werden kann. Alternativ können Sie v1 herunterfahren, bevor Sie v2 aufrufen. TensorFlow Serving unterstützt beide Optionen - während eine für die Aufrechterhaltung der Verfügbarkeit während des Übergangs geeignet ist, ist die andere für die Minimierung des Ressourcenverbrauchs (z. B. RAM) geeignet.
TensorFlow Serving Manager
macht genau das. Es behandelt den gesamten Lebenszyklus von TensorFlow-Modellen, einschließlich Laden, Servieren und Entladen sowie Versionsübergänge. In diesem Lernprogramm bauen Sie Ihren Server auf einem TensorFlow Serving ServerCore
, der einen AspiredVersionsManager
intern 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()
einen ServerCore :: Options-Parameter. Hier sind einige häufig verwendete Optionen:
-
ModelServerConfig
, der die zu ladenden Modelle angibt. Modelle werden entweder übermodel_config_list
deklariert, das eine statische Liste von Modellen deklariert, oder übercustom_model_config
, das eine benutzerdefinierte Methode zumcustom_model_config
einer Liste von Modellen definiert, die zur Laufzeit aktualisiert werden können. -
PlatformConfigMap
, die vom Namen der Plattform (z. B.tensorflow
) derPlatformConfig
, mit der derSourceAdapter
.SourceAdapter
passtStoragePath
(den Pfad, in dem eine ModellversionStoragePath
wird) an ModelLoader
(lädt die Modellversion aus dem Speicherpfad und stellt demManager
SourceAdapter
StoragePath
). WennPlatformConfig
SavedModelBundleSourceAdapterConfig
enthält, wird einSavedModelBundleSourceAdapter
erstellt, den wir später erläutern werden.
SavedModelBundle
ist eine Schlüsselkomponente von TensorFlow Serving. Es stellt ein TensorFlow-Modell dar, das aus einem bestimmten Pfad geladen wurde, und bietet dieselbe Session::Run
Schnittstelle wie TensorFlow, um Inferenz auszuführen. SavedModelBundleSourceAdapter
passt den Speicherpfad an Loader<SavedModelBundle>
sodass die Modelllebensdauer vom Manager
verwaltet werden kann. Bitte beachten Sie, dass SavedModelBundle
der Nachfolger des veralteten SessionBundle
. Benutzer werden aufgefordert, SavedModelBundle
zu verwenden, da die Unterstützung für SessionBundle
bald entfernt wird.
Mit all diesen Funktionen führt ServerCore
intern Folgendes aus:
- Instanziiert eine
FileSystemStoragePathSource
, die die inmodel_config_list
deklariertenmodel_config_list
. -
SourceAdapter
einenSourceAdapter
mithilfe derPlatformConfigMap
mit der inmodel_config_list
deklariertenmodel_config_list
und verbindet dieFileSystemStoragePathSource
damit. Auf diese Weise passt derSavedModelBundleSourceAdapter
, wenn eine neue Modellversion unter demSavedModelBundleSourceAdapter
diese an einenLoader<SavedModelBundle>
. - Instanziiert eine bestimmte Implementierung von
Manager
namensAspiredVersionsManager
, die alle vomSavedModelBundleSourceAdapter
erstelltenLoader
InstanzenSavedModelBundleSourceAdapter
.ServerCore
exportiert dieManager
Oberfläche, indem die Aufrufe anAspiredVersionsManager
.
Immer wenn eine neue Version verfügbar ist, lädt dieser AspiredVersionsManager
die neue Version und entlädt unter seinem Standardverhalten die alte. Wenn Sie mit dem Anpassen beginnen möchten, sollten Sie die intern erstellten Komponenten und deren Konfiguration verstehen.
Es ist erwähnenswert, dass TensorFlow Serving von Grund auf neu entwickelt wurde, um sehr flexibel und erweiterbar zu sein. Sie können verschiedene Plugins erstellen, um das Systemverhalten anzupassen, und dabei allgemeine Kernkomponenten wie ServerCore
und AspiredVersionsManager
. Sie können beispielsweise ein Datenquellen-Plugin erstellen, das den Cloud-Speicher anstelle des lokalen Speichers überwacht, oder Sie können ein Versionsrichtlinien-Plugin erstellen, das den Versionsübergang auf andere Weise ausführt. Sie können sogar ein benutzerdefiniertes Modell-Plugin erstellen, das dient Nicht-TensorFlow-Modelle. Diese Themen sind für dieses Lernprogramm nicht relevant. Weitere Informationen finden Sie jedoch in der benutzerdefinierten Quelle und in den benutzerdefinierten Tutorials.
Batching
Eine weitere typische Serverfunktion, die wir in einer Produktionsumgebung benötigen, ist das Batching. Moderne Hardwarebeschleuniger (GPUs usw.), die für Inferenzen beim maschinellen Lernen verwendet werden, erzielen normalerweise die beste Berechnungseffizienz, wenn Inferenzanforderungen in großen Stapeln ausgeführt werden.
Die Stapelverarbeitung kann aktiviert werden, SessionBundleConfig
beim Erstellen des SavedModelBundleSourceAdapter
die richtige SessionBundleConfig
SavedModelBundleSourceAdapter
. In diesem Fall setzen wir die BatchingParameters
auf ziemlich viele Standardwerte. Die Stapelverarbeitung kann durch Festlegen von benutzerdefinierten Werten für Zeitlimit, Stapelgröße usw. verfeinert werden. Einzelheiten finden Sie unter 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;
Bei Erreichen des vollständigen Stapels werden Inferenzanforderungen intern zu einer einzigen großen Anforderung (Tensor) zusammengeführt, und tensorflow::Session::Run()
wird aufgerufen (daher kommt der tatsächliche Effizienzgewinn bei GPUs).
Mit Manager servieren
Wie oben erwähnt, ist TensorFlow Serving Manager
als generische Komponente konzipiert, die das Laden, Servieren, Entladen und den Versionsübergang von Modellen übernimmt, die von beliebigen maschinellen Lernsystemen generiert werden. Die APIs basieren auf den folgenden Schlüsselkonzepten:
Servable : Servable ist ein undurchsichtiges Objekt, mit dem Clientanforderungen bearbeitet werden können. Die Größe und Granularität eines Servables ist flexibel, sodass ein einzelnes Servable alles umfassen kann, von einem einzelnen Shard einer Nachschlagetabelle über ein einzelnes maschinell erlerntes Modell bis hin zu einem Tupel von Modellen. Ein Servable kann von jedem Typ und jeder Schnittstelle sein.
Servable-Version : Servables sind versioniert und TensorFlow Serving
Manager
kann eine oder mehrere Versionen eines Servables verwalten. Durch die Versionierung können mehrere Versionen eines Servables gleichzeitig geladen werden, was ein schrittweises Rollout und Experimentieren unterstützt.Servable Stream : Ein Servable Stream ist die Folge von Versionen eines Servable mit zunehmenden Versionsnummern.
Modell : Ein maschinell erlerntes Modell wird durch ein oder mehrere Servables dargestellt. Beispiele für Servables sind:
- TensorFlow-Sitzung oder Wrapper um sie herum, z. B.
SavedModelBundle
. - Andere Arten von maschinell erlernten Modellen.
- Vokabeltabellen.
- Nachschlagen von Nachschlagetabellen.
Ein zusammengesetztes Modell kann als mehrere unabhängige Servables oder als ein einzelnes zusammengesetztes Servable dargestellt werden. Ein Servable kann auch einem Bruchteil eines Modells entsprechen, z. B. mit einer großen Nachschlagetabelle, die über viele
Manager
Instanzen verteilt ist.- TensorFlow-Sitzung oder Wrapper um sie herum, z. B.
Um all dies in den Kontext dieses Tutorials zu stellen:
TensorFlow-Modelle werden durch eine Art von Service dargestellt -
SavedModelBundle
.SavedModelBundle
besteht intern aus einemtensorflow:Session
gepaart mit einigen Metadaten darüber, welches Diagramm in die Sitzung geladen wird und wie es zur Inferenz ausgeführt wird.Es gibt ein Dateisystemverzeichnis, das einen Stream von TensorFlow-Exporten enthält, die sich jeweils in einem eigenen Unterverzeichnis befinden, dessen Name eine Versionsnummer ist. Das äußere Verzeichnis kann als serialisierte Darstellung des bedienbaren Streams für das zu bedienende TensorFlow-Modell betrachtet werden. Jeder Export entspricht einem Servables, das geladen werden kann.
AspiredVersionsManager
überwacht den Exportstrom und verwaltet den Lebenszyklus allerSavedModelBundle
Servables dynamisch.
TensorflowPredictImpl::Predict
dann einfach TensorflowPredictImpl::Predict
:
- Fordert
SavedModelBundle
vom Manager an (über ServerCore). - Verwendet die
generic signatures
, um logischePredictRequest
inPredictRequest
realenPredictRequest
und Werte an Tensoren zu binden. - Läuft Inferenz.
Testen Sie den Server und führen Sie ihn aus
Kopieren Sie die erste Version des Exports in den überwachten Ordner:
mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored
Starten Sie dann den Server:
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 &
Der Server sendet jede Sekunde Protokollnachrichten mit der Aufschrift "Aspiring version for servable ...". Dies bedeutet, dass er den Export gefunden hat und seinen Fortbestand verfolgt.
Lassen Sie uns den Client mit --concurrency=10
. Dadurch werden gleichzeitige Anforderungen an den Server gesendet und somit Ihre Stapellogik ausgelöst.
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
Was zu einer Ausgabe führt, die wie folgt aussieht:
...
Inference error rate: 13.1%
Dann kopieren wir die zweite Version des Exports in den überwachten Ordner und führen den Test erneut aus:
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
Was zu einer Ausgabe führt, die wie folgt aussieht:
...
Inference error rate: 9.5%
Dies bestätigt, dass Ihr Server die neue Version automatisch erkennt und zum Servieren verwendet!