当前位置: 首页 > 科技观察

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

时间:2023-03-12 20:59:22 科技观察

转载请联系Serverless公众号。前言图像分类是人工智能领域的热门话题。通俗的解释是一种图像处理方法,根据图像信息所反映的不同特征来区分不同类型的目标。它是利用计算机对图像进行定量分析,将图像或图像中的每个像素或区域归为几类中的某类,以代替人的视觉判读。图像分类在实际生产生活中经常遇到,针对不同的领域或需求具有很强的针对性。例如,通过拍摄花卉来识别花卉信息,通过人脸比对来比较人物信息等。通常,这些图像识别或分类工具都是在客户端采集数据,在服务器端进行计算得到结果。也就是说,一般来说,图像识别都有专门的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,youcanchooseamodelaccordingtoyourneeds:SqueezeNet(filesize:4.82MB,shortestpredictiontime,moderateaccuracy)ResNet50byMicrosoftResearch(filesize:98MB,fasterpredictiontime,highaccuracy)InceptionV3byGoogleBrainteam(filesize:91.6MB,slowpredictiontime,higheraccuracy)DenseNet121byFacebookAIResearch(filesize:31.6MB,slowerpredictiontime,highestaccuracy)ModeldownloadaddresscanrefertoGithub地址:https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0或参考ImageAI官方文档:https://imageai-cn.readthedocs.io/zh_CN/latest/ImageAI_Image_Prediction.htmlProjectServerless将项目根据函数计算的要求,编写入口方法,初始化项目。同时在当前工程下创建文件夹model,将模型文件复制到该文件夹??下:工程总体流程:实现代码:#-*-coding:utf-8-*-fromimageai.PredictionimportImagePredictionimportjsonimportuuidimportbase64importrandom#ResponseclassResponse:def__init__(self,start_response,response,errorCode=None):self.start=start_responseresponseBody={'Error':{"Code":errorCode,"Message}",:}iferrorCodeelse{'Response':response}#默认添加uuid方便后期定位'200'response_headers=[('Content-type','application/json;charset=UTF-8')]self.start(status,response_headers)yieldself.response.encode("utf-8")#randomstringrandomStr=lambdanum=5:"".join(random.sample('abcdefghijklmnopqrstuvwxyz',num))#模型加载print("Initmodel")prediction=ImagePrediction()prediction.setModelTypeAsResNet()print("Loadmodel")prediction.setModelPath("/mnt/auto/model/resnet50_weights_tf_dim_ordering_tf_kernels.h5")prediction.loadModel()print("Loadcomplete")defhandler(environ,start_response):try: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"))#图片获取print("Getpucture")imageName=randomStr(10)imageData=base64.b64decode(requestBody["image"])imagePath="/tmp/"+imageNamewithopen(imagePath,'wb')asf:f.write(imageData)#内容预测打印("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:ServerlessBookDescription:ServerlessbookcaseLog:AutoNas:AutoFunction:Name:serverless_imageAIDescription:ImageobjectdetectionCodeUri:Src:./srcExcludes:-src/.fun-src/modelHandler:index.handlerEnvironment:-Key:PYTHONUSERBASEValue:/mnt/auto/.fun/pythonMemorySize:3072Runtime:python3Timeout:60Triggers:-Name:ImageAIType:HTTPParameters:AuthType:ANONYMOUSMethods:-GET-POST-PUTDomains:-Domain:Auto在代码和配置中可以看到目录:/mnt/auto的存在/的,这部分其实就是nas挂载后的地址,代码中只需要写inadvance,接下来的环节就是nas的创建和挂载点配置的具体操作项目部署及测试完成以上步骤后,就可以通过:sdeploy来部署项目,部署完成后可以看到结果:部署完成后,可以通过:sinstalldocker安装依赖:依赖安装完成后完成后,可以看到在目录下生成了。fun的目录,是docker打包的依赖文件。这些依赖正是我们在requirements.txt文件中声明的依赖。完成后我们通过:snassync./src/.fun打包上传依赖目录到nas,成功后再打包上传model目录:snassync./src/model完成后可以通过:查看目录详情:snasls--all:complete之后我们可以写一个脚本进行测试,也适用于刚才的测试图片,通过代码: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()-timeStart)可以看到结果:{"Response":{"laptop":"71.43893837928772","notebook":"16.265614330768585","modem":"4.899385944008827","hard_disc":"4.007565602660179","mouse288:"83}6"ResponseId":"1d74ae7e-298a-11eb-8374-024215000701"}蒂姆e:29.16020894050598可以看出函数计算成功返回了预期的结果,但是花了将近30秒,但我们再次执行了测试脚本:{"Response":{"laptop":"71.43893837928772","notebook":"16.265614330768585","modem":"4.899385944008827","hard_disc":"4.007565602660179","mouse":"1.2981869280338287"},"ResponseId":"4b8be48a-298a-11eb-ba97-024215000501"}时间:1.1511380672454834可以在1.5秒内看到并再次执行相比提升了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)executionresult:LoadTime:5.549695014953613laptop:71.43893244188232notebook:16.265612840652466modem:4.899394512176514hard_disc:4.007557779550552mouse:1.2981942854821682PredictTime:0.8137111663818359可以看到,在加载imageAI模块以及加载模型文件的过程中,一共耗时5.5秒,在预测部分仅有不到1秒钟的时间。Infunctioncomputing,theperformanceofthemachineitselfisnotashighasmylocalperformance.Atthistime,inordertoavoidthelongresponsetimecausedbyloadingthemodeleachtime,inthedeployedcode,youcanseethatthemodelloadingprocessisactuallyplacedintheOutsidetheentrymethod.这样做的一个好处是每次执行项目时不一定都冷启动,也就是说可以在某些复用的前提下复用一些对象,即不需要重新加载模型和导入每次依赖等。所以在实际项目中,为了避免频繁请求,重复加载实例,创建某些资源,我们可以在初始化的时候放一些资源。这样一来,项目的整体性能可以得到很大的提升。同时,借助厂商提供的预留容量,基本可以消除功能冷启动带来的负面影响。总结近年来,人工智能和云计算的发展突飞猛进。在Serverless架构下,传统的人工智能项目如何运行,逐渐成为很多人需要了解的事情。本文主要介绍一个通过已有的依赖库(ImageAI)进行图像分类和预测的接口。通过这个例子,可以明确几件事:Serverless架构可以运行人工智能相关的项目;Serverless很好的兼容Tensorflow等机器学习/深度学习工具;虽然函数计算本身有空间限制,但实际上加入硬盘挂载能力后,函数计算本身的能力会得到极大的扩展。当然,这篇文章也算是一个介绍。希望看完这篇文章后,读者可以发挥自己的想象力,将更多的AI项目与Serverless架构进一步结合起来。ServerlessDevsServerlessDevs是一个开源开放的serverless开发者平台,致力于为开发者提供强大的工具链体系。通过该平台,开发者可以一键体验多云Serverless产品,快速部署Serverless项目。Github地址:https://github.com/serverless-devsGitee地址:https://gitee.com/organizations/serverless-devs/projectsServerlessDevs官网:https://www.serverless-devs.com