使用docker和tf serving搭建模型预测服务

使用docker和tf serving搭建模型预测服务

本篇主要介绍使用dockertensorflow serving搭建一个模型预测服务,通过RESTful API和gRPC请求预测(python)。在下一篇将介绍使用Python web框架Django + tfserving,搭建一个图像分类预测web服务。

一、准备工作

1.安装Docker CE

Docker CE的安装可以参考docker官方参考文档:install Docker CE
安装完成后,可以运行 $sudo docker run hello-world 测试是否安装成功,成功安装的情况下应该看到如下输出:
使用docker和tf serving搭建模型预测服务_第1张图片
docker安装完成后,在使用docker命令的时候需要使用sudo,这是因为docker守护进程绑定的是Unix socket,默认情况下Unix socket为root用户所有,其他用户想要访问需要使用sudo。如果希望不使用sudo,可以新建一个名为docker的用户组,并将当前用户添加到该用户组,这样docker守护进程启动的时候,会自动为docker用户组用户获取Unix socket的读写权限。

sudo groupadd docker # 创建docker用户组
sudo usermod -aG docker ${USER} # 将当前用户添加到docker组
sudo systemctl restart docker # 重启docker
su root 
su ${USER} # 切换或退出当前用户再登入生效

完成后可以运行$docker ps -a 查看效果。

2.保存模型

保存模型是将训练得到的tensorflow模型保存为可以用于tensorflow serving的模型文件,主要是通过GraphDef对象保存模型文件。相关详细说明和完整示例代码可以参考tensorflow模型保存与恢复(2) 使用SavedModel,可以直接使用simple_save方法保存,更简洁方便。保存模型的时候注意设置好input和output,使用tfserving预测的输入即是从input tensor输入到网络,一次前向传播完成后,得到output tensor,返回预测结果。

二、运行容器

1.获取tfserving 镜像

这一步是从docker仓库获取tensorflow serving的镜像,用于后面的预测。
docker pull tensorflow/serving
下载完成后,可以使用docker images命令查看镜像:
在这里插入图片描述

2.运行容器

上述准备工作完成后可以运行容器:

$ docker run -p 8501:8501 --name tfserving_testnet  --mount type=bind,source=/tmp/testnet,target=/models/testnet  -e MODEL_NAME=testnet -t tensorflow/serving &

上面的命令中:
(1)-p 8501:8501是端口映射,是将容器的8501端口映射到宿主机的8501端口,后面预测的时候使用该端口;
(2)-e MODEL_NAME=testnet 设置模型名称;
(3)--mount type=bind,source=/tmp/testnet,target=/models/testnet 是将宿主机的路径/tmp/testnet挂载到容器的/models/testnet下。/tmp/testnet是存放的是上述准备工作中保存的模型文件,‘testnet’是模型名称,包含一个.pb文件和一个variables文件夹,在/tmp/testnet下新建一个以数字命名的文件夹,如100001,并将模型文件放到该文件夹中。容器内部会根据绑定的路径读取模型文件;
(4)-t tensorflow/serving 根据名称“tensorflow/serving”运行容器;

3.通过API查看模型状态,元数据

(1) 通过model status API 查看模型状态

curl http://localhost:8501/v1/models/testnet

结果为:

{
 "model_version_status": [
  {
   "version": "1",
   "state": "AVAILABLE",
   "status": {
    "error_code": "OK",
    "error_message": ""
   }
  }
 ]
}

(2) 通过model metadata API 查看模型的元数据

curl http://localhost:8501/v1/models/testnet/metadata

结果为:

{
"model_spec":{
 "name": "testnet",
 "signature_name": "",
 "version": "1"
}
,
"metadata": {"signature_def": {
 "signature_def": {
  "serving_default": {
   "inputs": {
    "input0": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "-1",
        "name": ""
       },
       {
        "size": "1",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "Placeholder:0"
    }
   },
   "outputs": {
    "output0": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "-1",
        "name": ""
       },
       {
        "size": "1",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "Add:0"
    }
   },
   "method_name": "tensorflow/serving/predict"
  }
 }
}
}
}

三、使用RESTful API 请求预测

