20行代码:Serverless架构下用Python轻松搞定图像分类和预测

简介: 图像分类是人工智能领域的一个热门话题。通俗解释就是,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。图像分类在实际生产生活中也是经常遇到的,而且针对不同领域或者需求有着很强的针对性。例如通过拍照花朵识别花朵信息,通过人脸匹对人物信息等。

前言

图像分类是人工智能领域的一个热门话题。通俗解释就是,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。图像分类在实际生产生活中也是经常遇到的,而且针对不同领域或者需求有着很强的针对性。例如通过拍照花朵识别花朵信息,通过人脸匹对人物信息等。

通常情况下,这些图像识别或者分类的工具,都是在客户端进行数据采集,在服务端进行运算获得结果,也就是说一般情况下都是有专门的API实现图像识别的。例如各大云厂商都会为我们有偿提供类似的能力:

阿里云图像识别页面:

华为云图像识别页面:

本文将会通过一个有趣的Python库,快速将图像分类的功能搭建在云函数上,并且和API网关结合,对外提供API功能,实现一个Serverless架构的"图像分类API"。

首先和大家据介绍一下需要的依赖库:ImageAI。通过该依赖的官方文档我们可以看到这样的描述:

ImageAI是一个python库,旨在使开发人员能够使用简单的几行代码构建具有包含深度学习和计算机视觉功能的应用程序和系统。

ImageAI本着简洁的原则,支持最先进的机器学习算法,用于图像预测,自定义图像预测,物体检测,视频检测,视频对象跟踪和图像预测训练。ImageAI目前支持使用在ImageNet-1000数据集上训练的4种不同机器学习算法进行图像预测和训练。ImageAI还支持使用在COCO数据集上训练的RetinaNet进行对象检测,视频检测和对象跟踪。 最终,ImageAI将为计算机视觉提供更广泛和更专业化的支持,包括但不限于特殊环境和特殊领域的图像识别。

也就是说这个依赖库,可以帮助我们完成基本的图像识别和视频的目标提取,虽然他给了一些数据集和模型,但是我们也可以根据自身需要对其进行额外的训练,进行定制化拓展。通过官方给的代码,我们可以看到一个简单的Demo:

# -*- coding: utf-8 -*-

from imageai.Prediction import ImagePrediction


# 模型加载

prediction = ImagePrediction()

prediction.setModelTypeAsResNet()

prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")

prediction.loadModel()


predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5 )

for eachPrediction, eachProbability in zip(predictions, probabilities):

   print(str(eachPrediction) + " : " + str(eachProbability))

当我们指定的picture.jpg图片为:

我们在执行之后的结果是:

laptop : 71.43893241882324

notebook : 16.265612840652466

modem : 4.899394512176514

hard_disc : 4.007557779550552

mouse : 1.2981942854821682

如果在使用过程中觉得模型resnet50_weights_tf_dim_ordering_tf_kernels.h5过大,耗时过长,可以按需求选择模型:

  • SqueezeNet(文件大小:4.82 MB,预测时间最短,精准度适中)
  • ResNet50 by Microsoft Research (文件大小:98 MB,预测时间较快,精准度高)
  • InceptionV3 by Google Brain team (文件大小:91.6 MB,预测时间慢,精度更高)
  • DenseNet121 by Facebook AI Research (文件大小:31.6 MB,预测时间较慢,精度最高)

模型下载地址可参考Github地址:https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0,或者参考ImageAI官方文档:https://imageai-cn.readthedocs.io/zh_CN/latest/ImageAI_Image_Prediction.html

项目 Serverless 化

将项目按照函数计算的需求,编写好入口方法,以及做好项目初始化,同时在当前项目下创建文件夹model,并将模型文件拷贝到该文件夹:

项目整体流程:

实现代码:

# -*- coding: utf-8 -*-


from imageai.Prediction import ImagePrediction

import json

import uuid

import base64

import random



# Response

class Response:

   def __init__(self, start_response, response, errorCode=None):

       self.start = start_response

       responseBody = {

           'Error': {"Code": errorCode, "Message": response},

       } if errorCode else {

           'Response': response

       }

       # 默认增加uuid,便于后期定位

       responseBody['ResponseId'] = str(uuid.uuid1())

       print("Response: ", json.dumps(responseBody))

       self.response = json.dumps(responseBody)


   def __iter__(self):

       status = '200'

       response_headers = [('Content-type', 'application/json; charset=UTF-8')]

       self.start(status, response_headers)

       yield self.response.encode("utf-8")



