700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 搜狐新闻客户端Android端侧双擎Hybrid AI框架探索

搜狐新闻客户端Android端侧双擎Hybrid AI框架探索

时间:2020-05-11 16:57:01

相关推荐

搜狐新闻客户端Android端侧双擎Hybrid AI框架探索

本文字数:2917

预计阅读时间:24分钟

前言

人工智能,深度学习,机器学习,当今已经很广泛的应用到了手机端APP。无论是各类修图软件上的各种抠图美化,实时变装。还是社交软件的图片自动匹配文案。抑或是输入法程序和微信上的语音文字互转。以及各类消费应用上的人工智能客服,高效收集和处理客户的反馈。

——这些都用到了端侧人工智能机器学习的解决方案。

而把机器学习的结果,部署到手机端,实现端侧软件的AI化,传统解决方案有三种。让我们用一个小小的例子来看看这三种方案:

假如我们要实现一个最简单的AI功能:根据图片生成对应文案。如下图所示,当用户从图库中选择了一张电动跑车的图片,并准备发布一个原创内容feed。程序自动的识别到图片中主体构图是一辆跑车,并且扫描后台,发现有当前正在热议的社交话题,非常贴切这个图片,于是提醒用户,是否需要带上话题:

这个简单功能,为用户发的内容带来了更多的曝光机会,同时为话题运营也创造了更多的内容,一举两得。

那么,怎样实现类似的功能呢?

实现这个功能,传统的三种方案是这样的:

• 方案1.首先,客户端采集压缩图片,做预处理。然后上传图片到云端存储,云存储再利用AI服务器算力,使用物体识别,物体分类等成熟的模型识别图片中的物体,再匹配合适的文案。最后下发到客户端。

• 方案2.客户端自己训练实现一个端侧模型,大多利用类似Tensor Flow Lite,Paddle Paddle之类的支持Arm架构 cpu芯片的端侧AI框架,使用内置到应用内部的模型。需要识别物体时,由App加载AI引擎,引擎再加载预先训练好的模型,模型推演出结果以后,在手机端完成识别和展示。

• 方案3.客户端在不同系统的手机上,利用手机系统内置的AI能力,如华为手机上的EMUI内置的HiAI,调用系统接口。通常内置一些AI能力的手机,都有系统级的最优算力方案,可以调度NPU,而不是使用CPU或者GPU,可以更快速的利用系统算力完成识别,再在应用端做结果展示。

这三种方案各有缺点。

第一种,可以适配各种高低端机型,但是需要使用用户流量上传大图片,因为需要大量流量传递,所以如果需要摄像头数据逐帧处理并回显,这种方案是无法实现的,并且上传成功以后,识别也需要耗费云端的算力资源,并且还有一定的隐私风险。

第二种,一般情况可以适配大部分机型,但是会使用手机的cpu或者gpu资源,增加功耗,并且内置模型会增加客户端安装包体积。最重要的一点是,它对开发者有很高的要求,需要开发者即是人工智能算法工程师又是客户端前端工程师。

而第三种,虽然可以很好的调度npu,拥有更好的性能,并且对客户端开发者更友好,但是可用机型很少,比如HiAI,只能用在华为的部分手机上,并且不同ROM版本还有不同的AI能力。

优点整合的Hybrid AI Engine

在这个大前提下,搜狐新闻hybrid双擎AI客户端引擎框架应运而生。框架把常用的AI功能作为独立的可扩展模块,提供给上层应用开发者。利用Tensor Flow Lite和HiAI双引擎,做出决策,再由Hybrid AI Engine由速度优先,结果优先,性能优先几种模式做决策整合纠偏,最终提供给应用层推理的结果。

架构思路如下图所示

应用层和AI算法层之间,加入了一层框架适配层,应用开发者,只需要使用我们提供的AI能力接口,不需要关心这些能力,是云端实现还是客户端实现或者是手机系统实现。也不需要去专门设计训练对应的模型。更不需要考虑模型碎片化的问题,适配各种机型乃至处理器。极大的解放了应用开发者的手脚,让应用开发者专注与应用层面的创新,算法工程师专注于算法模型的训练和优化。

Talk is cheap, show me the code. 实战演示

光说不练假把式,让我们回到最初提出的例子,来实现一下识图功能。

实际的应用开者,把双擎Hybrid AI引擎编译集成到app端以后,只需要再加入下面几行代码,就可以实现从图片Bitmap中获取对应文案的功能:

