深度学习模型最佳部署⽅式:⽤Python实现HTTP服务器作
API接⼝
在苹果系统下,如果⽂章中的图⽚不能正常显⽰,请升级Safari浏览器到最新版本,或者使⽤Chrome、Firefox浏览器打开。)
当训练和测试完成⼀个深度学习模型之后,如果我们打算将这个算法模型上线,投⼊⽣产环境部署使⽤,那么我们就需要做⼀些额外的处理⼯作。由于深度学习模型对于算⼒需求较⼤,在上线过程中,⼀般有减⼩⽹络规模、使⽤专⽤硬件和通过C/S架构联⽹进⾏云端计算这三种⽅式。AI柠檬博主推荐使⽤第三种⽅式,即模型部署于服务器端,客户端通过⽹络将输⼊数据发送⾄服务器,计算得结果后传递给客户端。5G时代就在眼前,IPv6协议⼤规模部署,万物即将互联,尤其是⽆线移动互联⽹作为重要的基础设施是⼤势所趋。通过联⽹,即使是成本最低的低端的硬件,也可以在不损失精度的情况下,能够以更快的速度得到深度学习模型的计算结果。例如,ASRT语⾳识别系统就是以这种⽅式进⾏模型的部署的,已经能够为AI柠檬⽹站提供语⾳识别服务,⽤于语⾳搜索等任务。
1 都有哪些模型部署⽅式
1.1 减⼩⽹络规模再移植
通常来讲,我们训练得到的模型规模都很⼤,曾有类似MobileNet等⽅式,直接构建成⼀个轻量级的神经⽹络,直接移植到⽤户终端的移动设备和其他嵌⼊式硬件中,或将原有的⼤规模⽹络进⾏剪枝,保存为⼀个精简版模型。这样得到的模型的准确率不会⽐原⽹络差太多,同时却能⼤⼤减少计算开销,提⾼运⾏速度。
不过这样做不仅仅是会有⼀定精度损失这么简单,模型的剪枝过程同样很繁琐,确定如何剪枝和剪枝到什么程度也是需要做很多⼯作的。⽽且,模型还存在移植问题,⽤PyTorch训练的模型会⽐⽤TensorFlow的需要做更多的⼯作量,⽽其他框架则更甚,因为⾕歌
有“TensorFlow全家桶”。TensorFlow官⽅发布有⽀持Go语⾔的库,以⽤于⾼效运⾏模型的推理,还有其Lite版本(TensorLite),以⽤于模型在移动端的运⾏,并且除了Python外,还⽀持Java、Swift、Object-C等语⾔。即使这样,移植的过程也很繁琐,需要⼤量参照TensorFlow的⽂档,还存在硬件设备的兼容性问题。
总之,不论怎么做,都等于为了解决⼀个问题⽽引⼊了⼀堆新的问题,不论怎么看都不划算。
1.2 为设备使⽤专⽤硬件
这种⽅式最适合禁⽌联⽹或者⽆法连接⽹络的环境。有哪些地⽅是不能(两种含义)连接互联⽹络的
呢?⼤家懂的都懂。⽽⼀旦没有联⽹的限制,使⽤专⽤硬件是不划算的,⽬前最重要的是综合成本⾼,性价⽐低,不仅仅存在上⼀节所说的模型移植各项成本问题,还存在硬件成本问题。当前专⽤硬件成本较⾼,虽然⼀般据说可以⽐GPU的速度更快,但是⼀个专⽤硬件价格⽐普通GPU还要贵,却只能⽤来计算深度学习模型,⽽且移植的时候还需要适配硬件⽽编程。⼀个典型的例⼦就是FPGA,⽽据了解⼀些公司的相关专⽤硬件成本很⾼。
1.3 基于⽹络采⽤C/S架构进⾏云端计算
“C/S” 架构即软件体系结构中的经典架构模型——“客户端/服务器”架构,⼀个典型的C/S架构常常采⽤MVC模式,即:模型(Model)、视图(View)、控制器(Controller)。
图1 MVC模式⽰意图
以下是来⾃菜鸟教程中对MVC模式的讲解:
Model(模型) – 模型代表⼀个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
View(视图) – 视图代表模型包含的数据的可视化。
Controller(控制器) – 控制器作⽤于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。
通过联⽹,使⽤C/S架构,可以使得我们将⼀个完整的深度学习模型的计算部署于⾼性能的服务器上,客户端⽆需使⽤昂贵的设备,连接⽹络,即可享受AI带来的便捷。这样⼀来,只需要在云端部署少量⾼性能计算服务器,⼤量的廉价硬件和设备都可以使⽤模型计算推理,综合成本很低。这样的部署⽅式,使得客户端不再需要⼤量昂贵的硬件,避免了闲置计算资源的浪费,也避免了模型移植的⼈⼒物⼒成本。
2 为什么要⽤HTTP服务⽅式
我们已经确定应当采⽤联⽹的C/S架构作为深度学习模型的部署会更好,⽽C/S架构还有很多种具体的实现,AI柠檬博主在这⾥还要再推荐使⽤HTTP协议来做。为什么是HTTP协议呢?
因为HTTP协议是⼀个使⽤最⼴泛、兼容性最好、功能上⼏乎可以适⽤于任何场景的应⽤层⽹络协议。各种形式基于浏览器的⽹站就是⼀个例⼦,但基于浏览器的⽹站是“B/S”架构,也就是“浏览器/服务器”架构,⽽我们这⾥只说C/S架构。
2.1 什么是HTTP
HTTP是超⽂本传输协议(Hyper Text Transfer Protocol),是基于TCP/IP协议之上的应⽤层协议,⼀般认为是⽆连接和⽆状态的。HTTP协议有GET、POST、PUT、DELETE等请求⽅式,对应着查、增、改、删这⼏种操作,最常⽤的是前两种。我们⼀般打开⽹页⽤的是GET请求,如果有提交数据,⽐如注册登陆、发布⽂章和评论等,⼀般就是⽤POST请求了,因为GET请求存在URL最⼤长度限制,⽽POST请求⼀般没有。所以,⽤POST请求向服务器上传图⽚、语⾳和视频等数据,然后服务器进⾏深度学习计算给我们返回结果,是最适合不过了。
HTTP⼀般是⽆连接⽆状态的,但我们在需要时也可以实现为有状态的,⽐如⽤户的注册登陆,我们都知道,当登陆之后,我们才可以使⽤我们⾃⼰的账号发布⽂章和评论之类。⽽这种有连接、有状态可以通过HTTP协议中的Cookie和Session实现。Cookie存储于⽤户端(⽐如浏览器端),Session存储
于服务器端(HTTP服务软件或者数据库都可以),⼀般情况下两者是⼀起使⽤的。
对于⼤量的深度学习模型的计算,通常是上下⽂⽆关的,⽐如识别图⽚1上的所有⼈和图⽚2上的所有⼈,我们⼀般不需要使⽤Cookie和Session实现上下⽂关联的状态和连接。不过有时也是需要的,⽐如机器问答系统,通常需要考虑与⽤户过去⼀段时间内所交谈内容的上下⽂语境,或者长时间、长篇⽂本的语⾳识别,这时可以进⾏有连接有状态的处理,⽽这也只需要Cookie + Session即可。
2.2 基于HTTP协议部署的好处
AI柠檬博主刚才说过,HTTP使⽤很⼴泛,⼏乎所有编译器都有可⽤的库实现,⽽且协议是标准化的,不存在协议实现不⼀致的问题,是经过时间和实践考验的,有⼤量的现成的软件以及库。⽽且使⽤HTTP协议时,弹性伸缩很容易实现,甚⾄不需要额外写代码,现成的Nginx服务器⼀个配置⽂件全套搞定!
图2 ⼀个⾼性能深度学习推理计算服务器集架构⽰意图
⽐如启动⼀个HTTP服务器⽤于深度学习模型计算,⼀台服务器不够⽤,那么我们就可以启动100台,IP地址设为192.168.1.100到192.168.1.199(也可以同⼀台机器上监听100个不同的端⼝,需要服务器
性能够好),然后填⼊这100个IP地址,使⽤Nginx通过UpStream反向代理这100台服务器,把每⼀次计算请求通过轮询的⽅式转发给这100台服务器中的⼀台。假如⼀次识别需要1秒,那么⼀台服务器1秒就只能识别1次,通过Nginx负载均衡之后,这样的⼀个服务器集,1秒就可以识别100次,将吞吐率从1提⾼到100!AI柠檬博主在部署ASRT语⾳识别API服务器时,⽬前就采⽤这种⽅式,后端部署了若⼲(N)服务器,将语⾳识别吞吐率提⾼到了原来的N倍。
因此,通过C/S架构,我们只需要将深度学习推理计算部署于服务器,其他的功能实现仍然保留在终端,使得AI算法模型能够以低成本、⾼效率的模式落地,结合云计算,能够进⼀步降低企业的总成本。菜鸟教程python函数
2.3 为什么不推荐⽤私有应⽤协议
不推荐私有协议的原因主要在于这是私有协议,对于企业的软件⼯程开发和管理能⼒有着⼀定的要求。基于TCP/IP再开发新的协议容易有缺陷,⽽协议的缺陷会导致各种问题出现,⽽协议版本的更新更容易导致兼容问题。如果有⾜够的开发能⼒,倒可以试试。
3 为什么推荐使⽤原⽣HTTP库,⽽不是Django和Flask
Django和Flask分别是2005年和2010年发布的⽤于Web⽹站开发的Python库,这两个框架有其特定的
⽤法,有着额外的学习成本,并且作为API服务器,很多特性我们并不需要关注。⽽直接使⽤Python原⽣HTTP库,我们只需要编写⼀个HTTP服务⼦类代码,实现处理GET和POST请求的⽅法就⾏,语法上还是熟悉的味道。
4 Python实现⼀个HTTP服务程序样例,并⽀持IPv6
本节我们介绍⼀个⽤Python实现处理API请求的HTTP服务器Demo,并让其⽀持IPv6协议。
apiserver.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: AI柠檬
某深度学习模型API的HTTP服务器程序
"""
import http.server
import urllib
class TestHTTPHandle(http.server.BaseHTTPRequestHandler):
def setup(self):
http.server.BaseHTTPRequestHandler.setup(self)
def _set_response(self):
self.send_response(200) #设定HTTP服务器请求状态200
self.send_header('Content-type', 'text/html') #设定HTTP服务器请求内容格式d_headers()
def do_GET(self):
buf = 'AI柠檬深度学习模型计算API服务'
self.protocal_version = 'HTTP/1.1'
self._set_response()
buf = bytes(buf,encoding="utf-8") #编码转换
self.wfile.write(buf) #写出返回内容
def do_POST(self):
'''
处理通过POST⽅式传递过来并接收的输⼊数据并计算和返回结果
'''
path = self.path #获取请求的URL路径
print(path)
#获取post提交的数据
datas = ad(int(self.headers['content-length']))
#datas = urllib.unquote(datas).decode("utf-8", 'ignore')
datas = datas.decode('utf-8')
'''
输⼊数据已经存储于变量“datas”⾥,这⾥可插⼊⽤于深度学习计算的处理代码等假设计算结果存储于变量“buf”⾥
'''
self._set_response()
buf = bytes(buf,encoding="utf-8")
self.wfile.write(buf) #向客户端写出返回结果
启⽤IPv6协议⽀持的改造,在上述代码之后添加:
import socket
class HTTPServerV6(http.server.HTTPServer):
address_family = socket.AF_INET6
def start_server(ip, port):
if(':' in ip):
http_server = HTTPServerV6((ip, port), TestHTTPHandle)
else:
http_server = http.server.HTTPServer((ip, int(port)), TestHTTPHandle)
print('服务器已开启')
try:
http_server.serve_forever() #设置⼀直监听并接收请求
except KeyboardInterrupt:
pass
http_server.server_close()
print('HTTP server closed')
这个HTTPServerV6就是⼀个⽀持IPv6协议的服务器程序,为了能够在纯IPv4和⽀持IPv6的两种情况下切换,我们只需要实现start_server()函数作为启动⼊⼝即可,在任何想启动服务端程序的地⽅调⽤它。例如:
if __name__ == '__main__':
start_server('', 20000) # For IPv4 Network Only
#start_server('::', 20000) # For IPv6 Network
5 应⽤实例:ASRT语⾳识别API服务器是如何⼯作的
ASRT语⾳识别系统实现API服务器程序的代码是:
如上述所说,⾸先在HTTP Server类的代码外部添加深度学习相关的初始化代码:
import keras
from SpeechModel251 import ModelSpeech
from LanguageModel import ModelLanguage
datapath = './'
modelpath = 'model_speech/'
ms = ModelSpeech(datapath)
ms.LoadModel(modelpath + 'm251/speech_model251_e_0_del')
ml = ModelLanguage('model_language')
ml.LoadModel()
然后在处理POST请求得到的输⼊数据后⾯添加深度学习计算代码:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论