# 随机字符串

randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', num))


# 模型加载

print("Init model")

prediction = ImagePrediction()

prediction.setModelTypeAsResNet()

print("Load model")

prediction.setModelPath("/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5")

prediction.loadModel()

print("Load complete")



def handler(environ, start_response):

   try:

       request_body_size = int(environ.get('CONTENT_LENGTH', 0))

   except (ValueError):

       request_body_size = 0

   requestBody = json.loads(environ['wsgi.input'].read(request_body_size).decode("utf-8"))


   # 图片获取

   print("Get pucture")

   imageName = randomStr(10)

   imageData = base64.b64decode(requestBody["image"])

   imagePath = "/tmp/" + imageName

   with open(imagePath, 'wb') as f:

       f.write(imageData)


   # 内容预测

   print("Predicting ... ")

   result = {}

   predictions, probabilities = prediction.predictImage(imagePath, result_count=5)

   print(zip(predictions, probabilities))

   for eachPrediction, eachProbability in zip(predictions, probabilities):

       result[str(eachPrediction)] = str(eachProbability)


   return Response(start_response, result)

所需要的依赖:

tensorflow==1.13.1

numpy==1.19.4

scipy==1.5.4

opencv-python==4.4.0.46

pillow==8.0.1

matplotlib==3.3.3

h5py==3.1.0

keras==2.4.3

imageai==2.1.5

编写部署所需要的配置文件:

ServerlessBookImageAIDemo:

 Component: fc

 Provider: alibaba

 Access: release

 Properties:

   Region: cn-beijing

   Service:

     Name: ServerlessBook

     Description: Serverless图书案例

     Log: Auto

     Nas: Auto

   Function:

     Name: serverless_imageAI

     Description: 图片目标检测

     CodeUri:

       Src: ./src

       Excludes:

         - src/.fun

         - src/model

     Handler: index.handler

     Environment:

       - Key: PYTHONUSERBASE

         Value: /mnt/auto/.fun/python

     MemorySize: 3072

     Runtime: python3

     Timeout: 60

     Triggers:

       - Name: ImageAI

         Type: HTTP

         Parameters:

           AuthType: ANONYMOUS

           Methods:

             - GET

             - POST

             - PUT

           Domains:

             - Domain: Auto


在代码与配置中,可以看到有目录:/mnt/auto/的存在,该部分实际上是nas挂载之后的地址,只需提前写入到代码中即可,下一个环节会进行nas的创建以及挂载点配置的具体操作。

项目部署与测试

在完成上述步骤之后,可以通过:

s deploy

进行项目部署,部署完成可以看到结果:

完成部署之后,可以通过:

s install docker

进行依赖的安装:

依赖安装完成可以看到在目录下生成了.fun的目录,该目录就是通过docker打包出来的依赖文件,这些依赖正是我们在requirements.txt文件中声明的依赖内容。

完成之后,我们通过:

s nas sync ./src/.fun

将依赖目录打包上传到nas,成功之后再将model目录打包上传:

s nas sync ./src/model

完成之后可以通过:

s nas ls --all

查看目录详情:

完成之后,我们可以编写脚本进行测试,同样适用刚才的测试图片,通过代码:

import json

import urllib.request

import base64

import time


with open("picture.jpg", 'rb') as f:

   data = base64.b64encode(f.read()).decode()


url = 'http://35685264-1295939377467795.test.functioncompute.com/'


timeStart = time.time()

print(urllib.request.urlopen(urllib.request.Request(

   url=url,

   data=json.dumps({'image': data}).encode("utf-8")

)).read().decode("utf-8"))

print("Time: ", time.time() - timeStart)


可以看到结果:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "1d74ae7e-298a-11eb-8374-024215000701"}

Time:  29.16020894050598

可以看到,函数计算顺利地返回了预期结果,但是整体耗时却超乎想象,有近30s,此时我们再次执行一下测试脚本:

{"Response": {"laptop": "71.43893837928772", "notebook": "16.265614330768585", "modem": "4.899385944008827", "hard_disc": "4.007565602660179", "mouse": "1.2981869280338287"}, "ResponseId": "4b8be48a-298a-11eb-ba97-024215000501"}

