使用函数 initializer 接口优化深度学习场景下模型加载的冷启动延时

本文涉及的产品
简介: 背景 深度学习场景使用函数计算典型案例 阿里云 函数计算 客户 码隆科技 是一家专注于深度学习与计算机视觉技术创新的公司。当码隆的客户上传大量图像数据后,需要尽快把图像按照客户指定的方式处理,包括商品识别,纺织面料等柔性材质识别分析,内容审查,以图搜图等等。

背景

深度学习场景使用函数计算典型案例

阿里云 函数计算 客户 码隆科技 是一家专注于深度学习与计算机视觉技术创新的公司。当码隆的客户上传大量图像数据后,需要尽快把图像按照客户指定的方式处理,包括商品识别,纺织面料等柔性材质识别分析,内容审查,以图搜图等等。图像处理基于码隆预先训练好的深度学习模型,要求在短时间内准备大量的计算资源进行大规模并行处理。客户将深度学习推理逻辑实现为函数,在函数中加载模型后对图像数据进行处理。通过函数计算提供的大规模计算能力,客户能够短时间处理大量图像,平稳应对峰值压力。更多详细案例请见 函数计算客户案例

深度学习场景的客户在使用函数计算服务中更希望平台做哪些改进?

深度学习场景下加载模型是主要的应用层冷启动开销,模型的规格多为 500MB+,应用层冷启动开销往往会导致毛刺的产生,为归避这类问题,函数计算引入了 initializer 接口来解决应用层冷启动开销带来的毛刺问题。

功能简介

Initializer 编程模式为用户提供了 initializer 入口定义,便于用户将业务逻辑分为initializer函数请求处理函数两部分。函数计算使用容器执行用户函数代码,这样的执行环境我们称之为函数实例。函数实例会在启动的时候能够自动执行 initializer 函数,进行业务层冷启动,成功之后,该实例收到用户的 Invoke 请求,就能够执行用户的请求处理函数了。

引入 initializer 接口的优势:

  • 分离初始化逻辑和请求处理逻辑,程序逻辑更清晰,让用户更易写出结构良好,性能更优的代码;
  • 用户函数代码更新时,系统能够保证用户函数的平滑升级,规避应用层初始化冷启动带来的性能损耗。新的函数实例启动后能够自动执行用户的初始化逻辑,在初始化完成后再处理请求;
  • 在应用负载上升,需要增加更多函数实例时,系统能够识别函数应用层初始化的开销,更精准的计算资源伸缩的时机和所需的资源量,让请求延时更加平稳;
  • 即使在用户有持续的请求且不更新函数的情况下,FC系统仍然有可能将已有容器回收或更新,这时没有平台方(FC)的冷启动,但是会有业务方冷启动,Initializer 的引入可以最大限度减少这种情况;

案例实践

本实践以 函数计算部署机器学习遇到的问题和解法 这篇文章为基础,做了进一步改造和优化。下文将按照以下几个步骤讲解如何利用函数计算以高性能、低延时玩转深度学习场景下的识别手写数字案例:

安装依赖

训练模型

首先需要训练预期的模型,模型的训练可参考 这篇文章。按照文章中的步骤下载 MINIST 数据库和相关代码并开始训练模型,训练时长持续半小时左右,训练成功后的结构目录如下,其中 model_data 目录下的文件便是通过训练得到的模型。

project root
├── main.py
├── grf.pb
└── model_data
    ├── checkpoint
    ├── model.data-00000-of-00001
    ├── model.index
    └── model.meta

应用依赖的安装

本案例需要安装的应用依赖有 tensorflowopencv-python,模型的训练和函数的处理逻辑都强依赖这两个库,训练模型可在本地直接操作,通过 pip 在本地安装两个依赖库即可,版本不限。由于函数运行在函数计算(FC)系统同样依赖这两个库,需要提前下载好依赖并打包上传到 OSS。推荐使用 fcli 工具的 sbox 命令,下面以 runtime 为 python2.7 进行操作:

目前 Pypi 上 tensorflow 最新版本为 1.11.0,为避免因版本问题影响您的实践,建议安装 1.8.0 版本。

