Aide à protéger la Grande barrière de corail avec tensorflow sur Kaggle Rejoignez Défi

Création d'un serveur de modèle TensorFlow standard

Ce didacticiel vous montre comment utiliser les composants TensorFlow Serving pour créer le TensorFlow ModelServer standard qui découvre et sert de manière dynamique les nouvelles versions d'un modèle TensorFlow formé. Si vous voulez juste utiliser le serveur standard pour servir vos modèles, voir tensorflow service tutoriel de base .

Ce didacticiel utilise le modèle de régression Softmax simple introduit dans le didacticiel TensorFlow pour la classification des images manuscrites (données MNIST). Si vous ne savez pas ce que tensorflow ou MNIST est, consultez le MNIST Pour ML débutants tutoriel.

Le code de ce tutoriel se compose de deux parties :

  • Un fichier Python mnist_saved_model.py que les trains et les exportations multiples versions du modèle.

  • Fichier d'un C de main.cc qui est la norme tensorflow ModelServer qui découvre de nouveaux modèles exportés et gère un GRPC service pour les servir.

Ce didacticiel décrit les tâches suivantes :

  1. Entraînez et exportez un modèle TensorFlow.
  2. Gérer modèle avec versioning tensorflow service ServerCore .
  3. Configurer à l' aide batching SavedModelBundleSourceAdapterConfig .
  4. Servir demande avec tensorflow service ServerCore .
  5. Exécutez et testez le service.

Avant de commencer, d' abord installer Docker

Entraîner et exporter le modèle TensorFlow

Tout d'abord, si vous ne l'avez pas encore fait, clonez ce dépôt sur votre machine locale :

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

Effacez le répertoire d'exportation s'il existe déjà :

rm -rf /tmp/models

Entraînez (avec 100 itérations) et exportez la première version du modèle :

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

Entraînez (avec 2000 itérations) et exportez la deuxième version du modèle :

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

Comme vous pouvez le voir dans mnist_saved_model.py , la formation et l' exportation se fait de la même manière , il est dans le tensorflow service tutoriel de base . À des fins de démonstration, vous composez intentionnellement les itérations d'entraînement pour la première exécution et l'exportez en tant que v1, tout en l'entraînant normalement pour la deuxième exécution et en l'exportant en tant que v2 vers le même répertoire parent - comme nous nous attendons à ce que ce dernier obtienne meilleure précision de classification grâce à un entraînement plus intensif. Vous devriez voir les données de formation pour chaque cycle de formation dans votre /tmp/mnist répertoire:

$ ls /tmp/mnist
1  2

Cœur du serveur

Imaginez maintenant que v1 et v2 du modèle sont générés dynamiquement au moment de l'exécution, alors que de nouveaux algorithmes sont expérimentés ou que le modèle est entraîné avec un nouvel ensemble de données. Dans un environnement de production, vous souhaiterez peut-être créer un serveur capable de prendre en charge un déploiement progressif, dans lequel v2 peut être découvert, chargé, expérimenté, surveillé ou annulé tout en servant v1. Vous pouvez également supprimer la v1 avant de lancer la v2. TensorFlow Serving prend en charge les deux options : alors que l'une est bonne pour maintenir la disponibilité pendant la transition, l'autre est bonne pour minimiser l'utilisation des ressources (par exemple, la RAM).

