最小工作示例张量流服务客户端

MInimum working example tensorflow serving client

本文关键字:张量流 服务 客户端 工作      更新时间:2023-10-16

我正在研究基本的Tensorflow Serve示例。我遵循 MNIST 示例,除了我想使用 numpy 数组来预测另一个numpy 数组而不是分类。

为此,我首先训练了我的神经网络。

x = tf.placeholder("float", [None, n_input],name ="input_values")
weights = {
'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
'encoder_h3': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_3])),
'decoder_h1': tf.Variable(tf.random_normal([n_hidden_3, n_hidden_2])),
'decoder_h2': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
'decoder_h3': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
'encoder_b3': tf.Variable(tf.random_normal([n_hidden_3])),
'decoder_b1': tf.Variable(tf.random_normal([n_hidden_2])),
'decoder_b2': tf.Variable(tf.random_normal([n_hidden_1])),
'decoder_b3': tf.Variable(tf.random_normal([n_input])),
}
# Building the encoder
def encoder(x):
# Encoder Hidden layer with sigmoid activation #1
layer_1 = tf.nn.tanh(tf.matmul(x, weights['encoder_h1'])+biases['encoder_b1'])
print(layer_1.shape)
# Decoder Hidden layer with sigmoid activation #2
layer_2 = tf.nn.tanh(tf.matmul(layer_1, weights['encoder_h2'])+biases['encoder_b2'])
print(layer_2.shape)
# Layer 3
layer_3 = tf.nn.tanh(tf.matmul(layer_2, weights['encoder_h3'])+biases['encoder_b3'])
print(layer_3.shape)
return layer_3

# Building the decoder
def decoder(x):
# Encoder Hidden layer with sigmoid activation #1
layer_1 = tf.nn.tanh(tf.matmul(x, weights['decoder_h1'])+biases['decoder_b1'])
print(layer_1.shape)
# Decoder Hidden layer with sigmoid activation #2
layer_2 = tf.nn.tanh(tf.matmul(layer_1, weights['decoder_h2'])+biases['decoder_b2'])
# Layer 3
layer_3 = tf.nn.tanh(tf.matmul(layer_2, weights['decoder_h3'])+biases['decoder_b3'])
return layer_3
# Construct model
encoder_op = encoder(x)
decoder_op = decoder(encoder_op)
# Prediction
y = decoder_op

# Objective functions
y_ = tf.placeholder("float", [None,n_input],name="predict")

接下来,正如有人在这里建议的那样,我保存了这样的网络。

import os
import sys
from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import utils
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import     build_signature_def, predict_signature_def
from tensorflow.contrib.session_bundle import exporter
with tf.Session() as sess:
# Initialize variables
sess.run(init)
# Restore model weights from previously saved model
saver.restore(sess, model_path)
print("Model restored from file: %s" % save_path)
export_path = '/tmp/AE_model/6'
print('Exporting trained model to', export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)

signature = predict_signature_def(inputs={'inputs': x},
outputs={'outputs': y})
builder.add_meta_graph_and_variables(sess=sess,
tags=[tag_constants.SERVING],
signature_def_map={'predict': signature})
builder.save()

print 'Done exporting!'

接下来,我按照说明在本地主机上运行我的服务器:9000

bazel build //tensorflow_serving/model_servers:tensorflow_model_server

我设置了服务器

bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_base_path=/tmp/AE_model/

问题所在

