Maison > Article > développement back-end > Déploiement du modèle d'environnement produit, image Docker, espace de travail Bazel, modèle d'export, serveur, client
Déploiement du modèle d'environnement produit, création d'une application Web simple, les utilisateurs téléchargent des images, exécutent le modèle Inception et réalisent une classification automatique des images.
Créez un environnement de développement de services TensorFlow. Installez Docker, . Utilisez le fichier de configuration pour créer une image Docker localement, docker build --pull -t $USER/tensorflow-serving-devel . Pour exécuter le conteneur sur l'image, docker run -v $HOME:/mnt/home -p 9999:9999 -it $USER/tensorflow-serving-devel , chargez-le dans le chemin conteneur/mnt/home dans le répertoire personnel, et travailler dans le terminal. Utilisez un IDE ou un éditeur pour modifier le code, utilisez le conteneur pour exécuter l'outil de construction et l'hôte est accessible via le port 9999 pour créer le serveur. La commande exit quitte le terminal conteneur et arrête de s'exécuter.
Le programme de service TensorFlow est écrit en C++ et utilise l'outil de construction Bazel de Google. Le conteneur exécute Bazel. Bazel gère les dépendances tierces au niveau du code. Bazel télécharge automatiquement la version. Le répertoire racine de la bibliothèque du projet définit le fichier WORKSPACE. La bibliothèque de modèles TensorFlow contient le code du modèle Inception.
Le service TensorFlow est inclus dans le projet en tant que sous-module Git. mkdir ~/serving_example, cd ~/serving_example, git init, git submodule add, tf_serving, git submodule update --init --recursive.
La règle local_repository du fichier WORKSPACE définit les dépendances tierces en tant que fichiers de stockage local. Le projet importe la règle tf_workspace pour initialiser les dépendances TensorFlow.
workspace(name = "serving")
local_repository(
name = "tf_serving",
) path = __workspace_dir__ + "/tf_serving",
)
local_repository(
name = "org_tensorflow",
path = __workspace_dir__ + "/tf_serving/tensorflow",
)
load('//tf_serving/tensorflow/tensorflow : workspace .bzl', 'tf_workspace')
tf_workspace("tf_serving/tensorflow/", "@org_tensorflow")
bind(
name = "libssl",
actual = "@ ennuyeuxssl_git //:ssl",
)
bind(
name = "zlib",
actual = "@zlib_archive//:zlib",
)
local_repository(
name = "inception_model",
path = __workspace_dir__ + "/tf_serving/tf_models/inception",
)
Exportez le modèle entraîné, exportez le diagramme de flux de données et variables , pour les produits. Le graphique de flux de données du modèle doit recevoir les entrées des espaces réservés et calculer la sortie en une seule étape d'inférence. Le modèle de création (ou le modèle de reconnaissance d'image en général), l'entrée de chaîne d'image codée JPEG, est différent de l'entrée de lecture du fichier TFRecord. Définissez l'espace réservé d'entrée, appelez la fonction pour convertir l'espace réservé pour représenter l'entrée externe au format d'entrée du modèle d'inférence d'origine, convertissez la chaîne d'image en un tenseur de pixels avec chaque composant situé entre [0, 1], redimensionnez la taille de l'image pour qu'elle corresponde la largeur et la hauteur attendues du modèle, la valeur du pixel est transformée en l'intervalle requis par le modèle [-1, 1]. Appelez la méthode d'inférence du modèle d'origine et déduisez les résultats en fonction de l'entrée transformée.
Attribuez des valeurs à chaque paramètre de la méthode d'inférence. Restaurez les valeurs des paramètres à partir du point de contrôle. Enregistrez périodiquement les fichiers de points de contrôle de formation du modèle, qui contiennent les paramètres d'apprentissage. Le dernier fichier de point de contrôle de formation enregistré contient les derniers paramètres de modèle mis à jour. Allez télécharger le fichier de point de contrôle pré-entraînement : . Dans le conteneur Docker, cd /tmp, curl -0 , tar -xzf inception-v3-2016-03-01.tar.gz.
La classe tensorflow_serving.session_bundle.exporter.Exporter exporte le modèle. Transmettez l'instance de sauvegarde pour créer l'instance et utilisez exporter.classification_signature pour créer la signature du modèle. Spécifiez input_tensor et le tenseur de sortie. classes_tensor contient une liste de noms de classes de sortie et le modèle attribue à chaque catégorie un score (ou probabilité) socres_tensor. Pour les modèles avec plusieurs catégories, la configuration spécifie que seul tf.nntop_k sera renvoyé pour sélectionner les catégories et que les scores d'allocation de modèle seront triés dans les K premières catégories par ordre décroissant. Appelez la signature de la méthode exporter.Exporter.init. La méthode d'exportation exporte le modèle et reçoit le chemin de sortie, le numéro de version du modèle et l'objet de session. La classe Exporter génère automatiquement du code comportant des dépendances et le conteneur Doker utilise Bazel pour exécuter l'exportateur. Le code est enregistré dans l'espace de travail bazel exporter.py.
temps d'importation
import sys
import tensorflow as tf
from tensorflow_serving.session_bundle import exporter
from inception import inception_model
NUM_CLASSES_TO_RETURN = 10
def convert_external_inputs(external_x):
image = tf.image.convert_image_dtype(tf.image.decode_jpeg(external_x, canaux=3), tf.float32)
images = tf.image.resize_bilinear(tf .expand_dims(image, 0), [299, 299])
images = tf.mul(tf.sub(images, 0.5), 2)
return images
def inference(images) :
logits, _ = inception_model.inference(images, 1001)
return logits
external_x = tf.placeholder(tf.string)
= inference(x)
saver = tf.train.Saver()
avec tf.Session() comme session :
ckpt = tf.train.get_checkpoint_state(sys.argv[1])
if ckpt et ckpt.model_checkpoint_path:
saver.restore(sess, sys.argv[1] + "/" + ckpt.model_checkpoint_path)
else:
print("Fichier de point de contrôle introuvable")
augmenter SystemExit
scores, class_ids = tf.nn.top_k(y, NUM_CLASSES_TO_RETURN)
classes = tf.contrib.lookup.index_to_string(tf.to_int64(class_ids),
mapping=tf .constant([str(i) for i in range(1001)]))
model_exporter = exporter.Exporter(saver)
signature = exporter.classification_signature(
input_tensor=external_x, classes_tensor= classes, scores_tensor=scores)
model_exporter.init(default_graph_signature=signature, init_op=tf.initialize_all_tables())
model_exporter.export(sys.argv[1] + "/export", tf.constant(time. time()), sess)
一个构建规则BUILD文件。在容器命令运行导出器,cd /mnt/home/serving_example, hazel run:export /tmp/inception-v3 ,依据/tmp/inception -v3提到的检查点文件在/tmp/inception-v3/{currenttimestamp}/创建导出器。首次运行要对TensorFlow编译。load avec protobuf库,导入cc_proto_library est disponible pour le proto.通过命令bazel run :server 9999 /tmp/inception-v3/export/{timestamp},容器运行推断服务器。
py_binary(
name = "export",
srcs = [
"export.py",
],
deps = [
"@tf_serving//tensorflow_serving/session_bundle:exporter",
"@org_tensorflow//tens orflow:tensorflow_py",
" @inception_model//inception",
],
)
load("@protobuf//:protobuf.bzl", "cc_proto_library")
cc_proto_library(
name="classification_service_proto",
srcs=["classification_service.proto"],
cc_libs = ["@protobuf//:protobuf"],
protoc="@protobuf//:protoc",
default_runtime="@protobuf//:protobuf",
use_grpc_plugin=1
)
cc_binary(
name = "server",
srcs = 🎜> " server.cc",
],
deps = [
":classification_service_proto",
"@tf_serving//tensorflow_serving/servables/tensorflow:session_bundle_factory",
"@grpc// : grpc++",
],
)
// octets d'entrée = 1;
float petalWidth = 1;
float petalHeight = 2;
float sepalWidth = 3;
float sepalHeight = 4;
};
classes ClassificationClass répétées = 1;
};
Classe de classification des messages {
> >
Implémentez le serveur d'inférence. Chargez le modèle exporté, appelez la méthode d'inférence et implémentez ClassificationService::Service. Exportez le modèle, créez un objet SessionBundle, incluez un objet de session TF de graphique de flux de données entièrement chargé et définissez les métadonnées de signature de classification de l'outil d'exportation. La classe SessionBundleFactory crée un objet SessionBundle, le configure pour charger le modèle d'exportation au chemin spécifié par pathToExportFiles et renvoie un pointeur unique vers l'instance SessionBundle créée. Définissez ClassificationServiceImpl et recevez les paramètres d'instance SessionBundle.
Chargez la signature de classification, la fonction GetClassificationSignature charge les métadonnées d'exportation du modèle ClassificationSignature, la signature spécifie le nom logique du tenseur d'entrée du nom réel de l'image reçue et le résultat de l'inférence de mappage du nom logique du tenseur de sortie du graphique de flux de données . Transformez l'entrée protobuf en un tenseur d'entrée d'inférence et le paramètre de requête copie la chaîne d'image codée en JPEG dans le tenseur d'inférence. Pour exécuter l'inférence, sessionbundle obtient l'objet de session TF, l'exécute une fois et transmet l'inférence du tenseur d'entrée et de sortie. Le tenseur de sortie déduit transforme la sortie protobuf et le résultat du tenseur de sortie est copié dans le message ClassificationResponse et formaté avec les paramètres de sortie de réponse dans la forme spécifiée. Configurez le serveur gRPC, configurez l'objet SessionBundle et créez l'exemple de code de l'instance ClassificationServiceImpl.
#include
#include
#include
#include "classification_service.grpc.pb.h"
#include "tensorflow_serving/servables/tensorflow/session_bundle_factory.h"
en utilisant l'espace de noms std ;
en utilisant l'espace de noms tensorflow : servir;en utilisant l'espace de noms grpc;
unique_ptr
class ClassificationServiceImpl final: public ClassificationService::Service {
private:
unique_ptr
public:
sessionBundle(move(sessionBundle)) {};
Réponse ClassificationResponse*) remplace {
const tensorflow::Status signatureStatus =
GetClassificationSignature(sessionBundle->meta_graph_def, &signature);
if (!signatureStatus.ok()) {
Return Status( StatusCode : :INTERNAL, signatureStatus.error_message());
tensorflow::Tensor input(tensorflow::DT_STRING, tensorflow::TensorShape()); );
const tensorflow::Status inferenceStatus = sessionBundle->session->Run(
if (!inferenceStatus.ok()) {
return Status(StatusCode::INTERNAL, inferenceStatus.error_message());
for (int i = 0; i < outputs[0].NumElements(); ++i) {
ClassificationClass *classificationClass = response->add_classes();
classificationClass->set_name(outputs[0].flat
classificationClass->set_score(outputs[1].flat
}
return Status::OK;
}
};
int main(int argc, char** argv) {
if (argc < 3) {
cerr << "Usage: server
return 1;
}
const string serverAddress(string("0.0.0.0:") + argv[1]);
const string pathToExportFiles(argv[2]);
unique_ptr
ClassificationServiceImpl classificationServiceImpl(move(sessionBundle));
ServerBuilder builder;
builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
builder.RegisterService(&classificationServiceImpl);
unique_ptr
cout << "Server listening on " << serverAddress << endl;
server->Wait();
return 0;
}
通过服务器端组件从webapp访问推断服务。运行Python protocol buffer编译器,生成ClassificationService Python protocol buffer客户端:pip install grpcio cython grpcio-tools, python -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. classification_service.proto。生成包含调用服务stub classification_service_pb2.py 。服务器接到POST请求,解析发送表单,创建ClassificationRequest对象 。分类服务器设置一个channel,请求提交,分类响应渲染HTML,送回用户。容器外部命令python client.py,运行服务器。浏览器导航http://localhost:8080 访问UI。
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import cgi
import classification_service_pb2
from grpc.beta import implementations
class ClientApp(BaseHTTPRequestHandler):
def do_GET(self):
self.respond_form()
def respond_form(self, response=""):
form = """
réponse = formulaire % réponse
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-length", len(response))
self.end_headers( )
self.wfile.write(response)
def do_POST(self):
form = cgi.FieldStorage(
fp=self.rfile,
en-têtes= self.headers,
environ={
'REQUEST_METHOD': 'POST',
'CONTENT_TYPE': self.headers['Content-Type'],
})
request = classification_service_pb2.ClassificationRequest()
request.input = form['file'].file.read()
channel = Implementations.insecure_channel("127.0.0.1", 9999)
stub = classification_service_pb2.beta_create_ClassificationService_stub(channel)
réponse = stub.classify(request, 10) # Délai d'expiration de 10 secondes
self.respond_form("
if __name__ == '__main__':
host_port = ('0.0.0.0', 8080)
print "Serving in %s:%s" % host_port
HTTPServer (host_port, ClientApp).serve_forever()理所有临时构建文件。容器中,mkdir /opt/classification_server, cd / mnt/home/serving_example, cp -R bazel-bin/. /opt/classification_server, bazel clean.图像推送到自己偏好docker服务云,服务。
参考资料:
《面向机器智能的TensorFlow实践》
欢迎付费咨询(150元每小时),我的微信:qingxingfengzi
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!