pytorch模型网页部署——Flask

news2024/11/25 20:38:08

一、Flask用法

Flask是python的轻量级web框架,可用来做简单的模型部署。Flask的基本用法如下:

step1:定义Flask类的对象,即创建一个基于Flask的服务器

step2:定义公开的路由及路由对应的调用函数

step3:运行服务器

"""基于flask的web网页"""
from flask import Flask     # 导入flask库

app = Flask(__name__)       # 创建Flask类的对象,可理解为建立一个基于flask框架的服务器

# 公开路由的名称【my_fcn】,同时修饰下一行定义的函数。
# 定义的函数名要与公开的路由名称一致。
# 后续访问网页的url格式为:http://ip:port/路由名称
@app.route("/my_fcn")
def my_fcn():
    return "hello world"    # 访问网页时返回内容会显示在网页上

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000)      # 运行服务器。可通过get/post参数请求数据

运行结果:

二、在基于flask的网页上部署模型

在基于flask的网页上部署模型,其实只需在上述例子中定义的函数【my_fcn】中添加模型预测的代码即可。示例如下:

"""基于flask的web网页"""
import numpy as np
import cv2
import torch
import torchvision
from flask import Flask     # 导入flask库


app = Flask(__name__)       # 创建Flask类的对象,可理解为建立一个基于flask框架的服务器

# 公开路由的名称【my_fcn】,同时修饰下一行定义的函数。
# 定义的函数名要与公开的路由名称一致。
# 后续访问网页的url格式为:http://ip:port/路由名称
@app.route("/my_fcn")
def my_fcn():
    # 加载图片,并将图片转为0到1之间的浮点数张量
    img = cv2.imread("rose.jpg")
    img = cv2.resize(img, (224, 224))
    img_tensor = torch.tensor(img).permute(2, 0, 1).unsqueeze(0).float()/255.0
    model = torchvision.models.resnet50(pretrained=True)
    model.eval()
    output = model(img_tensor)
    output = torch.nn.functional.softmax(output,1)
    output = torch.argmax(output)

    return "class index={}".format(output.numpy())


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000)      # 运行服务器。可通过get/post参数请求数据

运行结果:

三、远程客户端访问网页服务器模型进行推理 

当需要在远程客户端请求服务器进行推理时,需要将图像的数据post到服务器,第二节的方法就需要进行改进了,具体方法是将图像数据编码为二进制以post方法提交,服务器解析后进行推理。

举例:web服务器部署了基于resnet50的分类模型,远程客户端读取了一张图片,并提交给服务器进行推理,服务器将推理结果返回给客户端。

代码如下:

3.1 服务器代码:server.py

# server.py

import numpy as np
from flask import Flask, request, jsonify

import json
import torch
import torchvision

app = Flask(__name__)

model = torchvision.models.resnet50(pretrained=True)
model.eval()

# 推理过程
def run_inference(in_tensor):
    with torch.no_grad():
        out_tensor = model(in_tensor)
        out_tensor = torch.nn.functional.softmax(out_tensor, 1)
        output = torch.argmax(out_tensor)

    return output

# flask服务器
@app.route('/predict', methods=['GET', 'POST'])     # 注意,这里开放GET、POST请求
def predict():
    # 客户端post时,包含将输入张量尺寸以json字符串,input_input = "{"shape": [C, W, H]}",因此需要重新解析为json并提取尺寸
    in_shape = json.load(request.files['in_shape'])

    # 客户端post时,将图像数据以二进制形式发送,因此需要将图像重新从二进制转换会tensor,并resize
    in_blob = request.files['in_blob'].read()
    in_tensor = torch.from_numpy(np.frombuffer(in_blob, dtype=np.float32))
    in_tensor = in_tensor.view(*in_shape['shape'])

    output = run_inference(in_tensor)  # 推理
    output = '{}'.format(output)

    return jsonify(output)          # 以json返回结果

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8000)

3.2 客户端代码:client.py

# 首先运行【server.py】,然后运行本文件,实现请求推理本地图像的预测结果。
# client.py

import torch
import cv2
import io
import json
import requests


# config
IMG_NAME = 'dog.jpg'
MY_URL = 'http://192.168.1.103:8000/predict'

# 处理图像数据
img = cv2.imread(IMG_NAME)
img = cv2.resize(img, (224, 224))       # resnet输入张量shape=3x224x224
in_tensor = torch.tensor(img).permute(2, 0, 1).unsqueeze(0).float()/255.0
blob = io.BytesIO(bytearray(in_tensor.numpy()))      # 将输入张量转为numpy,再转为二进制进行post请求
shape = io.StringIO(json.dumps({'shape': [1, 3, 224, 224]}))    # 将输入张量尺寸post

my_files = {'in_shape': shape, 'in_blob': blob}
r = requests.post(url=MY_URL, files=my_files)
response = json.loads(r.content)        # 由于服务器返回结果为json,因此需要解析json内容

print("the class index of '{}' is: {}".format(IMG_NAME, response))

运行结果:

四、缺点

由于HTTP是串行的,当大量并发请求时,这种方式只能应答完一个请求后才会应答下一个,改进方法可通过使用Sanic框架,实现异步并行处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享新零售系统商城小程序开发制作功能介绍_商城小程序开发好处

小编主要专注于新零售系统开发商城的领域,新零售系统开发商业模式有哪些: ① 多种销售模式:邀请有奖、销售业绩奖、团队业绩奖、区域分红,分销模式等。 ② 团队协作功能:立即邀约分销模式,清楚搜索直属代…

大型ERP生产制造管理系统源码

