没人告诉你的大规模部署AI高效流程!
作者:CQITer小编 时间:2019-01-07 09:50
现在有许多关于 AI 的教程。比如如何进行目标检测、图像分类、NLP 以及构建聊天机器人等,不胜枚举。
但当我查找如何正确扩展 AI 的内容时,却发现少得可怜。更令人惊讶的是,现有的极少数资源在反复强调相同的几点:
用像 TensorFlow 这样的可扩展框架构建模型。
将其打包到客户端(TF.js、TF Lite、TF-slim 等)或部署为基于容器的微服务。
我对第二点更感兴趣,因为我已经开发好了一个模型,但令我惊讶的是,没有任何关于如何实现第二点的细节,而关于每个解决方案缺点的信息则更少。研究了几天并在 Crane.ai 上扩展 AI 之后,我整理了一些关于如何部署这些方法、这些方法的缺点以及如何在低级别优化 TensorFlow 模型的内容。

将模型打包到客户端——这种方法太糟了!
最常用的方法之一是用像 TensorFlow.js、TF Lite 或 TensorFlow Slim 这样的工具将 AI 打包到你所选择的客户端中。我不会详细介绍这些框架如何运行,但我会重点说明它们的缺点。
计算能力。部署这些模型的问题在于它们需要大量的内存(我指的是移动应用程序或浏览器的限制,即 > 1-2GB RAM)。许多手机都没有这样的计算能力,而桌面浏览器又会延迟 UI 线程,同时也降低了用户的计算机速度,要打开浏览器,还要打开风扇等等。
推断时间。当你在计算能力未知的设备上运行模型时,推断时间一般也是未知的;这些设备不是 GPU 驱动的高 RAM、高 CPU 机器,它们只是在普通计算机上运行的手机、浏览器和桌面应用程序。较大模型的推断时间可以轻松超过一分钟时间,而从用户体验的角度来看,这并不可行。

大文件。不幸的是大多数模型都存储在相当大的文件中(我指的是数十、数百 MB)。因此,加载这些文件速度很慢,需要的内存量比较大,也大幅增加了应用程序包的大小。
不安全。除非你用的是开源模型,否则你要相对保密你的 AI 模型和预训练检查点。然而,当你将模型打包进应用程序时,不仅你的推断代码容易被反编译,而且在应用程序包里的预训练检查点也很容易被窃取。
难以更新。如果想要更新你的模型,在客户端中你有两个选择。要么通过集中管理器(即 Play Store、App Store 等)发布更新,这会导致频繁的大型更新(对用户而言这是很烦人的,而且用户可以根据设置打断这个过程,或者压根就不开启更新)。或者应用程序本身可以获取新模型的检查点和元数据。后者听起来要好得多,但是这意味着你可能要在用户连接不稳定的情况下下载 100MB 以上的文件,这可能需要一段时间,所以你的应用程序至少要在后台开到下载过程完成,而且会产生很高的互联网输出成本(这取决于你的云计算)。
缺乏可训练性。针对新用户的数据训练的模型提供了一定程度的个性化,同时提高了准确率,并建立了核心的高信号数据集。不幸的是大部分设备缺乏训练模型的计算能力,即便它们的计算能力够了,也无法将训练效果传递到服务器或其他运行该应用程序的设备。

这些缺点使得在客户端上部署和维护大型神经网络几乎不可能,所以我们从扩展模型的备选项中排除这一项。
部署为云端点

图源:https://xkcd.com/908/
云是可以大规模部署模型的强大工具。你可以根据需要定制环境、容器化应用程序、立即水平扩展应用程序,同时提供足以和大公司媲美的 SLA 和运行时间。
对大部分 TensorFlow 模型来说,部署流程是相同的:
将图像固化为 Protobuf 二进制文件
调整推断代码,使它可以处理固化的图
容器化应用程序
在最上面加上 API 层
第一部分相对简单。「固化」图要用所有命名节点、权重、架构和检查点元数据创建一个 protobuf 二进制文件。这一步可以用多种工具实现,最常用的是 TF 自己的工具,它可以固化任何给定输出节点名字的图。
更多该技术相关信息以及实现参阅: https://www.tensorflow.org/guide/extend/model_files#freezing。

调整推断代码也不难。在大多数情况下,feed_dict 是不变的,主要区别在于添加了加载模型的代码,也许还有输出节点的规范。
容器化也很简单——只要在 Dockerfile 中设置环境即可。而当我们开始添加 API 层时,事情就会变得混乱。通常用这两种方法:



