深度学习-模型部署

一、定义与目的

模型部署是指将大模型运行在专属的计算资源上,使模型在独立的运行环境中高效、可靠地运行,并为业务应用提供推理服务。其目标是将机器学习模型应用于实际业务中,使最终用户或系统能够利用模型的输出,从而发挥其作用。

二、模型部署

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。

猜你喜欢

转载自blog.csdn.net/2301_77698138/article/details/143128419