前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在几分钟内构建强大的可用于生产的深度学习视觉模型

在几分钟内构建强大的可用于生产的深度学习视觉模型

作者头像
代码医生工作室
发布2019-09-26 15:04:11
1.2K0
发布2019-09-26 15:04:11
举报
文章被收录于专栏:相约机器人相约机器人

作者 | Dipanjan

来源 | Medium

编辑 | 代码医生团队

介绍

得益于更快的计算,更好的存储和易于使用的软件,基于深度学习的解决方案绝对可以看到从概念验证隧道进入现实世界的曙光!看到深度学习模型已广泛应用于该行业的各个领域,包括医疗保健,金融,零售,技术,物流,食品技术,农业等!考虑到深度学习模型需要大量资源并且经常需要大量计算的事实,因此我们需要暂停片刻,并考虑一下最终用户使用模型时的推断和服务时间。

在进行原型设计时,需要对静态批次的数据进行训练和执行模型推断。但是,当希望以Web服务或API的形式使用模型时,这种方法论和代码工件就无法发挥作用。通常需要一个健壮且低延迟的模型服务层,该层应能够更快,更轻松地满足模型推理请求。本文试图给出一个简单而全面的动手概述,说明如何利用TensorFlow Serving为计算机视觉提供深度学习模型。本文将涉及很多内容,还将包含许多动手代码,可以根据自己的实践采用这些代码。将在本文中介绍以下主题:

  • 什么是服务?
  • TensorFlow服务概述
  • TensorFlow服务架构
  • 模型服务方法
  • 主要目标-建立服装分类器
  • 训练简单的CNN模型
  • 微调预训练的ResNet-50 CNN模型
  • TensorFlow服务的保存模型
  • 通过CPU推论服务模型
  • 使用Docker服务模型进行GPU推理
  • 奖励:使用Flask和TensorFlow服务构建服装分类器API

什么是服务?

服务,或更具体地说,模型服务是一种在训练模型后使用或应用模型进行推理的技术。通常,这涉及拥有服务器-客户端体系结构以及服务或公开训练有素的模型以进行推理。

考虑到将在本文中关注的问题-图像分类,将为模型提供一些特定的访问模式。在最终用户或客户端上,将有一个需要标记或分类的输入图像。需要将该图像转换为特定的编码格式,将其包装在带有标头的特定JSON负载中,然后将其发送到通常应托管在服务器上的Web Service \ API。API调用将调用预训练模型进行预测,并将推理结果作为从服务器到客户端的JSON响应提供服务。

TensorFlow服务概述

TensorFlow服务有很多很棒的文章,包括官方文档,绝对应该检查一下。在本部分中,将简要概述TensorFlow Serving的基本知识以及为什么需要它。为了生产深度学习或机器学习模型,需要一个强大的系统,该系统可以帮助使模型快速,一致地满足请求。TensorFlow Serving就是这样一个框架,它是一个针对机器学习模型的灵活,高性能的服务系统,专门针对生产环境而设计。

尽管始终可以构建自己的服务管道和系统,但是使用TensorFlow服务有很多好处。

  • 在保持相同的服务器体系结构和API的同时,部署新算法和实验非常容易。
  • 不仅可以与TensorFlow模型一起使用,而且可以轻松扩展以服务于其他类型的模型和数据。
  • 可用于同时服务多个模型和模型版本。
  • 高效的模型生命周期管理。
  • 可以与Docker和Kubernetes之类的工具集成以实现更大的可扩展性。

TensorFlow服务架构

在本节中,将简要研究TensorFlow Serving背后的体系结构的要点。要深入了解该体系结构,建议再次检查官方文档。

服务是TensorFlow服务架构中的核心抽象。通常,可服务对象是客户端用来执行诸如模型推断之类的计算的基础对象。单个Servable可能包含一个模型甚至多个模型。下图展示了可服务对象的典型寿命。

可服务人员的寿命

通常,此体系结构中包含多个组件。可服务流是可服务版本的序列。装载机管理可服务的生命周期,具有装载和卸载可服务的API。源是用于查找和提供可服务项并可以维护在多个可服务项之间共享的状态的插件模块。经理负责处理可食用物品的整个生命周期,包括装载,卸载和供应可食用物品。使用标准的TensorFlow Serving API,TensorFlow Serving Core可以管理服务项目的生命周期和指标。