现在我想编写一个程序,这样我就可以将 Mat 向量从 eclipse 中的C++程序(我使用了很多库(传递到我的服务器,这样我就可以做出某种预测。

我首先想到使用 inception_client.cc 作为参考。但是,似乎我需要 Bazel 来编译它,因为我在任何地方都找不到 prediction_service.grpc.pb.h :(

所以似乎我唯一的其他选择是使用 python 调用脚本,我得到以下输出:

<grpc.beta._client_adaptations._Rendezvous object at 0x7f9bcf8cb850>

任何有关此问题的帮助将不胜感激。

谢谢。

编辑:

我重新安装了protobuf和grpc,并按照建议运行命令:

我的命令有点不同,我不得不在我的服务文件夹之外使用它(在 Ubuntu 14.04 中(。

sudo protoc -I=serving -I serving/tensorflow --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` serving/tensorflow_serving/apis/*.proto

这生成了.gprc.pb.h文件,我将它们拖到/apis/文件夹中,错误消失了。现在我收到错误

/tensorflow/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:1:42: fatal error: unsupported/Eigen/CXX11/Tensor: No such file or directory

即使此文件确实存在。任何建议不胜感激。

谢谢@subzero!

编辑 2

我能够通过更新到最新的特征版本并从源代码构建来解决 Eigen 的问题。接下来我指向/usr/local/include/eigen3/

之后,我在使用张量流库时遇到了问题。这些问题我通过使用lababidi的建议生成libtensorflow_cc.so库来解决。 https://github.com/tensorflow/tensorflow/issues/2412

我还有最后一个问题。一切似乎都很好,除了我收到错误:

undefined reference to 'tensorflow::serving::P redictRequest::~PredictRequest(('

似乎我缺少链接器或库。有谁知道我错过了什么???

自定义客户端和服务器的示例:

要添加到 TensorFlow 模型的服务器代码:

import grpc
from concurrent import futures
import python_pb2
import python_pb2_grpc
class PythonServicer(python_pb2_grpc.PythonServicer):

def makePredictions(self, request, context):

items = eval(str(request.items)) #Receives the input values for the model as a string and evaluates them into an array to be passed to tensorflow
x_feed = items
targetEval_out = sess.run(confidences, feed_dict={x:x_feed}) #"confidences" is the output of my model, replace it for the appropriate function from your model

out = str(targetEval_out.tolist()) #The model output is then put into string format to be passed back to the client. It has to be reformatted on the other end, but this method was easier to implement
return python_pb2.value(name=out)

print("server online")
MAX_MESSAGE_LENGTH = 4 * 1024 * 1024 #can be edited to allow for larger amount of data to be transmitted per message. This can be helpful for making large numbers of predictions at once.
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), 
options=[('grpc.max_send_message_length', MAX_MESSAGE_LENGTH), (
'grpc.max_receive_message_length', MAX_MESSAGE_LENGTH)])
python_pb2_grpc.add_PythonServicer_to_server(
PythonServicer(), server)
server.add_insecure_port('[::]:50051')
server.start()

客户端C++代码:

#include <grpc/grpc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include "python.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::ClientReader;
using grpc::ClientReaderWriter;
using grpc::ClientWriter;
using grpc::Status;
using python::request;
using python::value;
using python::Python;
using namespace std;

unsigned MAX_MESSAGE_LENGTH = 4 * 1024 * 1024; //can be edited to allow for larger amount of data to be transmitted per message. This can be helpful for making large numbers of predictions at once.
grpc::ChannelArguments channel_args;
channel_args.SetMaxReceiveMessageSize(MAX_MESSAGE_LENGTH);
channel_args.SetMaxSendMessageSize(MAX_MESSAGE_LENGTH);
shared_ptr<Channel> channel = CreateCustomChannel("localhost:50051", grpc::InsecureChannelCredentials(),channel_args);
unique_ptr<python::Python::Stub>stub = python::Python::NewStub(channel);
request r;
r.set_items(dataInputString); //The input data should be a string that can be parsed to a python array, for example "[[1.0,2.0,3.0],[4.0,5.0,6.0]]"
//The server code was made to be able to make multiple predictions at once, hence the multiple data arrays 
value val;
ClientContext context;
Status status = stub->makePredictions(&context, r, &val);
cout << val.name() << "n"; //This prints the returned model prediction

python.proto 代码:

syntax = "proto3";

package python;
service Python {
rpc makePredictions(request) returns (value) {}

}
message request {
string items = 1;
}

message value {
string name = 1;
}

我不确定这些代码片段是否独立工作,因为我刚刚从当前项目中复制了相关代码。但希望这对于任何需要 tensorflow 客户端和服务器的人来说都是一个很好的起点。

您要查找的pb.h文件是通过在此文件上运行protc生成的。

您可以按照此处描述的说明生成头文件并自行使用它。 在任何情况下,您运行的巴塞尔构建都应该在构建目录中生成此文件,您可以将 eclipse 项目设置为使用这些包含路径来编译 C 客户端。

它不是C++,也不是你要找的,但我们这里有一个预测客户端,如果你愿意,你可以使用它。

https://github.com/epigramai/tfserving_predict_client/

https://github.com/tobegit3hub/tensorflow_template_application,它基于这里的代码,我认为可能有一个C++客户端可以在那里使用。