cd <'此项目的根目录中'>
mkdir applib      // 创建存储所有应用依赖的目录
fcli shell        // fcli version >= 0.24
sbox -d applib -t python2.7
pip install -t $(pwd) tensorflow==1.8.0
pip install -t $(pwd) opencv-python

完成之后 exit 退出沙盒环境,并执行 exit 退出fcli。

上传依赖

依赖和模型下载成功后需要进行压缩并上传到 OSS 中,以便后面函数可以直接从 OSS 下载即可,在项目的根目录执行下面两条命令可以得到 applib.zipmodel_data.zip 两个 zip 压缩包。

cd applib && zip -r applib.zip * && mv applib.zip ../ ; cd ..
cd model_data && zip -r model_data.zip * && mv model_data.zip ../ ; cd ..

下面提供了一个简单的上传 zip 包到 OSS 的模版,上传成功后删除本地的依赖和模型目录即可。

# -*- coding: utf-8 -*-
import oss2

auth = oss2.Auth(<'Your access_key_id'>, <'Your access_key_secret'>)
bucket = oss2.Bucket(auth, <'Your endpoint'>, <'Your bucket'>)
bucket.put_object_from_file('applib.zip', <'Your applib.zip path'>)
bucket.put_object_from_file('model_data.zip', <'Your model_data.zip path'>)

将机器学习应用迁移至函数计算

如何将本地机器学习应用进行改造并迁移到函数计算的流程在 将机器学习应用迁移至函数计算 中有详细的步骤,这篇文章中的改造并没有 initializer 的概念,您只需要关注 index.py 和 loader.py 是如何产生的,详细代码链接,改造后的目录结构如下,其中 index.py 存放了机器学习相关逻辑的代码,loader.py 存放了函数入口和加载依赖逻辑的代码。

project root
└─── code
    ├── loader.py
    └── index.py
    └── pic
        └── e2.jpg

e2.jpg 只是文章中提供的一个简单的数字 2 图片,如做验证性测试需要更多的素材可以通过 keras.js 平台手动绘制生成。

30321e3e7b260c558ddae712ca13e293.png

引入 initializer 接口

经过应用迁移处理后得到了一个可以运行在函数计算服务上的函数,很明显可以看到函数入口 loader.handler 中首先需要从 OSS 加载应用依赖(tensorflow、opencv)和资源依赖(模型),加载的过程都属于应用层冷启动,冷启动所耗费的时间在一定程度上和所需依赖的大小规格成正比。为避免后续处理逻辑受到应用层冷启动延时的影响,这里将加载依赖逻辑放入 initializer 函数中。

其中 index.py 文件保持不变,loader.py 文件需要进行如下改造:

  • 添加 initializer 函数,initializer 入口便为 loader.initializer。
  • 将对 download_and_unzip_if_not_exist 的调用从 handler 中更换到 initializer 函数中。

loader.py 经过改造后的代码如下:

# -*- coding:utf-8 -*-
import sys
import zipfile
import os
import oss2
import imp
import time

app_lib_object = os.environ['AppLibObject']
app_lib_dir = os.environ['AppLibDir']
model_object = os.environ['ModelObject']
model_dir = os.environ['ModelDir']

local = bool(os.getenv('local', ""))
print 'local running: ' + str(local)

def download_and_unzip_if_not_exist(objectKey, path, context):
    creds = context.credentials
    if (local):
        print 'thank you for running function in local!!!!!'
        auth = oss2.Auth(creds.access_key_id,
                         creds.access_key_secret)
    else:
        auth = oss2.StsAuth(creds.access_key_id,
                            creds.access_key_secret,
                            creds.security_token)

    endpoint = os.environ['Endpoint']
    bucket = os.environ['Bucket']

    print 'objectKey: ' + objectKey
    print 'path: ' + path
    print 'endpoint: ' + endpoint
    print 'bucket: ' + bucket

    bucket = oss2.Bucket(auth, endpoint, bucket)

    zipName = '/tmp/tmp.zip'

    print 'before downloading ' + objectKey + ' ...'
    start_download_time = time.time()
    bucket.get_object_to_file(objectKey, zipName)
    print 'after downloading, used %s seconds...' % (time.time() - start_download_time)

    if not os.path.exists(path):
        os.mkdir(path)

    print 'before unzipping ' + objectKey + ' ...'
    start_unzip_time = time.time()
    with zipfile.ZipFile(zipName, "r") as z:
        z.extractall(path)
    print 'unzipping done, used %s seconds...' % (time.time() - start_unzip_time)