模型服务方法

在讨论主要目标并训练模型之前,简要讨论一下将遵循的模型服务方法,假设已经训练了一些基于视觉的深度学习模型。下图显示了要遵循的关键步骤。

因此,将主要针对服务模型的关键步骤包括:

  • 模型训练:要为任何模型服务,需要首先训练模型!在本文中,将利用tf.kerasTensorFlow中的API,这有助于轻松训练深度学习模型。
  • 导出模型:在这里,需要将训练有素的模型导出为TF Serving可以使用的特定格式。TensorFlow将SavedModel格式提供为导出模型的通用格式。这将在定义明确的目录层次结构中创建一个protobuf文件,并且还将包含如下所示的版本号。

TensorFlow Serving允许我们选择在进行推理请求时要使用的模型版本或“可服务”版本。每个版本都将导出到给定路径下的不同子目录,如上图所示。TensorFlow提供便利功能tf.saved_model.simple_save() ,可帮助轻松保存这些模型。

  • 托管TensorFlow服务模型服务器:在这里,将使用TensorFlow服务框架来托管保存的模型。将专注于基于本地TF Serving的CPU推断安装,还将展示如何将基于Docker容器的TF Serving实例用于GPU推断。在本文结尾,还利用TF Serving之上的Flask框架来构建自己的自定义服务API。
  • 发出服务器请求:服务器启动并运行后,可以通过gRPC或HTTP对其进行请求。对于这两种方法,通常创建带有必要内容和标头的有效负载消息,并将其发送到服务器。服务器又应返回包含预测的消息。将使用该requests模块进行HTTP请求。

主要目标-建立服装分类器

关于关键目标,将在这里简化。将基于Zalando的商品图片,在非常著名的Fashion MNIST数据集上训练模型,从而建立一个简单的服装分类器,该模型包括6万个示例的训练集和10,000个示例的测试集。每个示例都是一个28x28灰度图像,与来自10个类别的标签相关联。想法是将这些图像分类为10个类别中的服装类别,将在这些类别上训练模型。

https://github.com/zalandoresearch/fashion-mnist

Fashion-MNIST示例

在着重于模型服务之前,将在本文中构建以下两个深度学习CNN(卷积神经网络)分类器。

  • 从头开始训练的简单CNN
  • 微调经过预训练的ResNet-50 CNN

本文的目的是将更多的精力放在部署和服务方面,因此不会花很多时间讨论模型架构或训练和微调。如有必要,请随时在本文结尾处查看有关CNN的简要说明。测试本文的平台是带有NVIDIA Tesla T4 的Google Cloud Platform深度学习VM,这使得在云上进行实验变得非常容易!

https://cloud.google.com/deep-learning-vm/

加载依赖项和数据

在训练深度学习模型之前,加载必要的依赖项和数据集以训练深度学习模型。

1.14.0

在这里使用TensorFlow GPU版本1.14,但是考虑到主要关注tf.kerasAPI,可以轻松将其扩展到TensorFlow 2.0 。现在可以利用TensorFlow本身来加载Fashion-MNIST数据集。

Train_images.shape: (60000, 28, 28), of uint8

Test_images.shape: (10000, 28, 28), of uint8

根据前面提到的内容,有60000个训练图像和10000个大小的测试图像28x28。现在,将开始训练深度学习模型。

训练简单的CNN模型

在本节中,将从头开始训练基本的2层CNN模型。在训练模型之前,确实需要重塑数据,而以下代码也将处理这些数据。

Train_images.shape: (60000, 28, 28, 1), of uint8

Test_images.shape: (10000, 28, 28, 1), of uint8

还可以查看一些图像的外观,如以下快照所示。

现在,将构建基本的2层CNN模型架构。

训练模型10个时间段,然后看看其性能。

请注意,训练了90%的训练数据,并验证了10%的训练数据。性能在验证集上相当不错。让保存模型,然后检查测试数据集的性能。

测试数据集的总体模型性能为提供了91%的f1分数,这非常好!

微调预训练的ResNet-50 CNN模型

