文章目录
一、定义与目的
模型部署是指将大模型运行在专属的计算资源上,使模型在独立的运行环境中高效、可靠地运行,并为业务应用提供推理服务。其目标是将机器学习模型应用于实际业务中,使最终用户或系统能够利用模型的输出,从而发挥其作用。
二、模型部署
1.部署步骤
- 导出模型:将训练好的模型导出为可部署的格式。
- 部署模型:将导出的模型部署到生产环境中,通常是以一个服务或一个库的形式。
- 测试模型:在生产环境中对模型进行测试,以确保其能够正常工作,并且输出结果符合预期。
- 监控模型:在生产环境中对模型进行监控,以便及时发现并解决问题。
2.部署方式
模型的部署方式多种多样,可以根据具体的应用场景和需求而定。以下是一些常见的模型部署方式:
- 云端部署:将模型部署到云端服务器上,通过API接口提供服务,实现远程调用。这种方式可以实现大规模的分布式计算和存储,同时提供高可用性和可扩展性。在云端部署中,需要考虑数据的安全性和隐私保护,以及模型的并发处理能力。
- 嵌入式设备部署:将模型部署到嵌入式设备中,如智能手机、智能音箱、智能家居等。这种方式可以实现本地化的智能化应用,具有实时性、低延迟的优点。在嵌入式设备部署中,需要考虑设备的计算能力、存储空间等限制,以及模型的轻量化设计。
- 边缘计算部署:将模型部署到边缘设备上,如路由器、摄像头等。这种方式可以实现本地数据的实时处理和智能化分析,减少数据传输的延迟和成本。在边缘计算部署中,需要考虑设备的计算能力和数据处理能力,以及模型的实时性要求。
- 移动端部署:将模型部署到移动端设备上,如智能手机、平板电脑等。这种方式可以实现移动设备的智能化应用,提高用户体验。在移动端部署中,需要考虑设备的功耗和性能限制,以及模型的轻量化设计。
- FPGA和GPU部署:FPGA(Field-Programmable Gate Array)部署是将深度学习模型部署到FPGA芯片上,实现高效的硬件加速,提高模型的运行速度和效率。GPU(Graphics Processing Unit)部署是将深度学习模型部署到GPU上,利用GPU的并行计算能力,提高模型的运行速度和效率。这两种方式适用于对计算性能要求较高的场景,如实时图像处理、视频分析等。
三、框架对比
Django、Pyramid和Flask都是Python中流行的Web框架,它们各自具有独特的优点和缺点。
1.Django
优点:
- 功能全面:Django是一个“全包式”的框架,提供了丰富的内置功能,如ORM(对象关系映射)、用户认证、内容管理等,非常适合快速开发。
- 文档完善:Django的官方文档非常详细,易于理解,对于新手来说非常友好。
- 社区支持强大:Django拥有一个庞大的社区和大量的第三方包可供选择,这使得开发者能够轻松地找到解决方案和支持。
- 安全性高:Django具有集成的安全功能,如防止跨站请求伪造(CSRF)和SQL注入攻击的机制,能够最大程度地保护系统的安全性。
缺点:
- 学习曲线较陡:对于初学者来说,Django提供的功能可能会显得过于复杂,需要一定的时间去学习和掌握。
- 灵活性较低:由于Django的全包式设计,它在一些情况下可能不如其他框架灵活。
- 性能问题:在处理高负载应用程序时,Django的性能可能不如一些轻量级的框架。
2.Pyramid
优点:
- 灵活性和可扩展性:Pyramid的设计哲学是“尽可能少地强制开发人员做出选择”,它提供了一组基本的工具和功能,但允许开发人员根据项目需求选择使用的组件和库。
- 高性能:Pyramid在设计上注重性能,采用了一些优化技术,如延迟加载和缓存机制,以提供快速响应和高并发处理能力。
- 适用于大型应用程序:由于Pyramid的灵活性和可扩展性,它非常适合构建大型和复杂的Web应用程序。
缺点: - 社区及资源相对较少:与Django和Flask相比,Pyramid的社区和第三方资源可能较少。
- 学习曲线:虽然Pyramid提供了灵活的选择,但对于初学者来说,可能需要更多的时间来理解和选择适合项目的组件和库。
3.Flask
优点:
- 轻量级:Flask是一个轻量级的框架,代码量少,灵活性高,适合快速开发小型应用程序。
- 简单易学:Flask的设计理念简洁明了,入门相对容易,对于初学者来说非常友好。
- 可扩展性强:Flask提供了丰富的扩展库,开发者可以根据需求选择合适的扩展来扩展功能。
- 社区支持良好:Flask有一个庞大的社区,提供了丰富的资源和支持。
缺点: - 功能相对较少:相比于一些大型框架如Django,Flask的功能相对较少,需要依赖扩展库来实现一些功能。
- 安全性考虑:由于Flask的轻量级特性,安全性方面的考虑需要开发者自行关注。
- 不适合大型应用:由于Flask的轻量级特性,它可能不适合开发大型复杂的应用程序。
综上所述,Django、Pyramid和Flask各有其优缺点,选择哪个框架取决于项目的具体需求、开发者的偏好和经验水平。
四、代码实现
下面为大家提供一个基于Flask框架的Web服务的代码,该服务使用PyTorch加载了一个预训练的ResNet18模型,并对用户上传的图像进行分类预测。
1.服务端代码
(1)初始化flask并定义全局变量
import io
import flask # 自己安装
import torch
import torch.nn.functional as F
from PIL import Image
from torch import nn
from torchvision import transforms, models, datasets
# 初始化Flask app
app = flask.Flask(__name__) # #创建一个新的Flask应用程序实例
model = None
use_gpu = False
导入必要库(注意确保所以库都以安装,未安装可以使用pip命令安装),然后创建一个Flask应用实例app,定义model用于存储加载的模型、use_gpu用于指示是否使用GPU进行模型推理。
(2)加载模型
def load_model():
global model
# 加载resent18网络
model = models.resnet18()
num_ftrs = model.fc.in_features
model.fc = nn.Sequential(nn.Linear(num_ftrs, 102))
checkpoint = torch.load('best.pth')
model.load_state_dict(checkpoint['state_dict'])
# 将模型指定为测试格式
model.eval()
# 是否使用gpu
if use_gpu:
model.cuda()
- load_model函数加载了一个预训练的ResNet18模型,并修改了最后的全连接层以适应102个分类(类别数自己根据自己任务来)。
- 从best.pth文件中加载模型权重(best.pth文件可以通过链接: https://pan.baidu.com/s/1RFNufQoLzuDZasgBdE7MdQ?pwd=qbw1 提取码: qbw1 获取)。
- 设置模型为评估模式。
- 如果use_gpu为真,则将模型移至GPU。
(3)图像预处理
def prepare_image(image, target_size):
if image.mode != 'RGB':
image = image.convert('RGB')
image = transforms.Resize(target_size)(image)
image = transforms.ToTensor()(image)
image = transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])(image)
image = image[None]
if use_gpu:
image = image.cuda()
return torch.tensor(image)
prepare_image函数接收一个PIL图像和目标尺寸,将图像转换为RGB模式(如果尚未转换),调整图像大小,并将其转换为张量,进行标准化,并通过判断移至GPU。
(4)预测端点
@app.route('/predict', methods=['POST'])
def predict():
# #做一个标志,刚开始无图像传入时为false,传入图像时为true
data = {
'success': False}
if flask.request.method == 'POST': # 如果收到请求
if flask.request.files.get("image"):
image = flask.request.files['image'].read() # 将收到的图像进行读取,内容为二进制
image = Image.open(io.BytesIO(image))
# 利用上面的预处理函数将读入的图像进行预处理
image = prepare_image(image, traget_size=(224, 224))
preds = F.softmax(model(image), dim=1) # 得到各个类别的概率
results = torch.topk(preds.cpu().data, k=3, dim=1) # 概率最大的前3个结果
results = (results[0].cpu().numpy(), results[1].cpu().numpy())
# 将data字典增加一个key,value,其中value为list格式
data['predictions'] = list()
for prob, label in zip(results[0][0], results[1][0]):
r = {
'label': str(label), 'probability': float(prob)}
data['predictions'].append(r)
data['success'] = True
return flask.jsonify(data) # json类型可以被多种语言解析
- /predict端点设计为接收POST请求,其中包含要分类的图像。
- 如果请求成功且包含图像文件,则读取图像,调用上述函数进行预处理,并通过模型进行推理。
- 通过torch.topk获取预测结果的前三个最高概率的类别和相应的概率,将结果以JSON格式返回。
(5)主程序运行
if __name__ == '__main__':
print('Loading PyTorch model and Flask starting server ...')
print('Please wait until server has fully started')
load_model()
app.run(port='5012')
# app.run(host='192.000.00.00', port='5012')
2.客服端代码
import requests
flask_url = 'http://127.0.0.1:5012/predict'
def predict_result(image_path):
image = open(image_path, 'rb').read()
payload = {
'image': image}
r = requests.post(flask_url, files=payload).json()
# 向flask_urL服务发送一个POST请求,并尝试将返回的JSON响应解析为一个Puthon字典
if r['success']:
for (i, result) in enumerate(r['predictions']):
print('{}.预测类别为{}:的概率:{}'.format(i + 1, result['label'], result['probability']))
else:
print('Request failed')
if __name__ == '__main__':
predict_result('./train/6/image_07163.jpg')
3.总结
这部分代码片段主要讲述了服务端打开端口,然后客户端向运行在上述服务器上的Flask应用发送HTTP POST请求,以预测给定图像的分类。在客户端运行之前,我们需要先运行服务端代码,将端口打开,以便能够接收客户端发送的请求。这里展示的是本机发送请求,如果想发送请求到A电脑,需要另一台电脑运行服务端代码,并将服务端主程序运行注释部分取消注释,将IP地址更改为A电脑的IP,然后B电脑即可运行客户端代码,注意,这里客户端IP也应改为A电脑IP。