def initializer(context):
    if not local:
        download_and_unzip_if_not_exist(app_lib_object, app_lib_dir, context)
        download_and_unzip_if_not_exist(model_object, model_dir, context)
    sys.path.insert(1, app_lib_dir)

def handler(event, context):
    desc = None
    fn, modulePath, desc = imp.find_module('index')
    mod = imp.load_module('index', fn, modulePath, desc)
    request_handler = getattr(mod, 'handler')
    return request_handler(event, context)

部署

本地开发已经完成,下面借助阿里云函数计算的工具 fun 可以进行一键部署,Fun 是一个用于支持 Serverless 应用部署的工具,它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作,步骤如下:

  • release 页面对应平台的 binary 版本,解压就可以使用。或者使用 npm install @alicloud/fun * -g 也可以直接使用。
  • 使用 fun config 配置 ak、region 等信息。
  • 编写 template.yml
  • fun deploy 部署

template.yml 文件如下:

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  tensorflow: # 服务名
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'tensorflow demo'
      Policies:
        - AliyunOSSReadOnlyAccess
    initializer: # 函数名
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: loader.handler  # 处理函数入口
        Initializer: loader.initializer  # initializer 入口
        CodeUri: ./code/
        Description: 'tensorflow application!'
        Runtime: python2.7
        MemorySize: 1024
        Timeout: 300
        InitializationTimeout: 60
        EnvironmentVariables:
          Bucket: test-bucket # 替换为自己的 oss bucket
          Endpoint: 'https://oss-cn-hangzhou.aliyuncs.com' # 替换掉 OSS Endpoint
          AppLibObject: applib.zip
          AppLibDir: /tmp/applib
          ModelObject: model_data.zip
          ModelDir: /tmp/model
  • 执行 fun deploy 会显示如下信息,部署成功后可到对应 region 下查看部署是否生效。
    image.png

测试

功能测试

登陆函数计算 控制台 对应 region 下找到所创建的函数,连续执行两次查看执行结果如下。

  • 首次执行
    image.png
  • 第二次执行
    image.png

从以上图片可以看到首次函数执行时间为 3793ms,第二次函数执行时间为 810ms,执行结果都为 the predict is 2 ,从执行结果可以确认函数执行正确,但性能真的提高了吗?下面会有简单的性能测试做对比。

性能测试

这里对改造前的函数做同样的测试:

  • 首次执行
    image.png
  • 首次执行日志
    image.png
  • 第二次执行
    image.png

从以上图片可以看到首次函数执行时间为 17506ms,第二次函数执行时间为 815ms,通过日志可以发现首次触发函数执行大约 13s 花费在加载模型和依赖库上,函数的执行时间会随着模型和依赖库规格的增大而增大。由此可见,initializer 函数的引入会使得函数实例在首次启动时规避冷启动开销,降低函数执行时间,提高函数性能,并且不会对后续的请求产生任何影响。

总结

通过将深度学习场景下规格较大的模型、依赖库的加载等初始化逻辑进行提取放到 initializer 函数中可以极大的提升函数性能,规避用户系统/函数升级带来的冷启动开销,帮助用户实现业务系统的热升级。

最后欢迎大家通过扫码加入我们用户群中,使用过程中有问题或者有其他问题可以在群里提出来。函数计算官网客户群(11721331)。

参考文章:

