TensorFlow REST 前端,但不是 TensorFlow Serving

Posted

技术标签:

【中文标题】TensorFlow REST 前端,但不是 TensorFlow Serving【英文标题】:TensorFlow REST Frontend but not TensorFlow Serving 【发布时间】:2016-12-20 11:58:11 【问题描述】:

我想部署一个简单的 TensorFlow 模型并在 Flask 等 REST 服务中运行它。 目前在 github 或这里没有找到好的例子。

我还没有准备好按照其他帖子中的建议使用 TF Serving,它对 Google 来说是完美的解决方案,但对于我的 gRPC、bazel、C++ 编码、protobuf 任务来说,它过大了...

【问题讨论】:

缩小问题的范围,只想要一个在保护程序加载模型后在 Flask 中返回结果的工作示例 22人没觉得太宽泛了 您好!我可以看到这将是一个有用的问题!但是,在这里提供代码非常困难(因为这个问题非常广泛),并且有很多方法可以实现这一点。如果您与我们共享了您为完成此操作而编写的特定代码,那么我们将能够帮助调试该代码。有一个相关的网站,softwareengineering.stackexchange.com,它可能可以帮助你想出一个设计。祝你好运! 根据网站的规则,这太宽泛了,但我还是投票决定重新开放。你可以在Flask上找到很多教程,只要把工作放进去,你就会有解决方案。 在问这个问题的时候,没有像 pyimagesearch.com/2018/01/29/… 这样的教程。但是,如果有人要尝试实现生产就绪的解决方案,则需要考虑 GPU 内存限制、线程并发性、模型优化和不可变性等。实际上没有简单易行的方法,但交付的产品更多。 【参考方案1】:

github project 展示了一个恢复模型检查点和使用 Flask 的工作示例。

@app.route('/api/mnist', methods=['POST'])
def mnist():
    input = ((255 - np.array(request.json, dtype=np.uint8)) / 255.0).reshape(1, 784)
    output1 = simple(input)
    output2 = convolutional(input)
    return jsonify(results=[output1, output2])

网上demo好像挺快的。

【讨论】:

【参考方案2】:

有不同的方法可以做到这一点。纯粹来说,使用 tensorflow 不是很灵活,但是相对简单。这种方法的缺点是您必须在恢复模型的代码中重建图形并初始化变量。 tensorflow skflow/contrib learn 中显示了一种更优雅的方法,但是目前这似乎不起作用,并且文档已过时。

我在 github here 上放了一个简短的示例,展示了如何将 GET 或 POST 参数命名为 REST 部署的 tensorflow 模型。

然后,主要代码在一个函数中,该函数根据 POST/GET 数据获取字典:

@app.route('/model', methods=['GET', 'POST'])
@parse_postget
def apply_model(d):
    tf.reset_default_graph()
    with tf.Session() as session:
        n = 1
        x = tf.placeholder(tf.float32, [n], name='x')
        y = tf.placeholder(tf.float32, [n], name='y')
        m = tf.Variable([1.0], name='m')
        b = tf.Variable([1.0], name='b')
        y = tf.add(tf.mul(m, x), b) # fit y_i = m * x_i + b
        y_act = tf.placeholder(tf.float32, [n], name='y_')
        error = tf.sqrt((y - y_act) * (y - y_act))
        train_step = tf.train.AdamOptimizer(0.05).minimize(error)

        feed_dict = x: np.array([float(d['x_in'])]), y_act: np.array([float(d['y_star'])])
        saver = tf.train.Saver()
        saver.restore(session, 'linear.chk')
        y_i, _, _ = session.run([y, m, b], feed_dict)
    return jsonify(output=float(y_i))

【讨论】:

【参考方案3】:

我不喜欢在烧瓶 restful 文件中放置太多用于数据/模型处理的代码。我通常分别有 tf 模型类等。 可能是这样的:

# model init, loading data
cifar10_recognizer = Cifar10_Recognizer()
cifar10_recognizer.load('data/c10_model.ckpt')

@app.route('/tf/api/v1/SomePath', methods=['GET', 'POST'])
def upload():
    X = []
    if request.method == 'POST':
        if 'photo' in request.files:
            # place for uploading process workaround, obtaining input for tf
            X = generate_X_c10(f)

        if len(X) != 0:
            # designing desired result here
            answer = np.squeeze(cifar10_recognizer.predict(X))
            top3 = (-answer).argsort()[:3]
            res = ([cifar10_labels[i] for i in top3], [answer[i] for i in top3])

            # you can simply print this to console
            # return 'Prediction answer: '.format(res)

            # or generate some html with result
            return fk.render_template('demos/c10_show_result.html',
                                      name=file,
                                      result=res)

    if request.method == 'GET':
        # in html I have simple form to upload img file
        return fk.render_template('demos/c10_classifier.html')

cifar10_recognizer.predict(X) 是一个简单的函数,在 tf 会话中运行预测操作:

    def predict(self, image):
        logits = self.sess.run(self.model, feed_dict=self.input: image)
        return logits

附言从文件中保存/恢复模型是一个非常漫长的过程,在提供 post/get 请求时尽量避免这种情况

【讨论】:

以上是关于TensorFlow REST 前端,但不是 TensorFlow Serving的主要内容,如果未能解决你的问题,请参考以下文章

当我有 REST 服务时,我是不是需要 JSF 来构建前端? [复制]

GraphQL 是不是具有与 REST 相同的缓存能力

将图像从 rest 端点保存到 firebase 存储不起作用,但可以从前端工作

安装 tensorflow 1.3 后是不是需要单独安装 keras 2.0?

SOAP 还是 REST?具体项目

如何使 TensorFlow Hub 模型为 TensorFlow Serving REST 请求做好准备(使用 base64 编码图像)?