资讯专栏INFORMATION COLUMN

TensorFlow在产品环境中运行模型的实践经验总结

stackfing / 2955人阅读

摘要:它使用机器学习来解释用户提出的问题,并用相应的知识库文章来回应。使用一类目前较先进的机器学习算法来识别相关文章,也就是深度学习。接下来介绍一下我们在生产环境中配置模型的一些经验。

我们如何开始使用TensorFlow  

在Zendesk,我们开发了一系列机器学习产品,比如的自动答案(Automatic Answers)。它使用机器学习来解释用户提出的问题,并用相应的知识库文章来回应。当用户有问题、投诉或者查询时,他们可以在线提交请求。收到他们的请求后,Automatic Answers将分析请求,并且通过邮件建议客户阅读相关的可能最有帮助的文章。

Automatic Answers使用一类目前较先进的机器学习算法来识别相关文章,也就是深度学习。 我们使用Google的开源深度学习库TensorFlow来构建这些模型,利用图形处理单元(GPU)来加速这个过程。Automatic Answers是我们在Zendesk使用Tensorflow完成的第一个数据产品。在我们的数据科学家付出无数汗水和心血之后,我们才有了在Automatic Answers上效果非常好的Tensorflow模型。

但是构建模型只是问题的一部分,我们的下一个挑战是要找到一种方法,使得模型可以在生产环境下服务。模型服务系统将经受大量的业务。所以需要确保为这些模型提供的软件和硬件基础架构是可扩展的、可靠的和容错的,这对我们来说是非常重要的。接下来介绍一下我们在生产环境中配置TensorFlow模型的一些经验。

顺便说一下我们的团队——Zendesk的机器学习数据团队。我们团队包括一群数据科学家、数据工程师、一位产品经理、UX /产品设计师以及一名测试工程师。

Data Team At Zendesk Melbourne

TensorFlow模型服务  

经过数据科学家和数据工程师之间一系列的讨论,我们明确了一些核心需求:

预测时的低延迟

横向可扩展

适合我们的微服务架构

可以使用A/B测试不同版本的模型

可以与更新版本的TensorFlow兼容

支持其他TensorFlow模型,以支持未来的数据产品

TensorFlow Serving  

经过网上的调研之后,Google的TensorFlow Serving成为我们推荐的模型服务。TensorFlow Serving用C++编写,支持机器学习模型服务。开箱即用的TensorFlow Serving安装支持:

TensorFlow模型的服务

从本地文件系统扫描和加载TensorFlow模型

(小编注:TensorFlow和TensorFlow Serving的区别:TensorFlow项目主要是基于各种机器学习算法构建模型,并为某些特定类型的数据输入做适应学习,而TensorFlow Serving则专注于让这些模型能够加入到产品环境中。开发者使用TensorFlow构建模型,然后TensorFlow Serving基于客户端输入的数据使用前面TensorFlow训练好的模型进行预测。)

TensorFlow Serving将每个模型视为可服务对象。它定期扫描本地文件系统,根据文件系统的状态和模型版本控制策略来加载和卸载模型。这使得可以在TensorFlow Serving继续运行的情况下,通过将导出的模型复制到指定的文件路径,而轻松地热部署经过训练的模型。

   

TensorFlow Serving Architecture

根据这篇Google博客中报告的基准测试结果,他们每秒记录大约100000个查询,其中不包括TensorFlow预测处理时间和网络请求时间。

有关TensorFlow Serving架构的更多信息,请参阅TensorFlow Serving文档。

通信协议(gRPC)  

TensorFlow Serving提供了用于从模型调用预测的gRPC接口。gRPC是一个开源的高性能远程过程调用(remote procedure call,RPC)框架,它在HTTP/2上运行。与HTTP/1.1相比,HTTP/2包含一些有趣的增强,比如它对请求复用、双向流和通过二进制传输的支持,而不是文本。

