20行代码:Serverless架构下用Python轻松完成图像分类预测API函数实现了一个基于Serverless架构的“图像分类API”。前言图像分类是人工智能领域的热门话题。通俗的解释是一种图像处理方法,根据图像信息所反映的不同特征来区分不同类型的目标。它是利用计算机对图像进行定量分析,将图像或图像中的每个像素或区域归为几类中的某类,以代替人的视觉判读。图像分类在实际生产生活中经常遇到,针对不同的领域或需求具有很强的针对性。例如,通过拍摄花卉来识别花卉信息,通过人脸比对来比较人物信息等。通常,这些图像识别或分类工具都是在客户端采集数据,在服务器端进行计算得到结果。也就是说,一般来说,图像识别都有专门的API。比如各大云厂商都会收费为我们提供类似的能力:阿里云图像识别页面:华为云图像识别页面:本文将使用一个有趣的Python库在云函数上快速构建图像分类函数,以及API网关结合对外提供API功能,实现一个serverless架构的“图片分类API”。首先介绍一下需要的依赖库:ImageAI。通过这个依赖的官方文档,我们可以看到这样的描述:ImageAI是一个python库,旨在让开发者用几行代码就可以构建具有深度学习和计算机视觉能力的应用程序和系统。基于简单的原则,ImageAI支持最先进的机器学习算法,用于图像预测、自定义图像预测、对象检测、视频检测、视频对象跟踪和图像预测训练。ImageAI目前支持使用在ImageNet-1000数据集上训练的4种不同机器学习算法进行图像预测和训练。ImageAI还支持使用在COCO数据集上训练的RetinaNet进行对象检测、视频检测和对象跟踪。最终,ImageAI将为计算机视觉提供更广泛、更专业的支持,包括但不限于特殊环境、特殊领域的图像识别。也就是说这个依赖库可以帮助我们完成基本的图像识别和视频目标提取。虽然他给出了一些数据集和模型,但是我们也可以根据自己的需要进行额外的训练和定制的扩展。Throughtheofficialcode,wecanseeasimpledemo:#-*-coding:utf-8-*-fromimageai.PredictionimportImagePrediction#Modelloadingprediction=ImagePrediction()prediction.setModelTypeAsResNet()prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()predictions,probabilities=prediction.predictImage("./picture.jpg",result_count=5)foreachPrediction,eachProbabilityinzip(predictions,probabilities):print(str(eachPrediction)+":"+str(eachProbability))当我们指定的picture.jpg图片为:我们在执行之后的结果是:laptop:71.43893241882324notebook:16.265612840652466modem:4.899394512176514hard_disc:4.007557779550552mouse:1.2981942854821682如果在使用过程中觉得模型resnet50_weights_tf_dim_ordering_tf_kernels.h5istoolargeandtakestoolong,youcanchoosethemodelaccordingtoyourneeds:SqueezeNet(filesize:4.82MB,shortestpredictiontime,moderateaccuracy)ResNet50byMicrosoftResearch(filesize:98MB,fasterpredictiontime,accuracyHigh)InceptionV3byGoogleBrainteam(filesize:91.6MB,slowpredictiontime,higheraccuracy)DenseNet121byFacebookAIResearch(filesize:31.6MB,slowerpredictiontime,highestaccuracy)modeldownloadaddresscanrefertoGithubaddress:https://github.com/OlafenwaMo...或者参考ImageAI官方文档:https://imageai-cn.readthedoc...该项目是serverless的。根据函数计算的要求,编写入口方法并完成工程初始化,同时在当前工程下创建文件夹model,并将模型文件复制到该文件夹??下:工程总体流程:实现代码:#-*-编码:utf-8-*-fromimageai.PredictionimportImagePredictionimportjsonimportuuidimportbase64importrandom#ResponseclassResponse:def__init__(self,start_response,response,errorCode=None):self.start=start_responseresponseBody={'Error':{"Code":errorCode,"Message":response},}iferrorCodeelse{'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=[('内容-type','application/json;charset=UTF-8')]self.start(status,response_headers)yieldself.response。编码(“UTF-8”)#随机字符串randomStr=lambdanum=5:"".join(random.sample('abcdefghijklmnopqrstuvwxyz',num))#模型加载print("Initmodel")prediction=ImagePrediction()prediction.setModelTypeAsResNet()print(“加载模型”)prediction.setModelPath(“/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5”)prediction.loadModel()打印(“加载完成”)defhandler(environ,start_response):尝试:request_body_size=int(environ。get('CONTENT_LENGTH',0))except(ValueError):request_body_size=0requestBody=json.loads(environ['wsgi.input'].read(request_body_size).decode("utf-8"))#图片获取打印("获取图片")imageName=randomStr(10)imageData=base64.b64decode(requestBody["image"])imagePath="/tmp/"+imageNamewithopen(imagePath,'wb')asf:f.write(imageData)#内容预测print("Predicting...")result={}predictions,probabilities=prediction.predictImage(imagePath,result_count=5)print(zip(predictions,probabilities))foreachPrediction,eachProbabilityinzip(predictions,probabilities):result[str(eachPrediction)]=str(eachProbability)returnResponse(start_response,result)所需的依赖项:tensorflow==1.13.1numpy==1.19。4scipy==1.5.4opencv-python==4.4.0.46pillow==8.0.1matplotlib==3.3.3h5py==3.1.0keras==2.4.3imageai==2.1.5编写部署所需的配置文件:ServerlessBookImageAIDemo:Component:fcProvider:alibabaAccess:releaseProperties:Region:cn-beijingService:Name:ServerlessBook描述:ServerlessbookcaseLog:AutoNas:Auto功能:Name:serverless_imageAI描述:图片对象检测CodeUri:Src:./src排除:-src/.fun-src/model处理程序:index.handler环境:-键:PYTHONUSERBASE值:/mnt/auto/.fun/python内存大小:3072运行时:python3超时:60触发器:-名称:ImageAI类型:HTTPPparameters:AuthType:ANONYMOUSMethods:-GET-POST-PUTDomains:-Domain:Auto在代码和配置中可以看到目录存在:/mnt/auto/,其实就是nas挂载后的地址,只需要提前写到代码中即可。接下来的环节就是nas的创建和挂载点配置的具体操作。项目部署和测试。完成以上步骤后,可以通过:sdeploy部署项目,部署完成可以看到结果:部署完成后,可以通过:sinstalldocker安装依赖:依赖安装完成后,可以看到目录下生成了.fun目录。该目录是docker打包的依赖文件。这些依赖正是我们在requirements.txt文件中声明的依赖。完成后我们可以通过:snassync./src/.fun将依赖目录打包上传到nas中,成功之后再打包上传model目录:snassync./src/model完成后我们可以通过:snasls--all查看目录详情:完成后我们可以写一个脚本进行测试,也适用于刚才的测试图片,通过代码:importjsonimporturllib.requestimportbase64importtimewithopen("picture.jpg",'rb')asf: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.0077565602660179”,“鼠标”:“1.2981869280338282828282828287”}函数计算耗时较长,但顺利返回预期结果。快30s了,我们再执行一下测试脚本:{"Response":{"laptop":"71.43893837928772","notebook":"16.2656143330768585","modem"“:”4.899385944008827“,“HARD_DISC”:“4.007565602660179”,“鼠标”:“1.29818692803828287”}只用了1.15秒,比上次多了28秒项目优化在上一轮测试中,我们可以看到项目第一次启动和第二次启动的耗时差异,其实这个时间差异主要是由于加载模型的功能浪费了很长时间。Evenlocally,wecansimplytest:#-*-coding:utf-8-*-importtimetimeStart=time.time()#Modelloadingfromimageai.PredictionimportImagePredictionprediction=ImagePrediction()prediction.setModelTypeAsResNet()prediction.setModelPath("resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()print("LoadTime:",time.time()-timeStart)timeStart=time.time()predictions,probabilities=prediction.predictImage("./picture.jpg",result_count=5)foreachPrediction,eachProbabilityinzip(predictions,probabilities):print(str(eachPrediction)+":"+str(eachProbability))print("PredictTime:",time.time()-timeStart)执行结果:LoadTime:5.549695014953613laptop:71.43893241882324notebook:16.265612840652466modem:4.899394512176514hard_disc:4.007557779550552mouse:1.2981942854821682PredictTime:0.8137111663818359可以看到,在加载imageAI模块以及加载模型文件的过程中,一共耗时5.5秒,在预测Somearelessthan1secondlong.Infunctioncomputing,theperformanceofthemachineitselfisnotashighasmylocalperformance.Atthistime,inordertoavoidthelongresponsetimecausedbyloadingthemodeleachtime,inthedeployedcode,youcanseethatthemodelloadingprocessisactuallyplacedintheOutsidetheentrymethod.这样做的一个好处是每次执行项目时不一定都冷启动,也就是说可以在某些复用的前提下复用一些对象,即不需要重新加载模型和导入每次依赖等。所以在实际项目中,为了避免频繁请求,重复加载实例,创建某些资源,我们可以在初始化的时候放一些资源。这样一来,项目的整体性能可以得到很大的提升。同时,借助厂商提供的预留容量,基本可以消除功能冷启动带来的负面影响。总结近年来,人工智能和云计算的发展突飞猛进。在Serverless架构下,传统的人工智能项目如何运行,逐渐成为很多人需要了解的事情。本文主要介绍一个通过已有的依赖库(ImageAI)进行图像分类和预测的接口。通过这个例子,可以明确几件事:Serverless架构可以运行人工智能相关的项目;Serverless很好的兼容Tensorflow等机器学习/深度学习工具;虽然函数计算本身有空间限制,但实际上加入硬盘挂载能力后,函数计算本身的能力会得到极大的扩展。当然,这篇文章也算是一个介绍。希望看完这篇文章后,读者可以发挥自己的想象力,将更多的AI项目与Serverless架构进一步结合起来。作者:姜瑜原文链接
