使用Flask实现本机的模型部署

前言

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

一、设置客户端

  1. 运行之前要先运行服务端
  2. url里写入本机ip和端口,后面跟上端口名
  3. 以二进制形式读取图片创建payload字典
  4. 向上面的url服务器发送post请求,传入字典文件
  5. 将返回的json文件解析成字典
python 复制代码
import requests

# url和端口写成自己的端口
flask_url = "http://192.168.24.39: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响应解析为一个字典。
    # print(r)
    if r["success"]:
        # 输出结果
        for (i, result) in enumerate(r['predictions']):
            print(f"{i + 1}.预测类别为{result['label']}:{result['probability']}")
    else:
        print('Request failed')


if __name__ == '__main__':
    predict_result('./35/image_06975.jpg')

输出:

二、设置服务端

  1. 服务端初始化一个Flask对象,命名app
  2. @app.route("/predict", methods="POST") 定义了一个路由 以POST方式发送到/predict的请求都会进入下方的函数
  3. 下方函数处理完之后返回flask.jsonify(data),json文件
python 复制代码
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应用程序实例
# __name__参数通常被传递给FasK应用程序来定位应用程序的根路径,这样Flask就可以知道在哪里找到模板、静态文件等。
# 总体来说app = flask.Flask(__name__)是FLaSK应用程序的起点。它初始化了一个新的Flask应用程序实例。为后续添加路由、配置等奠定了基础

model = None
use_gpu = False


# 加载模块进来
def load_model():
    global model
    # 加载resnet18网络
    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()

    if use_gpu:
        model.cuda()


# 数据预处理
def prepare_image(image, target_size):
    # 针对不同模型 image的格式不同 但需要统一到RGB格式
    if image.mode != 'RGB':
        image = image.convert('RGB')

    # (按照所使用的模型将输入图片的尺寸修改,并转为tensor)
    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)

    # 增加一个维度  用于batch测试
    image = image[None]  # torch 的写法
    if use_gpu:
        image = image.cuda()
    return torch.tensor(image)


@app.route("/predict", methods=["POST"])
# @app.route("/predict"):
# 这部分定义了一个路由,表示当客户端发送请求到 /predict URL 时,Flask 应用会执行下方的处理函数。也就是说,任何访问 /predict 的请求都会被这个函数处理。
# methods=["POST"]:
# 这部分指定了允许的 HTTP 请求方法。methods=["POST"] 表示这个路由只接受 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))  # 将接收到的二进制图片转换成16进制  # 将二进制数据转换为图像对象

            # 利用上面的预处理函数将读入的图像进行预处理
            image = prepare_image(image, target_size=(224, 224))

            preds = F.softmax(model(image), dim=1)  # 得到各个类别的概率
            results = torch.topk(preds.cpu().data, k=3, dim=1)  # 概率最大的前3个结果
            # torch.topk用于返回输入张量中每行最大的k个元素及其对应的索引

            results = (results[0].cpu().numpy(), results[1].cpu().numpy())

            # 将data字典增加一个key,value,其中value为ist格式
            data['predictions'] = list()

            for prob, label in zip(results[0][0], results[1][0]):
                r = {"label": str(label), "probability": float(prob)}
                # 将预测结果添加至data字典
                data['predictions'].append(r)

            data["success"] = True
    return flask.jsonify(data)  # 将最后结果以json格式文件传出


if __name__ == '__main__':
    load_model()  # 先加载模型
    app.run(host='192.168.24.41', port='5012')  # 开启服务   服务器进入监听状态 等待用户发送信息
    # host 参数指定 IP 地址:
    # host = '127.0.0.1': 仅能从本机访问。
    # host = '0.0.0.0': 允许来自任何设备(网络)访问。
    # host = '192.168.24.41': 仅允许来自该特定IP地址的请求(通常是局域网内的某台设备)。

    # host = '127.0.0.1': 这表示Flask应用仅能在本机上访问。例如,只有在同一台计算机上打开浏览器,才能通过http: // 127.0.0.1: 5012 / 访问Flask应用。其他计算机无法通过这个IP访问。
    # host = '0.0.0.0': 这表示Flask应用会监听来自任何网络接口的请求,适用于让其他设备(比如局域网内的其他设备)也能访问该应用。通过局域网访问时,其他设备可以使用http: // < 你的局域网IP >: 5012 / 访问。
    # host = '192.168.24.41': 这意味着Flask仅监听来自该特定IP地址(通常是局域网IP)的请求。如果你在局域网中,其他设备可以使用http: // 192.168.24.41: 5012 / 访问。

输出:

如果最后的状态码是200,证明请求成功

相关推荐
watersink17 分钟前
机器学习随机森林
人工智能·随机森林·机器学习
高洁0132 分钟前
工信部教考中心证书
人工智能·深度学习·算法·机器学习·知识图谱
SomeB1oody44 分钟前
【RustyML入门】2.13. 孤立森林
开发语言·后端·机器学习·rust·教程
SomeB1oody2 小时前
【RustyML入门】3.8. 正则化与归一化层
开发语言·后端·机器学习·rust·教程
心运软件3 小时前
基于深度学习的宝石图像分类系统
人工智能·python·深度学习·机器学习·分类·数据挖掘
计科杨某人3 小时前
机器学习基本常识
随机森林·机器学习·支持向量机·监督学习·强化学习·最小二乘法·无监督学习
一个王同学3 小时前
从零到一 | CV转多模态大模型 | week22 | 实战项目-DocuMind-VL:基于 OCR 与 Qwen-VL 的文档多模态问答系统(二)
人工智能·深度学习·机器学习·计算机视觉·ocr
SomeB1oody3 小时前
【RustyML入门】3.7. 循环层
开发语言·后端·机器学习·rust·教程
ltl14 小时前
LLM 训练全景:Pre-train、SFT、RLHF、DPO 与蒸馏
机器学习