默认情况下,gRPC使用Protocol Buffers (Protobuf)作为其信息交换格式。Protocol Buffers是Google的开源项目,用于在高效的二进制格式下序列化结构化数据。它是强类型,这使它不容易出错。数据结构在.proto文件中指定,然后可以以各种语言(包括Python,Java和C ++)将其编译为gRPC请求类。 这是我第一次使用gRPC,我很想知道它与其他API架构(如REST)相比谁性能更好。

模型训练和服务架构  

我们决定将深度学习模型的训练和服务分为两个管道。下图是我们的模型训练和服务架构的概述:

Model Training and Serving Architecture

模型训练管道

模型训练步骤:

我们的训练特征是从Hadoop中提供的数据生成的。

生成的训练特征保存在AWS S3中。

然后使用AWS中的GPU实例和S3中的批量训练样本训练TensorFlow模型。

一旦模型被构建并验证通过,它将被发布到S3中的模型存储库。

模型服务管道

验证的模型在生产中通过将模型从模型库传送到TensorFlow Serving实例来提供。

基础结构  

我们在AWS EC2实例上运行TensorFlow Serving。Consul在实例之前设置,用于服务发现和分发流量。客户端连接从DNS查找返回的第一个可用IP。或者弹性负载平衡可用于更高级的负载平衡。由于TensorFlow模型的预测本质上是无状态操作,所以我们可以通过旋转加速更多的EC2实例 来实现横向可扩展性。

另一个选择是使用Google Cloud平台提供的Cloud ML,它提供TensorFlow Serving作为完全托管服务。 但是,当我们在大概2016年9月推出TensorFlow Serving时,Cloud ML服务处于alpha阶段,缺少生产使用所需的功能。因此,我们选择在我们自己的AWS EC2实例中托管,以实现更精细的粒度控制和可预测的资源容量。

模型服务的实现  

下面是我们实现TensorFlow Serving部署和运行所采取的步骤:

1.从源编译TensorFlow Serving

首先,我们需要编译源代码来产生可执行的二进制文件。然后就可以从命令行执行二进制文件来启动服务系统。

假设你已经配置好了Docker,那么一个好的开端就是使用提供的Dockerfile来编译二进制文件。请按照以下步骤:

运行该gist中的代码以构建适合编译TensorFlow Serving的docker容器。

在正在运行的docker容器中运行该gist中的代码以构建可执行二进制文件。

一旦编译完成,可执行二进制文件将在你的docker镜像的以下路径中:/work/serving/bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server

2.运行模型服务系统

上一步生成的可执行二进制文件(tensorflow_model_server)可以部署到您的生产实例中。 如果您使用docker编排框架(如Kubernetes或Elastic Container Service),您还可以在docker容器中运行TensorFlow Serving。

现在假设TensorFlow模型存储在目录/work/awesome_model_directory下的生产主机上。你可以在端口8999上使用以下命令来运行TensorFlow Serving和你的TensorFlow模型:

/tensorflow_model_server — port=8999 — model_base_path=/work/awesome_model_directory

默认情况下,TensorFlow Serving会每秒扫描模型基本路径,并且可以自定义。此处列出了可作为命令行参数的可选配置。

3.从服务定义(Service Definitions)生成Python gRPC存根

下一步是创建可以在模型服务器上进行预测的gRPC客户端。这可以通过编译.proto文件中的服务定义,从而生成服务器和客户端存根来实现。.proto文件在TensorFlow Serving源码中的tensorflow_serving_apis文件夹中。在docker容器中运行以下脚本来编译.proto文件。运行提交版本号为46915c6的脚本的示例:

./compile_ts_serving_proto.sh 46915c6

运行该脚本后应该在tensorflow_serving_apis目录下生成以下定义文件:

model_pb2.py

predict_pb2.py

prediction_service_pb2.py

你还可以使用grpc_tools Python工具包来编译.proto文件。

4.从远程主机调用服务

可以使用编译后的定义来创建一个python客户端,用来调用服务器上的gRPC调用。比如这个例子用一个同步调用TensorFlow Serving的Python客户端。

如果您的用例支持异步调用预测,TensorFlow Serving还支持批处理预测以达到性能优化的目的。要启用此功能,你应该运行tensorflow_model_server同时开启flag —enable_batching。这是一个异步客户端的例子。