1 :Tensorflow MINIST数据模型的训练,保存,恢复和手写字体识别
2:函数计算部署机器学习遇到的问题和解法

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
相关文章
|
3天前
|
机器学习/深度学习 算法 调度
深度学习|改进两阶段鲁棒优化算法i-ccg
深度学习|改进两阶段鲁棒优化算法i-ccg
|
1天前
|
机器学习/深度学习 数据可视化 PyTorch
使用Python实现深度学习模型:变分自编码器(VAE)
使用Python实现深度学习模型:变分自编码器(VAE)
8 2
|
1天前
|
机器学习/深度学习 人工智能 边缘计算
基于深度学习的图像识别优化策略研究
【5月更文挑战第17天】 在当前的信息时代,图像识别技术作为人工智能领域的一个重要分支,已经广泛应用于医疗诊断、自动驾驶、安防监控等多个行业。随着技术的不断进步,深度学习模型在图像识别任务中取得了显著的成果。然而,随之而来的是对计算资源的大量需求以及实时处理的挑战。本文针对现有深度学习模型在图像识别任务中的资源消耗和响应速度问题,提出了一种结合模型压缩与知识蒸馏的优化策略。通过深入分析模型结构与参数特性,实现在保持高准确率的同时降低模型复杂度,提高运算效率。本研究不仅对推动高效图像识别技术的发展具有重要意义,同时也为其他计算密集型应用提供了可行的优化思路。
|
1天前
|
机器学习/深度学习 数据可视化 PyTorch
使用Python实现深度学习模型:生成对抗网络(GAN)
使用Python实现深度学习模型:生成对抗网络(GAN)
17 3
|
1天前
|
机器学习/深度学习 数据采集 算法
利用深度学习优化图像识别流程
【5月更文挑战第16天】 在现代技术环境中,图像识别的精准度和速度是衡量一个系统性能的关键指标。随着深度学习技术的不断进步,通过构建和训练更加复杂的神经网络模型来提高图像识别的准确性已成为可能。本文将探讨如何利用深度学习优化图像识别流程,包括数据预处理、模型选择、训练策略及推理加速等方面,以期达到更高的识别精度和更快的处理速度。
10 0
|
2天前
|
机器学习/深度学习 数据可视化 PyTorch
使用Python实现深度学习模型:自动编码器(Autoencoder)
使用Python实现深度学习模型:自动编码器(Autoencoder)
8 0
|
3天前
|
机器学习/深度学习 自然语言处理 算法
利用深度学习优化图像识别精度的策略
【5月更文挑战第15天】 在计算机视觉领域,图像识别的精确度直接关系到后续处理的效果与可靠性。本文旨在探讨如何通过深度学习技术提升图像识别任务的精度。首先,文中介绍了卷积神经网络(CNN)的基础结构及其在图像识别中的应用;然后,详细分析了数据增强、网络结构优化、正则化方法和注意力机制等策略对提高模型性能的作用;最后,通过实验验证了所提策略的有效性,并讨论了未来可能的研究方向。本文不仅为图像识别领域的研究者提供了实用的优化策略,也为相关应用的开发者指明了提升系统性能的可能途径。
|
3天前
|
机器学习/深度学习 自动驾驶 算法
利用深度学习优化图像识别在自动驾驶系统中的应用
【5月更文挑战第15天】 随着自动驾驶技术的不断进步,图像识别作为其核心技术之一,对准确性和实时性的要求日益提高。本文旨在探讨如何通过深度学习算法优化图像识别流程,进而提升自动驾驶系统的整体性能。文中首先回顾了当前自动驾驶领域中图像识别面临的挑战,接着介绍了几种先进的深度学习模型及其在图像处理中的应用,最后提出了一个结合这些模型的优化框架,并对其潜在的改进效果进行了分析。
|
3天前
|
机器学习/深度学习 人工智能 测试技术
深度学习中损失函数和激活函数的选择
深度学习中损失函数和激活函数的选择
6 0
|
3天前
|
机器学习/深度学习 数据采集 人工智能
深度学习中的大模型「幻觉」问题:解析、原因及未来展望
深度学习中的大模型「幻觉」问题:解析、原因及未来展望
12 0

热门文章

最新文章


http://www.vxiaotou.com