迁移学习在计算机视觉和自然语言处理领域取得了空前的成功,其预训练的模型通常会从头开始胜过训练模型。在这里,将使用ResNet-50模型,该模型通过在Fashion-MNIST数据集上进行微调而在ImageNet数据集上进行了预训练。ResNet-50模型是建立在ImageNet数据库上的50个卷积块(每个块中有几个层)的深度学习网络。该模型共有175多个层,是一个非常深的网络。ResNet代表残差网络。

将使用的ResNet-50模型包括5个阶段,每个阶段都有一个卷积和标识块。每个卷积块具有3个卷积层,每个标识块也具有3个卷积层。本节的重点将是采用预先训练的ResNet-50模型,然后对网络中的所有层进行完整的微调。将像往常一样添加常规的密集层和输出层。

该模型非常庞大,可以根据可训练参数的数量看到证据!在训练模型之前,由于ResNet模型是在彩色图像上训练的,因此需要将灰度图像转换为具有三个通道的图像。除此之外,ResNet模型可接受的最小尺寸为32x32,因此需要调整图像大小。

Train_images.shape: (60000, 32, 32, 3), of float32

Test_images.shape: (10000, 32, 32, 3), of float32

让将模型训练10个时期,现在与先前的模型相似。

请注意,与之前的模型一样,使用90%的训练数据进行训练,并使用10%的训练数据进行验证。验证集上的性能看起来要好得多。保存模型,然后检查测试数据集的性能。

总体而言,f1得分为92%,比第一个模型更好!大多数教程都将在这里结束,但是,可以说教程将在这里开始,因为启用模型服务所需的步骤从现在开始!

TensorFlow服务的保存模型

已经在模型服务方法论中对此进行了简短的讨论。要使用TensorFlow Serving服务模型,需要将其保存为SavedModel 格式。多亏了非常漂亮的tf.saved_model.simple_save(…)功能,可以在几行之内做到这一点。

在继续设置TensorFlow Serving之前,可以利用TensorFlow的SavedModel命令行界面(CLI)工具saved_model_cli,该工具对于快速检查模型的输入和输出规格很有用。

上面的输出显示了与第二种模型有关的详细信息,包括输入和输出规范。

通过CPU推论服务模型

在本部分中,将展示如何利用TensorFlow服务来利用CPU服务已保存的模型。将在系统中进行本地安装,但是建议您使用基于Docker安装的 TF Serving 安装程序,该安装程序更易于使用和维护,因为只需使用以下命令拉入容器即可,而无需设置任何配置或依赖项。

docker pull tensorflow/serving

但是,为了在此处显示不同的选项,还将显示如何在本地设置TF服务。

安装TensorFlow服务

在这里,展示了在本地安装TF Serving的必要步骤。请注意,这仅包含CPU版本。首先,添加源以获得TF服务。

代码语言:javascript
复制
!echo "deb [arch=amd64] http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal" \
| sudo tee /etc/apt/sources.list.d/tensorflow-serving.list && \
curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg \
| sudo apt-key add -

接下来,可以使用以下命令删除TF服务的现有版本(如果存在)。

代码语言:javascript
复制
!sudo apt-get -y remove tensorflow-model-server
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  tensorflow-model-server
0 upgraded, 0 newly installed, 1 to remove and 39 not upgraded.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 124893 files and directories currently installed.)
Removing tensorflow-model-server (1.13.0) ...

接下来,使用以下命令安装TF Serving

代码语言:javascript
复制
!sudo apt-get update && sudo apt-get install tensorflow-model-server
Hit:1 http://packages.cloud.google.com/apt cloud-sdk-stretch InRelease
Get:2 http://security.debian.org stretch/updates InRelease          
...
...
Preparing to unpack .../tensorflow-model-server_1.14.0_all.deb
Unpacking tensorflow-model-server (1.14.0) ...
Setting up tensorflow-model-server (1.14.0) ...

使用TensorFlow服务开始服务模型

现在,准备开始使用TF Serving服务模型。如果要自定义要提供的模型数量和其他高级配置,需要设置一个模型服务配置文件。配置文件很简单,并存储在中的以下代码段中进行了描述models.conf。请注意,要同时服务于两个模型,因此config文件使事情变得更容易。

代码语言:javascript
复制
model_config_list: {
  config: {
    name:  "fashion_model_serving",
    base_path:  "/home/jupyter/tensorflow_serving/tf_saved_models",
    model_platform: "tensorflow",
    model_version_policy {
      specific {
        versions: 1
        versions: 2
      }
    }
  }
}