从其他存储加载模型

如果你的模型没有存储在本地系统中应该怎么办?你可能希望TensorFlow Serving可以直接从外部存储系统(比如AWS S3和Google Storage)中直接读取。

如果是这种情况,你将需要通过Custom Source来拓展TensorFlow Serving以使其可以读取这些源。TensorFlow Serving仅支持从文件系统加载模型。

一些经验  

我们在产品中已经使用TensorFlow Serving大概半年的时间,我们的使用体验是相当平稳。它具有良好的预测时间延迟。以下是我们的TensorFlow Serving实例一周内的预测时间(以秒为单位)的第95百分位数的图(约20毫秒):

然而,在生产中使用TensorFlow Serving的过程中,我们也有一些经验教训可以跟大家分享。

1.模型版本化

到目前为止,我们已经在产品中使用了几个不同版本的TensorFlow模型,每一个版本都有不同的特性,比如网络结构、训练数据等。正确处理模型的不同版本已经是一个重要的任务。这是因为传递到TensorFlow Serving的输入请求通常涉及到多个预处理步骤。这些预处理步骤在不同TensorFlow模型版本下是不同的。预处理步骤和模型版本的不匹配可能导致错误的预测。

1a.明确说明你想要的版本

我们发现了一个简单但有用的防止错误预测的方法,也就是使用在model.proto定义中指定的版本属性,它是可选的(可以编译为model_pb2.py)。这样可以始终保证你的请求有效负载与预期的版本号匹配。

当你请求某个版本(比如从客户端请求版本5),如果TensorFlow Serving服务器不支持该特定版本,它将返回一个错误消息,提示找不到模型。

1b.服务多个模型版本

TensorFlow Serving默认的是加载和提供模型的版本。当我们在2016年9月首次应用TensorFlow Serving时,它不支持同时提供多个模型。这意味着在指定时间内它只有一个版本的模型。这对于我们的用例是不够的,因为我们希望服务多个版本的模型以支持不同神经网络架构的A / B测试。

其中一个选择是在不同的主机或端口上运行多个TensorFlow Serving进程,以使每个进程提供不同的模型版本。这样的话就需要:

用户应用程序(gRPC客户端)包含切换逻辑,并且需要知道对于给定的版本需要调用哪个TensorFlow Serving实例。这增加了客户端的复杂度,所以不是推荐。

一个可以将版本号映射到TensorFlow Serving不同实例的注册表。

更理想的解决方案是TensorFlow Serving可以支持多个版本的模型。

所以我决定使用一个“lab day”的时间来扩展TensorFlow Serving,使其可以服务多个版本的时间。在Zendesk,“lab day”就是我们可以每两周有一天的时间来研究我们感兴趣的东西,让它成为能够提高我们日常生产力的工具,或者一种我们希望学习的新技术。我已经有8年多没有使用C++代码了。但是,我对TensorFlow Serving代码库的可读性和整洁性印象深刻,这使其易于扩展。支持多个版本的增强功能已经提交,并且已经合并到主代码库中。

TensorFlow Serving维护人员对补丁和功能增强的反馈非常迅速。从的主分支,你可以启动TensorFlow Serving,用model_version_policy中附加的flag来服务多个模型版本:

/work/serving/bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server — port=8999 — model_base_path=/work/awesome_model_directory — model_version_policy=ALL_VERSIONS

一个值得注意的要点是,服务多个模型版本,需要权衡的是更高的内存占用。所以上述的flag运行时,记住删除模型基本路径中的过时模型版本。

2.活用压缩

当你部署一个新的模型版本的时候,建议在复制到model_base_path之前,首先将导出的TensorFlow模型文件压缩成单个的压缩文件。Tensorflow Serving教程中包含了导出训练好的Tensorflow模型的步骤。导出的检查点TensorFlow模型目录通常具有以下文件夹结构:

一个包含版本号(比如0000001)和以下文件的父目录:

saved_model.pb:序列化模型,包括模型的图形定义,以及模型的元数据(比如签名)。