Time:  1.1511380672454834

可以看到,再次执行的时间仅有1.15秒,比上次整整提升了28秒之多。

项目优化

在上一轮的测试中可以看到,项目首次启动和二次启动的耗时差距,其实这个时间差,主要是函数在加载模型的时候浪费了及长的时间。

即使在本地,我们可以简单测试:

# -*- coding: utf-8 -*-


import time


timeStart = time.time()


# 模型加载

from imageai.Prediction import ImagePrediction


prediction = ImagePrediction()

prediction.setModelTypeAsResNet()

prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")

prediction.loadModel()

print("Load Time: ", time.time() - timeStart)

timeStart = time.time()


predictions, probabilities = prediction.predictImage("./picture.jpg", result_count=5)

for eachPrediction, eachProbability in zip(predictions, probabilities):

   print(str(eachPrediction) + " : " + str(eachProbability))

print("Predict Time: ", time.time() - timeStart)

执行结果:

Load Time:  5.549695014953613

laptop : 71.43893241882324

notebook : 16.265612840652466

modem : 4.899394512176514

hard_disc : 4.007557779550552

mouse : 1.2981942854821682

Predict Time:  0.8137111663818359

可以看到,在加载imageAI模块以及加载模型文件的过程中,一共耗时5.5秒,在预测部分仅有不到1秒钟的时间。而在函数计算中,机器性能本身就没有我本地的性能高,此时为了降低每次装载模型导致的响应时间过长,在部署的代码中,可以看到模型装载过程实际上是被放在了入口方法之外,这样做的一个好处是,项目每次执行的时候,不一定会有冷启动,也就是说在某些复用的前提下是可以复用一些对象的,即无需每次都重新加载模型,导入依赖等。

所以在实际项目中,为了避免频繁请求,实例重复装载、创建某些资源,我们可以将部分资源放在初始化的时候进行。这样可以大幅度提高项目的整体性能,同时配合厂商所提供的预留能力,可以基本上杜绝函数冷启动带来的负面影响。

总结

近年来,人工智能与云计算的发展是突飞猛进,在Serverless架构中,如何运行传统的人工智能项目已经逐渐成为很多人所需要了解的事情了。本文是通过一个已有的依赖库(ImageAI)实现一个图像分类和预测的接口。通过这个例子,其实是有几个事情可以被明确的:

  • Serverless架构可以运行人工智能相关项目
  • Serverless可以很好的兼容Tensorflow等机器学习/深度学习的工具
  • 虽然说函数计算本身有空间限制,但是实际上增加了硬盘挂在能力之后,函数计算本身的能力将会得到大幅度的拓展

当然,本文也算是抛砖引玉,希望读者在本文之后,可以发挥自己的想象,将更多的AI项目与Serverless架构进行进一步结合