可以直接在Jupyter Notebooks中运行以下代码以将服务器作为后台进程启动,也可以从终端运行它。

根据服务器日志消息,可以看到服务器已成功加载了两个模型,并且已经准备好提供服务。

服务模型推断请求

现在模型已经可以提供服务了,首先从使用第一个模型(基本的CNN)提供模型推断请求开始。

看起来TF Serving能够正确地服务于模型推断请求!请注意,在将请求发送到服务器之前,必须预处理图像并创建适当的有效负载。

看一下使用第二个模型ResNet-50 CNN为相同图像样本提供模型推理请求的情况。

看起来模型正在处理请求,并且预测比先前的模型要好!

模型预热

在生产和提供模型时,需要记住的重要一点是,TensorFlow运行时具有延迟初始化的组件,这可能导致加载后发送给模型的第一个请求的延迟较高。此延迟可能比单个推理请求的延迟高几个数量级。因此,最好在加载模型后通过发送一些样本记录作为初始请求来预热模型。可以在模型加载时通过查看以下文档来执行此操作。

在这里,将采用一种简单的方法,将示例请求发送到每个模型,以在加载后对其进行预热。为此,将一些示例数据保存在一个文件中,可以加载该文件并稍后将其用于热身模型,如以下代码所示。

Model 1 warmup complete

Model 2 warmup complete

基准化模型服务请求

看一下为一堆图像提供模型推理请求需要多长时间。为此,将考虑测试数据集中的10000张图像。请注意,仅发送单个请求,并查看整个批次的推理时间。将在下一部分中查看多个请求。看一下第一个模型的性能。

CPU times: user 7.64 s, sys: 612 ms, total: 8.26 s

Wall time: 9.76 s

Out[116]: 10000

能够在9.8秒左右的时间内完成10000张图像的推理请求,考虑到模型使用CPU进行推理,这是相当不错的。现在检查第二个模型的性能。

CPU times: user 21.6 s, sys: 1.38 s, total: 23 s

Wall time: 36.4 s

Out[122]: 10000

考虑到CPU推断,服务请求的时间为36秒,还不错!

使用GPU推论服务模型

在本部分中,将展示如何利用TensorFlow服务来利用GPU服务已保存的模型。这个想法是,如果有GPU,请使用它!将利用Docker来设置TensorFlow Serving系统。

提取TF服务GPU图像

假设已在系统或云中安装了docker。可以使用以下代码在GPU上获取最新版本的TF服务

代码语言:javascript
复制
!docker pull tensorflow/serving:latest-gpu
latest-gpu: Pulling from tensorflow/serving
Digest: sha256:fd54edb56a7b
Status: Image is up to date for tensorflow/serving:latest-gpu
docker.io/tensorflow/serving:latest-gpu

可以使用以下命令检查系统中是否存在映像

!docker images

使用Docker TensorFlow服务GPU开始服务模型

现在,准备开始使用TF Serving服务模型。将通过运行刚刚下载的docker镜像来做到这一点。实际上,最好从终端运行它。

然后,可以在Docker中使用以下命令来检查容器是否已启动并正在运行。

!docker ps -all

最后,可以检查Docker中的日志以验证一切工作正常。

!docker logs 7d4b091ccefa | tail -n 15

这证实了TF Serving将使用系统上的GPU进行推理的事实!

模型热身

可以利用之前实现的代码来预热我们的模型。在这里,将重点放在复杂的第二CNN模型上,因此对模型2进行了预热。

Model 2 warmup complete

基准化模型服务请求

让获取所有10000张测试图像,并发送一个请求以使用GPU检查模型服务时间以进行推理。请注意,此处仅关注第二模型。

CPU times: user 23.5 s, sys: 1.87 s, total: 25.3 s

Wall time: 31.3 s

Out[155]: 10000

10000张图像的总推理时间超过30秒,相当不错!现在执行一个真实的基准测试。考虑每次要分类的单个服装图像的10000个独立请求。TF Serving处理这10000个请求需要多少时间?

100%|██████████| 10000/10000 [01:55<00:00, 86.56it/s]

CPU times: user 39.1 s, sys: 2.2 s, total: 41.3 s

Wall time: 1min 55s

Out[157]: 10000

