赞
踩
基本思路:利用tensorflow官方提供的tensorflow serving进行部署,同时,为了免去环境配置等麻烦操作,可借助docker容器。
首先肯定要去租一个服务器,例如阿里云。一开始选了window server2012,结果很坑,装不了docker。上网想查解决方法,发现别人也遇到过这个问题。
了解的原因大概是:docker需要在linux的环境下运行。但通过在window server2012下使用vitural box运行linux虚拟机的办法不行,因为这样会造成二次虚拟(官方解释:阿里云给的轻量应用服务器是运行在虚拟机上的,所以不能再开虚拟机)。
不过网上一些大佬好像也给出了,但总之太过麻烦,不想去折腾,就没去尝试。骚操作
正当我觉得凉凉,想重新买linux服务器的时候,才发现阿里云的控制台上可以重新更改系统镜像,于是很愉快地换成了ubuntu18.04.
前提条件:Docker 要求 Ubuntu 系统的内核版本高于 3.10 ,通过 uname -r 命令查看你当前的内核版本。
接下来就是在linux终端敲命令了:
1.获取docker安装包
wget -qO- https://get.docker.com/ | sh
完成后会有一段提示
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
sudo usermod -aG docker runoob
Remember that you will have to log out and back in for this to take effect!
一般嫌麻烦的话,以后执行docker命令都在root下进行就可以了
2.运行docker容器
sudo service docker start
3.测试hello-world程序
docker run hello-world
第一次应该会失败,因为容器里还没有这个项目,所以docker会去下载,第二次运行就可以了。
1.拉取带tensorflow serving的docker镜像
docker pull tensorflow/serving
2.先来测试一下官方例子
- cd /root/software/
- git clone https://github.com/tensorflow/serving
将GitHub上的TensorFlow-serving拷贝下来,里面已经有一些模型,我们通过部署一个简单的模型上docker来观察结果
- docker run -p 8501:8501 \
- --mount type=bind,\
- source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu,\
- target=/models/half_plus_two \
- -e MODEL_NAME=half_plus_two -t tensorflow/serving &
运行成功后,我们写一个Python的代码测试
- import requests
- import json
- pdata={"instances":[1,2,3]}
- param=json.dumps(pdata)
- res=requests.post('http://localhost:8501/v1/models/half_plus_two:predict',data=param)
- print(res.text)
可以看到res返回的结果,对应的是我们输入的1,2,3,之后我们就利用这种方式传递图片或其他数据过去
- {
- "predictions": [2.5, 3.0, 3.5
- ]
- }
结果分析:
启动docker的时候,开启了8501端口,后面url通过该端口进行访问
参数source表示你模型存放的文件夹,如果你去找这个文件夹,你会发现里面模型存放的格式有些特别,后面我们要部署模型时也需要先转为这种类型
model_name是docker上模型的名称,在url上也可以看到
target是存放在docker上的路径
下面就开始部署我们自己的模型了
刚才第三步说过,要将模型导出为特殊的类型(有一个variables文件夹,同目录下一个pb模型,这个pb模型和之前的还不大一样)。
首先需要我们训练完模型后一个正常的checkpoint,转换的方法可以参考下面的做法
- import tensorflow as tf
- import numpy as np
-
- x = tf.placeholder(tf.float32, name='input_x')
- feed = np.random.rand(100)
- y = x + 1
-
- w = tf.Variable(0.)
- b = tf.Variable(0.)
-
- y_ = tf.add(tf.multiply(w, x), b)
-
- loss = tf.reduce_mean(tf.square(y-y_))
-
- optimizer = tf.train.GradientDescentOptimizer(0.2)
- train = optimizer.minimize(loss)
-
- init = tf.global_variables_initializer()
-
- saver = tf.train.Saver()
-
- with tf.Session() as sess:
- sess.run(init)
- for i in range(200):
- sess.run(train, feed_dict={x: feed})
- if i % 5 == 0:
- print(i, sess.run([w,b]))
-
- saver.save(sess, './linear/linear.ckpt')
-
- with tf.Session() as sess2:
- sess2.run(init)
- saver.restore(sess2, './linear/linear.ckpt')
-
- # 将训练好的模型保存在modelName下,版本为1,当然你的版本可以随便写
- builder = tf.saved_model.builder.SavedModelBuilder("./modelName/1")
-
- inputs = {
- # 注意,这里是你预测模型的时候需要传的参数,调用模型的时候,传参必须和这里一致
- # 这里的input_x就是模型里面定义的输入placeholder
- "input_x": tf.saved_model.utils.build_tensor_info(x)
- }
- outputs = {
- "output_y": tf.saved_model.utils.build_tensor_info(y),
- }
- prediction_signature = tf.saved_model.signature_def_utils.build_signature_def(
- inputs=inputs,
- outputs=outputs,
- method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME
- )
-
- builder.add_meta_graph_and_variables(
- sess2,
- [tf.saved_model.tag_constants.SERVING],
- {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: prediction_signature}
- )
- builder.save()
之后仿照样例模型,用docker运行这个模型就可以了,端口号、路径和模型名称什么的自定义即可,不冲突就行。
- docker run -p 8502:8501 \
- --mount type=bind,\source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/face/face2,\target=/models/face2 \
- -e MODEL_NAME=face2 -t tensorflow/serving &
一段测试代码,跟上面的有一点类似,具体什么参数看自己的模型
- import requests
- import numpy as np
- import json
- # json格式序列调整
- class NumpyEncoder(json.JSONEncoder):
- def default(self, obj):
- if isinstance(obj, np.ndarray):
- return obj.tolist()
- return json.JSONEncoder.default(self, obj)
- feature=np.array(range(128))
- param = {
- "instances":[
- #每一个大括号是一次请求,里面是每次请求的参数
- {
- "in":feature
- }
- ]
- }
- param = json.dumps(param, cls=NumpyEncoder)
-
- res = requests.post("http://localhost:8502/v1/models/face2:predict", data=param)
- # 根据自己设定的返回数据读取
- # softmax = json.loads(res2.text)["predictions"][0]
至此,大功告成。
PS:如果有多个模型需要部署,只需要修改本地端口号即可,不需要修改docker的端口号。(就是docker run命令的时候,只改第一个8501,不需要改第二个8501)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。