相关实践学习
【AI破次元壁合照】少年白马醉春风,函数计算一键部署AI绘画平台
本次实验基于阿里云函数计算产品能力开发AI绘画平台,可让您实现“破次元壁”与角色合照,为角色换背景效果,用AI绘图技术绘出属于自己的少年江湖。
从 0 入门函数计算
在函数计算的架构中,开发者只需要编写业务代码,并监控业务运行情况就可以了。这将开发者从繁重的运维工作中解放出来,将精力投入到更有意义的开发任务上。
目录
相关文章
|
3月前
|
运维 监控 数据可视化
Python 网络请求架构——统一 SOCKS5 接入与配置管理
通过统一接入端点与标准化认证,集中管理配置、连接策略及监控,实现跨技术栈的一致性网络出口,提升系统稳定性、可维护性与可观测性。
|
6月前
|
设计模式 SQL 人工智能
Python设计模式:从代码复用到系统架构的实践指南
本文以Python为实现语言,深入解析23种经典设计模式的核心思想与实战技巧。通过真实项目案例,展示设计模式在软件开发中的结构化思维价值,涵盖创建型、结构型、行为型三大类别,并结合Python动态语言特性,探讨模式的最佳应用场景与实现方式,帮助开发者写出更清晰、易维护的高质量代码。
305 1
|
6月前
|
设计模式 人工智能 算法
Python设计模式:从代码复用到系统架构的实践指南
本文探讨了电商系统中因支付方式扩展导致代码臃肿的问题,引出设计模式作为解决方案。通过工厂模式、策略模式、单例模式等经典设计,实现代码解耦与系统扩展性提升。结合Python语言特性,展示了模块化、装饰器、适配器等模式的实战应用,并延伸至AI时代的设计创新,帮助开发者构建高内聚、低耦合、易维护的软件系统。
362 0
|
4月前
|
设计模式 人工智能 API
AI智能体开发实战:17种核心架构模式详解与Python代码实现
本文系统解析17种智能体架构设计模式,涵盖多智能体协作、思维树、反思优化与工具调用等核心范式,结合LangChain与LangGraph实现代码工作流,并通过真实案例验证效果,助力构建高效AI系统。
585 7
|
5月前
|
机器学习/深度学习 算法 文件存储
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
神经架构搜索(NAS)正被广泛应用于大模型及语言/视觉模型设计,如LangVision-LoRA-NAS、Jet-Nemotron等。本文回顾NAS核心技术,解析其自动化设计原理,探讨强化学习、进化算法与梯度方法的应用与差异,揭示NAS在大模型时代的潜力与挑战。
1323 6
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
|
9月前
|
数据采集 运维 Serverless
云函数采集架构:Serverless模式下的动态IP与冷启动优化
本文探讨了在Serverless架构中使用云函数进行网页数据采集的挑战与解决方案。针对动态IP、冷启动及目标网站反爬策略等问题,提出了动态代理IP、请求头优化、云函数预热及容错设计等方法。通过网易云音乐歌曲信息采集案例,展示了如何结合Python代码实现高效的数据抓取,包括搜索、歌词与评论的获取。此方案不仅解决了传统采集方式在Serverless环境下的局限,还提升了系统的稳定性和性能。
282 0
|
9月前
|
存储 运维 Serverless
千万级数据秒级响应!碧桂园基于 EMR Serverless StarRocks 升级存算分离架构实践
碧桂园服务通过引入 EMR Serverless StarRocks 存算分离架构,解决了海量数据处理中的资源利用率低、并发能力不足等问题,显著降低了硬件和运维成本。实时查询性能提升8倍,查询出错率减少30倍,集群数据 SLA 达99.99%。此次技术升级不仅优化了用户体验,还结合AI打造了“一看”和“—问”智能场景助力精准决策与风险预测。
844 69
|
8月前
|
机器学习/深度学习 算法 测试技术
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析
本文探讨了基于图的重排序方法在信息检索领域的应用与前景。传统两阶段检索架构中,初始检索速度快但结果可能含噪声,重排序阶段通过强大语言模型提升精度,但仍面临复杂需求挑战
280 0
图神经网络在信息检索重排序中的应用:原理、架构与Python代码解析
|
8月前
|
数据采集 运维 监控
Serverless爬虫架构揭秘:动态IP、冷启动与成本优化
随着互联网数据采集需求的增长,传统爬虫架构因固定IP易封禁、资源浪费及扩展性差等问题逐渐显现。本文提出基于Serverless与代理IP技术的新一代爬虫方案,通过动态轮换IP、弹性调度任务等特性,显著提升启动效率、降低成本并增强并发能力。架构图与代码示例详细展示了其工作原理,性能对比数据显示采集成功率从71%提升至92%。行业案例表明,该方案在电商情报与价格对比平台中效果显著,未来有望成为主流趋势。
324 0
Serverless爬虫架构揭秘:动态IP、冷启动与成本优化
|
9月前
|
Cloud Native Serverless 流计算
云原生时代的应用架构演进:从微服务到 Serverless 的阿里云实践
云原生技术正重塑企业数字化转型路径。阿里云作为亚太领先云服务商,提供完整云原生产品矩阵:容器服务ACK优化启动速度与镜像分发效率;MSE微服务引擎保障高可用性;ASM服务网格降低资源消耗;函数计算FC突破冷启动瓶颈;SAE重新定义PaaS边界;PolarDB数据库实现存储计算分离;DataWorks简化数据湖构建;Flink实时计算助力风控系统。这些技术已在多行业落地,推动效率提升与商业模式创新,助力企业在数字化浪潮中占据先机。
499 12

相关产品

  • 函数计算
  • 推荐镜像

    更多