1.命令行下使用curl请求预测

使用Predict API请求预测,格式为:

POST http://host:port/v1/models/${MODEL_NAME}[/versions/${MODEL_VERSION}]:predict

其中模型版本MODEL_VERSION可以省略,默认使用最新版本的模型。

curl -d '{"instances": $input_data}' -X POST http://localhost:8501/v1/models/testnet:predict

input_data为模型的输入。如果是使用tensorflow模型保存与恢复(2) 使用SavedModel中的代码生成的模型,可以使用如下命令访问:

curl -d '{"instances": [[[10,10,10,10,10,10,10],[10,10,10,10,10,10,10],[10,10,10,10,10,10,10],[10,10,10,10,10,10,10],[10,10,10,10,10,10,10],[10,10,10,10,10,10,10],[10,10,10,10,10,10,10]]]}' -X POST http://localhost:8501/v1/models/testnet:predict

并将得到如下返回结果:
使用docker和tf serving搭建模型预测服务_第2张图片
如果机器有公网IP(如将tfsevring部署在阿里云服务器上),则可以在其他机器上通过IP地址访问进行预测,将上面的地址中的localhost改为运行容器的机器的公网IP地址即可。

2.使用Python代码请求预测

也可以使用python代码请求预测

import requests
import numpy as np
SERVER_URL = 'http://localhost:8501/v1/models/testnet:predict'
def prediction():
    predict_request='{"instances":%s}' % str([[[10]*7]*7])
    #print(predict_request)
    response = requests.post(SERVER_URL, data=predict_request)
    prediction = response.json()['predictions'][0]
    print(prediction)
    
if __name__ == "__main__":
    prediction()

四、使用gRPC 请求预测

需要安装tensorflow-serving-api,这里将gRPC的端口映射到宿主机的8500端口。

请求预测python代码:

import grpc
import numpy as np
from tensorflow_serving.apis import model_service_pb2_grpc, model_management_pb2, get_model_status_pb2, predict_pb2, prediction_service_pb2_grpc
from tensorflow_serving.config import model_server_config_pb2
from tensorflow.contrib.util import make_tensor_proto
from tensorflow.core.framework import types_pb2

def predict_test(batch_size, serving_config):
    channel = grpc.insecure_channel(serving_config['hostport'], options=[('grpc.max_send_message_length', serving_config['max_message_length']), (
        'grpc.max_receive_message_length', serving_config['max_message_length'])])
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)

    # Creating random images for given batch size 
    input_data=[5.0,2.0]

    request = predict_pb2.PredictRequest()
    request.model_spec.name = serving_config['model_name']
    request.model_spec.signature_name = serving_config['signature_name']
    request.inputs['input0'].CopyFrom(make_tensor_proto(
        input_data, shape=[1,2], dtype=types_pb2.DT_FLOAT))
    result = stub.Predict(request, serving_config['timeout'])
    channel.close()    
    return result

if __name__ == "__main__":
    serving_config = {
        "hostport": "127.0.0.1:8500",
        "max_message_length": 10 * 1024 * 1024,
        "timeout": 300,
        "signature_name": "serving_default",
        "model_name": "testnet"
    }
    predict_result = predict_test(1, serving_config)
    print(predict_result)
    print(predict_result.outputs['output0'].float_val)

返回的结果如下(这里使用的是另外一个模型,模型对输入数据进行加1操作):

outputs {
  key: "output0"
  value {
    dtype: DT_FLOAT
    tensor_shape {
      dim {
        size: 1
      }
      dim {
        size: 2
      }
    }
    float_val: 5.099999904632568
    float_val: 2.0999999046325684
  }
}
model_spec {
  name: "testnet"
  version {
    value: 1
  }
  signature_name: "serving_default"
}

Done!

上述使用如Python代码处理完成后再请求预测的方法,有时使用起来会显得不方便。有些情况下也可能有将预测的过程作为一个web服务,实现在网页上填写图片的地址信息,然后返回预测结果的需求。在下一篇将介绍使用开源的Python web框架Django结合tfserving,搭建一个图像分类预测web服务。

你可能感兴趣的:(TensorFlow)