AIHelperFactoryaiHelperFactory=AIHelperFactory.getInstance(context);aiHelperFactory.init(AIHelperFactory.AI_TOOL_RECOGNIZER);……if(AIHelperFactory.getInstance(context).isReady(AIHelperFactory.AI_TOOL_RECOGNIZER)){discription=AIHelperFactory.getInstance(context).getRecognizer().recognize(recognizeBitmap);}……AIHelperFactory.getInstance(context).release(AIHelperFactory.AI_TOOL_RECOGNIZER);

可以看到这个调用封装十分精简,中间的模型加载和推算已经对开发者完全透明,假如使用TensorFlowLite完成同样的工作,需要下面这段冗长的代码:

privatevoidinitModel(Contextcontext){finalContextappContext=context.getApplicationContext();ModelControler.getInstance(appContext).prepareModels(TF_MODEL_NAME,newModelControler.ModelDownloadListener(){@OverridepublicvoidonModelReady(){StringmodelPath=ModelControler.getInstance(appContext).getModelPath(TF_MODEL_NAME);recreateClassifier(appContext,modelPath);}@OverridepublicvoidonModelDownloadFailed(){//TODO:retry?}});}publicvoidrecreateClassifier(Contextcontext,StringmodelPath){if(mClassifier!=null){LOGGER.d("ClosingmClassifier.");mClassifier.close();mClassifier=null;}try{mClassifier=TFLiteObjectDetectionAPIModel.create(modelPath+TF_OD_API_MODEL_FILE,modelPath+TF_OD_API_LABELS_FILE,mInputSize,TF_OD_API_IS_QUANTIZED);mRecognizedBitmap=Bitmap.createBitmap(mInputSize,mInputSize,Bitmap.Config.ARGB_8888);}catch(finalIOExceptione){e.printStackTrace();}}privateList<Recognition>recognizeQualify(BitmapsourceBitmap){//NOTICE:thisshouldbeinvokedinworkingthreadif(mClassifier==null||mRecognizedBitmap==null){returnnull;}MatrixframeToCropTransform=ImageUtils.getTransformationMatrix(sourceBitmap.getWidth(),sourceBitmap.getHeight(),mInputSize,mInputSize,0,true);MatrixcropToFrameTransform=newMatrix();frameToCropTransform.invert(cropToFrameTransform);finalCanvascanvas=newCanvas(mRecognizedBitmap);canvas.drawBitmap(sourceBitmap,frameToCropTransform,null);List<Recognition>results=mClassifier.recognizeImage(mRecognizedBitmap);List<Recognition>qualifyResults=newArrayList<>();if(results.size()>0){for(Recognitionresult:results){if(result.getConfidence()>=MINIMUM_CONFIDENCE_TF_OD_API){qualifyResults.add(result);}}returnqualifyResults;}else{returnnull;}}@OverridepublicStringrecognize(BitmapsourceBitmap){List<Recognition>results=recognizeQualify(sourceBitmap);List<String>labels=newArrayList<>();for(Recognitionresult:results){labels.add(mTFTranslater.translate(result));}returnmDescriptionCreator.getDescription(labels);}

那么这精简调用的背后,详细是怎么实现的呢?

首先,根据需求初始化双擎AI框架,在收到客户端请求之后,会优先检查系统端有不有相近的系统级实现,如果有,会先调用系统接口,快速的返回结果。

接着会使用Tensor Flow Lite,加载对应功能的处理模型,使用客户端侧返回的结果,对系统返回结果进行补充或者纠偏。

publicstaticAIHelperFactorygetInstance(Contextcontext){if(sInstance!=null){returnsInstance;}sInstance=newAIHelperFactory(context);returnsInstance;}publicvoidinit(finalint...tools){if(HiAIUtils.isHuaweiAIAppInstalled(mContext)){VisionBase.init(mContext,newConnectionCallback(){@OverridepublicvoidonServiceConnect(){for(inttool:tools){createTools(tool);}}@OverridepublicvoidonServiceDisconnect(){release();}});}else{for(inttool:tools){createTools(tool);}}}

TFlite的模型还支持在线下载和更新。模型在线更新的机制,可以更好的缩窄应用场景,优化模型体积,同时更好的配合细化场景运营。

同样是“AI识图”的例子,用户不同时间上传同一张“山水”的风景图片,我们可以配合当前客户端正在运营的活动,配以不同的AI识图模型,给用户返回不同的结果,可以是#无人机大赛#相关的,也可以是#小长假旅游风景照#。做到差异化,精细化的为实际项目引流的作用。

接着,应用端只用直接调用初始化好的功能模块提供的识别图片方法,获取图片内容:

publicRecognizer(Contextcontext){if(HiAIUtils.isHuaweiAIAppInstalled(context)){mApi=newRecognizerHiAI(context);}else{mApi=newRecognizerTF(context);}}publicStringrecognize(Bitmapbitmap){if(mApi!=null){returnmApi.recognizeTarget(bitmap);}returnnull;}

从应用端只看到一个api的interface,实际的实现,可能是两种,HiAI或者Tensor Flow,各自实现了对应模块的功能接口:

publicclassRecognizerHiAIextendsRecognizerApi{……@OverrideprotectedStringrecognizeTarget(BitmapsourceBitmap){if(!isReady()){returnnull;}VisionImagevi=VisionImage.fromBitmap(sourceBitmap);ScenesceneResult=newScene(Scene.UNKNOWN);intresult=mSceneDetector.detect(vi,sceneResult,null);if(result!=0){Log.e(TAG,"detectfailed:"+result);returnnull;}returnmHiAITranslater.translate(sceneResult.getType());}……}publicclassRecognizerTFextendsRecognizerApi{……privateList<Recognition>recognizeQualify(BitmapsourceBitmap){//NOTICE:thisshouldbeinvokedinworkingthreadif(mClassifier==null||mRecognizedBitmap==null){returnnull;}MatrixframeToCropTransform=ImageUtils.getTransformationMatrix(sourceBitmap.getWidth(),sourceBitmap.getHeight(),mInputSize,mInputSize,0,true);MatrixcropToFrameTransform=newMatrix();frameToCropTransform.invert(cropToFrameTransform);finalCanvascanvas=newCanvas(mRecognizedBitmap);canvas.drawBitmap(sourceBitmap,frameToCropTransform,null);List<Recognition>results=mClassifier.recognizeImage(mRecognizedBitmap);List<Recognition>qualifyResults=newArrayList<>();if(results.size()>0){for(Recognitionresult:results){if(result.getConfidence()>=MINIMUM_CONFIDENCE_TF_OD_API){qualifyResults.add(result);}}returnqualifyResults;}else{returnnull;}}……}

最后,识别结束,如果不需要再识别的话,可以调用释放资源接口。释放加载到内存的模型文件,完成识别。

publicvoidrelease(finalint...tools){for(inttoolId:tools){if(toolId==AI_TOOL_RECOGNIZER||toolId==AI_TOOL_ALL){if(mRecognizer!=null){mRecognizer.release();mRecognizer=null;}}if(toolId==AI_TOOL_ID_DETECTOR||toolId==AI_TOOL_ALL){if(mIDCardDetector!=null){mIDCardDetector.release();mIDCardDetector=null;}}if(toolId==AI_TOOL_FACE_COMPARE||toolId==AI_TOOL_ALL){if(mFaceCompare!=null){mFaceCompare.release();mFaceCompare=null;}}………}}

Last but not least未来展望

客户端架构选择使用了TFlite的模型,算法工程师可以方便的把自己各种架构的模型转换成Tensor Flow Lite兼容模式。这样算法和客户端可以做到完美的解耦合,让各个领域的专家从事他们所擅长的工作,提高效率,中间的自动适配和翻译工作交给框架来维护。

除了图片识别这类基础功能,双擎AI框架还已经实现了:人脸识别,人脸比较,证件识别,语音输入…并且,各个模块完全独立,可以实时扩展更新增加新的模块。基础SDK包只有100K左右的体积,其他模块都可以通过在线下载的方式支持。对于apk本身的负担极小。

Hybrid AI Engine是端侧AI方案的一次整合,目前还在beta版本迭代开发中,这是一个开发友好度很好的支持库,应用端工程师可以不用深入了解人工智能机器学习的相关知识,也可以通过我们提供好的接口,快速的开发炫目的让人眼前一亮的“智能”的功能。真正release 1.0版本之后,我们打算彻底开源整个项目,欢迎届时大家一起来开发更多的更有意思的扩展模块。

也许你还想看

(▼点击文章标题或封面查看)

RocketMQ中台化建设

-01-14

带你实现完整的视频弹幕系统

-01-07

llvm 编译器高级用法:第三方库插桩

-12-10

【文末有惊喜!】Hive SQL血缘关系解析与应用

-12-03

如何实现图片的扭曲效果,窗帘效果及仿真水波纹效果,修图技术之瘦身瘦脸效果的实现(android-drawBitmapMesh)

-11-26

加入搜狐技术作者天团

千元稿费等你来!

???? 戳这里!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。