它需要一个总的115秒服务10000个请求。这意味着TF服务大约在11.5毫秒内满足每个请求。非常好!

现在尝试一个有趣的比较。将使用来自的常规model.predict(…)API调用tf.keras来查看处理10000个请求所需的时间。

100%|██████████| 10000/10000 [03:04 <00:00,54.12it / s]

CPU时间:用户3min 8s,sys:17.2 s,总计:3min 25s

挂墙时间:3min 4s

Out [159]:10000

处理10000个请求总共需要184秒。这意味着使用本机模型预测API,能够在大约18.4毫秒内满足每个请求。

这展示了利用TF服务的需求和重要性,尤其是在生产模型时!

奖励:使用Flask和TensorFlow服务构建服装分类器API

TF服务非常有用,它提供了一个高性能的系统来满足推理请求。考虑到端到端的观点,可能已经注意到模型服务不只是将一些数据作为请求转储到服务器。需要访问图像数据,对其进行预处理,然后以适当的格式将其发送到TF服务。同样,一旦获得响应,就需要访问类别概率,获取具有最大概率的类别,然后获取相应的服装类别标签。

整合所有这些步骤的最佳方法是利用Flask之类的健壮框架在TF Serving之上构建一个Web服务/ API,以接受来自现实世界的图像,执行必要的预处理,调用TF Serving,处理响应,然后将最终的JSON响应发送给最终用户。做笔记,甚至可以dockerize和部署Kubernetes的瓶API或使用WSGI服务器像Gunicorn规模并提高性能。

使用Flask创建API

将首先使用Flask创建自己的服装API,将在GitHub存储库中找到代码文件,但是为了完整和易于理解,还将在此处介绍代码。

https://github.com/dipanjanS/data_science_for_all/tree/master/gde_tf_serve_vision/tensorflow_serving

将此文件存储app.py在服务器中,该文件构成了API的基础。

启动用于TF服务的Docker容器

接下来,检查并重新启动用于TF服务的Docker容器(如果尚未启动并运行)。

!docker start 7d4b091ccefa

!docker ps -all

启动服装分类器Web服务

现在,需要启动Web服务。在生产中,建议不要使用Flask提供的默认Web服务器,而应使用像Gunicorn一样更好的生产就绪WSGI服务器。从终端使用以下命令启动Web服务。

根据需要利用多名员工来满足更多请求。现在,使用活动性测试端点检查API是否处于活动状态。

(200, 'API Live!')

使用Web服务提供服装样本分类

现在,获取一个样本真实世界图像,并尝试使用Web服务执行分类。该图像用以下代码表示。

代码语言:javascript
复制
plt.imshow(cv2.cvtColor(cv2.imread('sneaker.jpg'),    
                        cv2.COLOR_BGR2RGB))

因此,这显然是运动鞋的形象。利用API来服务于模型预测。请记住,将任何输入图像编码为Base64格式,然后对其进行解码,并在执行模型推断之前在服务器端对其进行预处理。

{'apparel_type': 'Sneaker'}

最终,以JSON响应的形式获得了正确的服装类别。事情正在按照想要的方式进行!

对Web服务进行基准测试

考虑到Web服务器的延迟,图像处理,模型推断和服务,看看现在处理10000个请求要花费多少时间。

100%|██████████| 10000/10000 [05:26<00:00, 30.66it/s]

CPU times: user 1min, sys: 3.17 s, total: 1min 4s

Wall time: 5min 26s

Out [58]: 10000

Inference time per image: 32.599999999999994 ms

能够在32.6毫秒内满足每个请求,这还不错!

结论

希望这篇篇幅冗长而又全面的文章能使对笔记本上的模型构建和原型设计与实际生产模型有很大不同。即使训练模型,也要始终想一想完整的端到端图片。一旦训练好模型,这将帮助更快地设想和实现自己的推理系统。希望这也能带来一个想法,尽管TensorFlow Serving可能看起来很复杂,但是一旦开始使用它,就可以轻松地训练,保存和提供模型,并且可以与Docker,Flask,Kubernetes等框架很好地兼容。

本文中使用的所有代码都可以在GitHub和Jupyter Notebook和必要的文件\资产。

https://github.com/dipanjanS

https://github.com/dipanjanS/data_science_for_all/tree/master/gde_tf_serve_vision/tensorflow_serving

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档