官方的文档https://www.tensorflow.org/tfx/serving/docker
目录
官方例程
部署自己的模型
首先拉取官方TensorFlow serving的镜像
docker pull tensorflow/serving
建立本地的repo
mkdir -p /tmp/tfserving
cd /tmp/tfserving
git clone https://github.com/tensorflow/serving
运行镜像
docker run -p 8501:8501 \
--mount type=bind,\
source=/tmp/tfserving/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 &
命令的解释如下
--mount: 表示要进行挂载
source: 指定要运行部署的模型地址, 也就是挂载的源,这个是在宿主机上的模型目录
target: 这个是要挂载的目标位置,也就是挂载到docker容器中的哪个位置,这是docker容器中的目录
-t: 指定的是挂载到哪个容器
-p: 指定主机到docker容器的端口映射,这里的8501端口是镜像里REST的端口
docker run: 启动这个容器并启动模型服务
综合解释:
将source目录中的例子模型,挂载到-t指定的镜像启动的容器下的target目录,并启动
这时出现错误,提示&要加双引号
所在位置 行:1 字符: 208
+ ... s/half_plus_three -e MODEL_NAME=half_plus_two -t tensorflow/serving &
+ ~
不允许使用与号(&)。& 运算符是为将来使用而保留的;请用双引号将与号引起来("&"),以将其作为字符串的一部分传递。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : AmpersandNotAllowed
用双引号把&扩起来
docker run -p 8501:8501 --name="half_plus_two" --mount type=bind,source=E:/tmp/tfserving/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 "&"
然后出现了-X的问题,可能是指令的格式不对
Invoke-WebRequest : 找不到与参数名称“X”匹配的参数。
所在位置 行:1 字符: 42
+ curl -d '{"instances": [1.0, 2.0, 5.0]}' -X POST http://localhost:850 ...
+ ~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest],ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
参考了https://www.shuijingwanwq.com/2018/12/28/3077/,改成如下
curl -Body '{"instances": [1.0, 2.0, 5.0]}' -Uri http://localhost:8501/v1/models/half_plus_two:predict -Method 'POST'
或者使用requests.post方法
uri=http://localhost:8501/v1/models/half_plus_two:predict
query_data = '{"instances": [[1.0, 2.0, 3.0]}'
requests.post(url, query_data)
这样就能work了,结果如下
StatusCode : 200
StatusDescription : OK
Content : {
"predictions": [2.5, 3.0, 4.5
]
}
RawContent : HTTP/1.1 200 OK
Content-Length: 43
Content-Type: application/json
Date: Mon, 22 Jun 2020 07:58:23 GMT
{
"predictions": [2.5, 3.0, 4.5
]
}
Forms : {}
Headers : {[Content-Length, 43], [Content-Type, application/json], [Date, Mon, 22 Jun 2020 07:58:23 GMT]}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : mshtml.HTMLDocumentClass
RawContentLength : 43
只需要把自己的模型存成例程那样的格式就行,例程的文件结构是
model下有一个00000123的文件夹,里面有assets,variables,saved_model.pb三个文件,结构如下
E:.
└─00000123
│ saved_model.pb
│
├─assets
│ foo.txt
│
└─variables
variables.data-00000-of-00001
variables.index
assets下只有一个foo.txt,里面内容是
asset-file-contents
因为我用的Keras训练网络,所以先需要转换成TensorFlow的.pb模型文件,代码如下
def model_h52pb():
model_path = r'D:\work\model\my_model.h5'
K.set_learning_phase(0)
model = load_model(model_path, custom_objects={'my_acc': my_acc}) # 加载h5模型
export_path = r'D:\work\model\tf_model'
with K.get_session() as sess:
tf.saved_model.simple_save(
sess,
export_path,
inputs={'input': model.input},
outputs={t.name: t for t in model.outputs})
这样可以得到和例程文件格式完全一样的variables和pb文件 ,那个assets文件夹直接拷贝过来。这样文件格式就搞定了。
官方例程的写法是
docker run -p 8501:8501 --mount type=bind,source=E:/tmp/tfserving/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 "&"
source里面是本地模型的路径,只需要换成我们模型的路径就行了。target里面放模型在容器里的路径,MODEL_NAME在query的时候要用到。这里模型名字设置为my_model。
docker run -p 8501:8501 --name="my_model" --mount type=bind,source=E:/tmp/tfserving/my_model,target=/models/my -e MODEL_NAME=my -t tensorflow/serving "&"
query可以这样写
curl -Body '{"instances": [[1.0, 2.0, 5.0]]}' -Uri http://localhost:8501/v1/models/my:predict -Method 'POST'
注意instances的格式要跟代码能正确处理的数据格式一样,才能进行预测,我这里是输入一个1*3的矩阵,与[1,2,3]点乘,然后+1。
收到的response如下
StatusCode : 200
StatusDescription : OK
Content : {
"predictions": [[20.8982468]
]
}
RawContent : HTTP/1.1 200 OK
Content-Length: 42
Content-Type: application/json
Date: Tue, 23 Jun 2020 01:31:10 GMT
{
"predictions": [[20.8982468]
]
}
Forms : {}
Headers : {[Content-Length, 42], [Content-Type, application/json], [Date, Tue, 23 Jun 2020 01:31:10 GMT]}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : mshtml.HTMLDocumentClass
RawContentLength : 42
可以看到结果是符合预期的,大功告成!
参考:
http://dockone.io/article/9209
https://www.shuijingwanwq.com/2018/12/28/3077/
https://blog.csdn.net/weixin_34343000/article/details/88118667?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-6
https://blog.csdn.net/u011734144/article/details/82107610?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
https://blog.csdn.net/m0_38088298/article/details/85796658