Au service tensorflow Manager fait exactement cela. Il gère le cycle de vie complet des modèles TensorFlow, y compris leur chargement, leur service et leur déchargement, ainsi que les transitions de version. Dans ce tutoriel, vous allez construire votre serveur sur un service tensorflow ServerCore , qui enveloppe interne une 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() prend un paramètre ServerCore :: Options. Voici quelques options couramment utilisées :

  • ModelServerConfig qui spécifie les modèles à charger. Les modèles sont déclarés soit par model_config_list , qui déclare une liste statique des modèles, ou par custom_model_config , qui définit une manière personnalisée de déclarer une liste de modèles qui peuvent se mis à jour lors de l' exécution.
  • PlatformConfigMap qui mappe du nom de la plate - forme (comme tensorflow ) au PlatformConfig , qui est utilisé pour créer le SourceAdapter . SourceAdapter adapte StoragePath (le chemin où une version du modèle est découverte) pour modéliser Loader (charge la version du modèle de chemin de stockage et fournit des interfaces de transition d'état au Manager ). Si PlatformConfig contient SavedModelBundleSourceAdapterConfig , un SavedModelBundleSourceAdapter sera créé, que nous expliquerons plus tard.

SavedModelBundle est un élément clé de tensorflow Serving. Il représente un modèle tensorflow chargé à partir d' un chemin donné et fournit la même Session::Run interface comme tensorflow à l' inférence de l' exécution. SavedModelBundleSourceAdapter chemin de stockage à Loader<SavedModelBundle> de sorte que la durée de vie modèle peut être géré par Manager . S'il vous plaît noter que SavedModelBundle est le successeur de dépréciée SessionBundle . Les utilisateurs sont encouragés à utiliser SavedModelBundle comme support de SessionBundle sera bientôt supprimé.

Avec tout cela, ServerCore fait en interne ce qui suit:

  • Instancie un FileSystemStoragePathSource qui surveille les trajectoires d'exportation de modèles déclarés dans model_config_list .
  • Instancier un SourceAdapter en utilisant la PlatformConfigMap avec la plate - forme de modèle déclaré dans model_config_list et relie le FileSystemStoragePathSource à lui. De cette façon, chaque fois qu'une nouvelle version du modèle est découvert sous le chemin d'exportation, le SavedModelBundleSourceAdapter adapte à un Loader<SavedModelBundle> .
  • Instantiates une implémentation spécifique du Manager appelé AspiredVersionsManager qui gère tous ces Loader instances créées par le SavedModelBundleSourceAdapter . ServerCore exporte le Manager de l' interface en déléguant les appels à AspiredVersionsManager .

Chaque fois qu'une nouvelle version est disponible, cette AspiredVersionsManager charge la nouvelle version, et sous son comportement par défaut déchargements l'ancien. Si vous souhaitez commencer à personnaliser, vous êtes encouragé à comprendre les composants qu'il crée en interne et comment les configurer.

Il convient de mentionner que TensorFlow Serving est conçu à partir de zéro pour être très flexible et extensible. Vous pouvez construire différents plugins pour personnaliser le comportement du système, tout en tirant parti des composants génériques de base comme ServerCore et AspiredVersionsManager . Par exemple, vous pouvez créer un plug-in de source de données qui surveille le stockage cloud au lieu du stockage local, ou vous pouvez créer un plug-in de politique de version qui effectue la transition de version d'une manière différente. En fait, vous pouvez même créer un plug-in de modèle personnalisé qui sert modèles non TensorFlow. Ces sujets sont hors de portée de ce didacticiel. Cependant, vous pouvez vous référer à la source sur mesure et personnalisée diffusables tutoriels pour plus d' informations.

Mise en lots

Une autre fonctionnalité de serveur typique que nous voulons dans un environnement de production est le traitement par lots. Les accélérateurs matériels modernes (GPU, etc.) utilisés pour faire de l'inférence d'apprentissage automatique atteignent généralement la meilleure efficacité de calcul lorsque les demandes d'inférence sont exécutées en lots importants.

Batching peut être activée en fournissant une bonne SessionBundleConfig lors de la création du SavedModelBundleSourceAdapter . Dans ce cas , nous avons mis les BatchingParameters avec à peu près les valeurs par défaut. Le traitement par lots peut être affiné en définissant des valeurs de délai d'attente personnalisées, batch_size, etc. Pour plus de détails, s'il vous plaît se référer à 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;

Après avoir atteint lot complet, les demandes d'inférence sont fusionnées à l' intérieur en une seule grande demande (tenseur) et tensorflow::Session::Run() est appelée (qui est l' endroit où le gain d'efficacité réelle sur les GPU vient).

Servir avec le gestionnaire

Comme mentionné ci - dessus, tensorflow service Manager est conçu pour être un composant générique qui peut gérer le chargement, le service, le déchargement et la transition de la version des modèles générés par les systèmes d'apprentissage machine arbitraires. Ses API sont construites autour des concepts clés suivants :

  • Diffusable: diffusable est un objet opaque qui peut être utilisé pour répondre à des demandes de clients. La taille et la granularité d'un servable sont flexibles, de sorte qu'un seul servable peut inclure n'importe quoi, d'un seul fragment d'une table de recherche à un seul modèle appris par machine à un tuple de modèles. Un serveur peut être de n'importe quel type et interface.

  • Diffusables Version: Servables sont versionnés et tensorflow service Manager peut gérer un ou plusieurs versions d'un diffusable. La gestion des versions permet de charger simultanément plusieurs versions d'un serveur, ce qui permet un déploiement et une expérimentation progressifs.

  • Diffusable Stream Un flux diffusable est la séquence de versions d'un diffusable, avec un nombre croissant de version.

  • Modèle: modèle appris machine-A est représenté par un ou plusieurs servables. Voici des exemples de servables :

    • Session de tensorflow ou emballages autour d' eux, comme SavedModelBundle .
    • D'autres types de modèles appris par machine.
    • Tables de recherche de vocabulaire.
    • Intégration de tables de recherche.

    Un modèle composite peut être représenté comme plusieurs servables indépendants ou comme un seul servable composite. Un diffusable peut également correspondre à une fraction d'un modèle, par exemple avec une grande table de recherche dans de nombreux fragmentées Manager des instances.

Pour mettre tout cela dans le contexte de ce tutoriel :

  • Modèles tensorflow sont représentés par une sorte de diffusable - SavedModelBundle . SavedModelBundle consiste en interne d'une tensorflow:Session jumelé avec des métadonnées sur ce graphique est chargé dans la session et comment l' exécuter pour l' inférence.

  • Il existe un répertoire de système de fichiers contenant un flux d'exportations TensorFlow, chacune dans son propre sous-répertoire dont le nom est un numéro de version. Le répertoire externe peut être considéré comme la représentation sérialisée du flux pouvant être servi pour le modèle TensorFlow servi. Chaque export correspond à un servables qui peut être chargé.

  • AspiredVersionsManager surveille le flux d'exportation, et gère le cycle de vie de tous les SavedModelBundle servables dynamiquement.

TensorflowPredictImpl::Predict puis juste:

  • Les demandes SavedModelBundle du gestionnaire (par ServerCore).
  • Utilise les generic signatures pour mapper les noms de tenseurs logiques dans PredictRequest à de vrais noms de tenseur et les valeurs se lient à tenseurs.
  • Exécute l'inférence.

Tester et exécuter le serveur

Copiez la première version de l'export dans le dossier surveillé :

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

Démarrez ensuite le serveur :

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 &

Le serveur émettra des messages de journal toutes les secondes indiquant « Aspiring version for servable ... », ce qui signifie qu'il a trouvé l'exportation et qu'il suit son existence.

Lançons le client avec --concurrency=10 . Cela enverra des requêtes simultanées au serveur et déclenchera ainsi votre logique de traitement par lots.

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

Ce qui donne une sortie qui ressemble à :

...
Inference error rate: 13.1%

Ensuite, nous copions la deuxième version de l'export dans le dossier surveillé et réexécutons le test :

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

Ce qui donne une sortie qui ressemble à :

...
Inference error rate: 9.5%

Cela confirme que votre serveur découvre automatiquement la nouvelle version et l'utilise pour servir !