🍓🍓【淘源码】:一个专业提供高品质源码免费下载的资源共享平台🍓🍓 👇👇👇以下是博主整理的淘源码网站内大家都比较感兴趣的一些源码,需要源码学习的朋友可以私信博主哦…

Exception | ShardingSphere | ShardingSphere引发的IndexOutOfBoundsException

ShardingSphere引发的IndexOutOfBoundsException一、异常二、 原因三、解决方法四、总结一、异常 ### Error querying database. Cause: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 ### The error may exist in file [D:\JetBrains\Idea\workspace\zohe\bjxz\ru…

N-gram和NNLM语言模型

背景: one-hot:缺点:1.高维稀疏,2.不能体现句子中词的重要性,3.不能体现词与词之间的关系。 embedding:1.解决了高维稀疏 tf-idf:2.解决了one-hot中不能体现句子中词的重要性这一特点。 语言模型:3.解决不能…

【20221201】【每日一题】划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度的列表。 思路&…

协程Part1-boost.Coroutine.md

首先,在计算机科学中 routine 被定义为一系列的操作,多个 routine 的执行形成一个父子关系,并且子 routine 一定会在父 routine 结束前结束,也就是一个个的函数执行和嵌套执行形成了父子关系。 coroutine 也是广义上的 routine&a…

网页JS自动化脚本(五)修改文字元素的内容和大小

今天的网页打开全是灰色的,顺便缅怀一下伟人,那么我我们今天定位换成按钮文字 window.onloadfunction(){var theElementdocument.querySelector("input[typesubmit]");theElement.value"爱我中华";theElement.style"font-size:25px"; }这一次的…

提分必练!中创教育PMP全真模拟题分享来喽

湖南中创教育每日五题分享来啦,“日日行,不怕千万里;常常做,不怕千万事。”,每日五题我们练起来! 1、一个项目正在实行敏捷方法,在迭代过程中,团队成员互相合作,解决了一…

【机器学习】核函数

核方法 核技巧 非线性分类问题是指通过利用非线性模型才能很好地进行分类的问题。如图 111 所示,“●”表示正样本,“”表示负样本,显然无法用直线(线性模型)将正负样本正确分开,但是可以用一条椭圆曲线&…

记一次大事务优化历程(短信发送)

问题背景 短信服务数据库连接数告警,grafana查看数据库连接池被打满。 问题分析 在这段时间内,通过链路分析,发现最终调用第三方短信发送服务偶然耗时过长,分析了原有发送逻辑的代码,该实现在入口send处加了事务&am…

leetcode4. 寻找两个正序数组的中位数python_二分查找和递归(困难)

题目 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (mn)) 。 示例 1: 输入:nums1 [1,3], nums2 [2] 输出:2.00000 解释…

第二证券|疫情扰动叠加需求不足,11月制造业PMI回落至48%

国家统计局周三称,11月,受国内疫情点多面广频发,世界环境更趋复杂严峻等多重要素影响,我国制造业收购经理人指数(PMI)较上月回落1.2个百分点至48.0%。制造业PMI接连两个月低于临界点,制造业下行…

第4季2:并口、MIPI、LVDS的简介

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、并口的简介 1、并口的含义 并口的含义,可以从AR0130或OV9712的原理图中形象地理解。 如下图所示,AR0130采用12bit的并口向SoC传输图像数据信息,而SoC和AR0130…

b站黑马JavaScript的Ajax案例代码——评论列表案例

目标效果: 1.在表单界面输入评论人和内容,点击发表评论按钮,可以在页面下面看到自己刚刚输入的内容 2.发表评论成功之后,用DOM对象的reset方法:重置表单为其默认值 e.g.1初始状态:【下面的评论内容会因为…

STC 51单片机48——数码管显示外部中断次数

#include<reg52.h> #include<intrins.h> #include "math.h" #define uchar unsigned char #define uint unsigned int #define ulong unsigned long //共阴字形码表【实验】数码管实验时&#xff0c;一定要将点阵模块跳针放到VCC上&#xff01;&…

【C语言】哈夫曼树,再来一次解剖

博主&#xff1a;&#x1f44d;不许代码码上红 欢迎&#xff1a;&#x1f40b;点赞、收藏、关注、评论。 格言&#xff1a; 大鹏一日同风起&#xff0c;扶摇直上九万里。 文章目录一、定义结构1.1 定义结点权值的数据类型1.2 定义单个结点信息1.3 字符指针数组中存储的元素类…

C++ Reference: Standard C++ Library reference: Containers: list: list: list

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/list/ 公有成员函数 <list> std::list::list C98 默认构造函数 (1) explicit list (const allocator_type& alloc allocator_type()); 填充构造函数 (2) explicit list (size_type n,…

将整个网站变为黑白色

目录 效果&#xff1a; 代码&#xff1a; 兼容性写法&#xff1a; 原理&#xff1a; 效果&#xff1a; ps&#xff1a;实测淘宝也是用的这种方式&#xff0c;有兴趣可以去看看 代码&#xff1a; 使用方式就是找到根标签&#xff0c;将里面的两行代码放进去即可 html {filte…

手写Redux(二):实现React-redux

在React中&#xff0c;组件和组件之间通过props传递数据的规范&#xff0c;极大地增强了组件之间的耦合性&#xff0c;而context类似全局变量一样&#xff0c;里面的数据能被随意接触就能被随意修改&#xff0c;每个组件都能够改context里面的内容会导致程序的运行不可预料。 …

借助cubeMX实现STM32MP157A(-M4核)UART、按键中断、环境检测开关实验

main.c 可以添加一句打印提示 int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init(…