variables:保存图形的序列化变量的文件。压缩导出的模型:

tar -cvzf modelv1.tar.gz 0000001

为什么需要压缩?

压缩后转移和复制更快

如果你将导出的模型文件夹直接复制到model_base_path中,复制过程可能需要一段时间,这可能导致导出的模型文件已复制,但相应的元文件尚未复制。如果TensorFlow Serving开始加载你的模型,并且无法检测到源文件,那么服务器将无法加载模型,并且会停止尝试再次加载该特定版本。

3.模型大小很重要

我们使用的TensorFlow模型相当大,在300Mb到1.2Gb之间。我们注意到,在模型大小超过64Mb时,尝试提供模型时将出现错误。这是由于protobuf消息大小的硬编码64Mb限制,如这个TensorFlow Serving在Github上的问题所述。

最后,我们采用Github问题中描述的补丁来更改硬编码的常量值。(这对我们来说还是一个问题。如果你可以找到在不改变硬编码的情况下,允许服务大于64Mb的模型的替代方案,请联系我们。)

4.避免将源移动到你自己的分支下

从实现时开始,我们一直从主分支构建TensorFlow Serving源,的版本分支(v0.4)在功能和错误修复方面落后于主分支。因此,如果你只通过检查主分支来创建源,一旦新的更改被合并到主分支,你的源也可能改变。为了确保人工制品的可重复构建,我们发现检查特定的提交修订很重要:

TensorFlow Serving

TensorFlow(TensorFlow Serving里的Git子模块)

期待未来加入的一些功能增强清单  

这里是一些我们比较感兴趣的希望以后TensorFlow Serving会提供的功能:

健康检查服务方法

一个TensorFlow Serving实例可以支持多种模型类型

直接可用的分布式存储(如AWS S3和Google存储)中的模型加载

直接支持大于64Mb的模型

不依赖于TensorFlow的Python客户端示例

欢迎加入本站公开兴趣群

商业智能与数据分析群

兴趣范围包括各种让数据产生价值的办法,实际应用案例分享与讨论,分析工具,ETL工具,数据仓库,数据挖掘工具,报表系统等全方位知识

QQ群:81035754

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/4490.html

相关文章

  • “大数据+”实践:数据平台设计与搭建

    摘要:在近期举办的全球架构师峰会上,个推首席数据架构师袁凯,基于他在数据平台的建设以及数据产品研发的多年经验,分享了面向机器学习数据平台的设计与搭建。二具体开展机器学习的过程原始数据经过数据的处理,入库到数据仓里。 机器学习作为近几年的一项热门技术,不仅凭借众多人工智能产品而为人所熟知,更是从根本上增能了传统的互联网产品。在近期举办的2018 ArchSummit全球架构师峰会上,个推首席数...

    BlackHole1 评论0 收藏0
  • 玩转TensorFlow Lite:有道云笔记实操案例分享

    摘要:如何进行操作本文将介绍在有道云笔记中用于文档识别的实践过程,以及都有些哪些特性,供大家参考。年月发布后,有道技术团队第一时间跟进框架,并很快将其用在了有道云笔记产品中。微软雅黑宋体以下是在有道云笔记中用于文档识别的实践过程。 这一两年来,在移动端实现实时的人工智能已经形成了一波潮流。去年,谷歌推出面向移动端和嵌入式的神经网络计算框架TensorFlowLite,将这股潮流继续往前推。Tens...

    Hanks10100 评论0 收藏0
  • 深度学习

    摘要:深度学习在过去的几年里取得了许多惊人的成果,均与息息相关。机器学习进阶笔记之一安装与入门是基于进行研发的第二代人工智能学习系统,被广泛用于语音识别或图像识别等多项机器深度学习领域。零基础入门深度学习长短时记忆网络。 多图|入门必看:万字长文带你轻松了解LSTM全貌 作者 | Edwin Chen编译 | AI100第一次接触长短期记忆神经网络(LSTM)时,我惊呆了。原来,LSTM是神...

    Vultr 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<