美文网首页tensowflowdocker
Tensorflow Serving-Docker RESTfu

Tensorflow Serving-Docker RESTfu

作者: 西溪雷神 | 来源:发表于2018-11-23 17:14 被阅读0次

    tensorflow模型的deploy有多种方法,tensorflow serving是一款面向tensorflow模型对外提供服务的web容器,部署之后只需要更新指定位置的模型文件即可实现模型的在线替换,非常适合生产环境下的运行。

    网上此类教程不多,但还是能搜到一些,我参考的是这位仁兄的:
    https://blog.csdn.net/u011734144/article/details/82107610?utm_source=oschina-app

    一、问题的提出

    安装好了,之后找了些例子跑了下,没什么问题。可是当我用自己的模型进行预测的时候,却报错了:

    (1) 当预测样本为1的时候,返回为0:

    客户端代码:

    p_data0 = {"input_x": input_x[0], 'keep_prob': 1.0}
    param = {
        "signature_name":signature_key,
        "instances": [p_data0]
    }
    

    返回结果:

    {
        "predictions": [[0.0, 0.0, 0.0]]
    }
    

    (2) 当预测样本为多个的时候,直接报错:

    客户端代码:

    p_data0 = {"input_x": input_x[0], 'keep_prob': 1.0}
    p_data1 = {"input_x": input_x[1], 'keep_prob': 1.0}
    param = {
        "signature_name":signature_key,
        "instances": [p_data0, p_data1]
     }
    

    返回错误:

    { "error": "Incompatible shapes: [2,1024] vs..."}
    

    二、问题排查

    1、解决单个预测结果为0的问题

    在请教了@小浩之后,才知道问题原来出在batch_norm上。之前是根据公式写的代码,如果只有一个样本,那么样本等于其均值,output就为0了


    batch norm

    详细解答可以参考:https://stackoverflow.com/questions/48320854/tensorflow-and-batch-normalization-with-batch-size-1-outputs-all-zeros?rq=1

    后面改正只需要把batch内样本求mean和var的公式改为总体样本的滑动方式就可以了,预测的时候使用训练集总体滑动的mean以及var。

    在线下将pb模型加载运行一遍,发现这个问题得到了解决。

    2、解决批量预测出现问题

    但是当我把修改代码训练后的模型加载到tensorflow serving、进行客户端访问时,却发现连单个样本的访问也无法成功了。

    客户端代码:

    p_data0 = {"input_x": input_x[0], 'keep_prob': 1.0, 'is_train': False}
    param = {
        "signature_name":signature_key,
        "instances": [p_data0]
    }
    

    报错:

    { "error": "The second input must be a scalar, but it has shape [1]..."}
    

    批量访问的错误也发生了变化

    客户端代码:

    p_data0 = {"input_x": input_x[0], 'keep_prob': 1.0, 'is_train': False}
    p_data1 = {"input_x": input_x[1], 'keep_prob': 1.0, 'is_train': False}
    param = {
        "signature_name":signature_key,
        "instances": [p_data0, p_data1]
    }
    

    报错:

    { "error": "The second input must be a scalar, but it has shape [2]..."}
    

    跟上一次唯一的不同,只是增加了一个is_train的placeholder,发生这样的错误感觉很匪夷所思。

    后来我在参考的那篇文章里面看到,作者之所以这样写客户端的请求代码,是参考了tensorflow/serving里面json_tensor.h这个文件,于是我也去github上面把这个文件读了一下,里面有这么一段话。

    // "instances" is used to format input tensors in "row" format and "inputs"
    // is used to format them in "columnar" format. The former is easy to read
    // but requires all inputs to have same 0-th dimension whereas the latter
    // can represent input tensors with varying sizes.

    使用"instances"作为参数传入的时候要求所有的输入具有相同的0维,反之"inputs"可以输入具有不同大小的张量,说实话不太懂,什么是具有相同的0维,"instances"列表里的元素还是单个元素里面各个不同的参数?又看了下"inputs"的使用方法:

    // {
    // "inputs": {
    // "tag": ["foo", "bar"],
    // "signal": [1, 2, 3, 4, 5, 3, 4, 1, 2, 4],
    // "sensor": [[1, 2], [3, 4], [4, 5], [6, 8]]
    // }
    // }

    貌似更符合输入习惯,于是我抱着试一试的心态改了下:

    p_data0 = {"input_x": input_x[0:1], 'keep_prob': 1.0, 'is_train': False}
    param = {
        "signature_name": signature_key,
        "inputs": p_data0
    }
    

    这下没问题了!上面是单个样本的预测,多个样本的话直接"input_x": input_x[0:n]就可以了。

    事实上我用到的只是predict API,RESTful API 还有classify API和regress API,它们两者的API很像,但与predict API不同。

    除了RESTful API 之外tensorflow serving主打的gRPC API好像才是亮点,这个以后再继续尝试吧。

    三、总结

    (1) 对于tensorflow serving-docker的安装、以及基础用法参考最上面那个文章就可以了,写的还是蛮清晰的;
    (2)如果进行单个模型预测(不局限于tensorflow serving)返回的结果为0,那么多半是batch norm的问题, 这类问题很常见,网上的资料已经很多了。
    (3)如果在客户端请求tensorflow serving接口时,发生返回错误,基本上是参数传入的问题。

    后面在这里找到一篇翻译,关于客户端请求参数的介绍,写得挺好的:
    https://www.jianshu.com/p/a9dbf1e63c88?utm_source=oschina-app

    相关文章

      网友评论

        本文标题:Tensorflow Serving-Docker RESTfu

        本文链接:https://www.haomeiwen.com/subject/udjjqqtx.html