使用Flask快速部署PyTorch模型

news2025/1/12 8:56:11

对于数据科学项目来说,我们一直都很关注模型的训练和表现,但是在实际工作中如何启动和运行我们的模型是模型上线的最后一步也是最重要的工作。

今天我将通过一个简单的案例:部署一个PyTorch图像分类模型,介绍这个最重要的步骤。

我们这里使用PyTorch和Flask。可以使用pip install torch和pip install flask安装这些包。

web应用

为Flask创建一个文件app.py和一个路由:

 fromflaskimportFlask
 importtorch
 
 
 app=Flask(__name__)
 
 @app.route('/')
 defhome():
     return'Welcome to the PyTorch Flask app!'

现在我们可以运行python app.py,如果没有问题,你可以访问http://localhost:5000/,应该会看到一条简单的消息——“Welcome to the PyTorch Flask app!”

这就说明我们flask的web服务已经可以工作了,现在让我们添加一些代码,将数据传递给我们的模型!

添加更多的导入

 fromflaskimportFlask, request, render_template
 fromPILimportImage
 importtorch
 importtorchvision.transformsastransforms

然后再将主页的内容换成一个HTML页面

 @app.route('/')
 defhome():
     returnrender_template('home.html')

创建一个templates文件夹,然后创建home.html。

 <html>
   <head>
     <title>PyTorch Image Classification</title>
   </head>
   <body>
     <h1>PyTorch Image Classification</h1>
     <formmethod="POST"enctype="multipart/form-data"action="/predict">
       <inputtype="file"name="image">
       <inputtype="submit"value="Predict">
     </form>
   </body>
 </html>

HTML非常简单——有一个上传按钮,可以上传我们想要运行模型的任何数据(在我们的例子中是图像)。

以上都是基本的web应用的内容,下面就是要将这个web应用和我们的pytorch模型的推理结合。

加载模型

在home route上面,加载我们的模型。

 model=torch.jit.load('path/to/model.pth')

我们都知道,模型的输入是张量,所以对于图片来说,我们需要将其转换为张量、还要进行例如调整大小或其他形式的预处理(这与训练时的处理一样)。

我们处理的是图像,所以预处理很简单

 defprocess_image(image):
     # Preprocess image for model
     transformation=transforms.Compose([
         transforms.Resize(256),
         transforms.CenterCrop(224),
         transforms.ToTensor(),
         transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
     ])
     image_tensor=transformation(image).unsqueeze(0)
     
     returnimage_tensor

我们还需要一个数组来表示类,本文只有2类

 class_names= ['apple', 'banana'] 

预测

下一步就是创建一个路由,接收上传的图像,处理并使用模型进行预测,并返回每个类的概率。

 @app.route('/predict', methods=['POST'])
 defpredict():
     # Get uploaded image file
     image=request.files['image']
 
     # Process image and make prediction
     image_tensor=process_image(Image.open(image))
     output=model(image_tensor)
 
     # Get class probabilities
     probabilities=torch.nn.functional.softmax(output, dim=1)
     probabilities=probabilities.detach().numpy()[0]
 
     # Get the index of the highest probability
     class_index=probabilities.argmax()
 
     # Get the predicted class and probability
     predicted_class=class_names[class_index]
     probability=probabilities[class_index]
 
     # Sort class probabilities in descending order
     class_probs=list(zip(class_names, probabilities))
     class_probs.sort(key=lambdax: x[1], reverse=True)
 
     # Render HTML page with prediction results
     returnrender_template('predict.html', class_probs=class_probs,
                            predicted_class=predicted_class, probability=probability)

我们的/predict路由首先使用softmax函数获得类概率,然后获得最高概率的索引。它使用这个索引在类名列表中查找预测的类,并获得该类的概率。然后按降序对类别概率进行排序,并返回预测结果。

最后,我们的app.py文件应该是这样的:

 fromflaskimportFlask, request, render_template
 fromPILimportImage
 importtorch
 importtorchvision.transformsastransforms
 
 
 model=torch.jit.load('path/to/model.pth')
 
 @app.route('/')
 defhome():
     returnrender_template('home.html')
 
 defprocess_image(image):
     # Preprocess image for model
     transformation=transforms.Compose([
         transforms.Resize(256),
         transforms.CenterCrop(224),
         transforms.ToTensor(),
         transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
     ])
     image_tensor=transformation(image).unsqueeze(0)
     
     returnimage_tensor
 
 
 class_names= ['apple', 'banana'] #REPLACE THIS WITH YOUR CLASSES
 
 @app.route('/predict', methods=['POST'])
 defpredict():
     # Get uploaded image file
     image=request.files['image']
 
     # Process image and make prediction
     image_tensor=process_image(Image.open(image))
     output=model(image_tensor)
 
     # Get class probabilities
     probabilities=torch.nn.functional.softmax(output, dim=1)
     probabilities=probabilities.detach().numpy()[0]
 
     # Get the index of the highest probability
     class_index=probabilities.argmax()
 
     # Get the predicted class and probability
     predicted_class=class_names[class_index]
     probability=probabilities[class_index]
 
     # Sort class probabilities in descending order
     class_probs=list(zip(class_names, probabilities))
     class_probs.sort(key=lambdax: x[1], reverse=True)
 
     # Render HTML page with prediction results
     returnrender_template('predict.html', class_probs=class_probs,
                            predicted_class=predicted_class, probability=probability)

最后一个部分是实现predict.html模板,在templates目录创建一个名为predict.html的文件:

 <html>
   <head>
     <title>PredictionResults</title>
   </head>
   <body>
     <h1>PredictionResults</h1>
     <p>PredictedClass: {{ predicted_class }}</p>
     <p>Probability: {{ probability }}</p>
     <h2>OtherClasses</h2>
     <ul>
       {%forclass_name, probinclass_probs%}
         <li>{{ class_name }}: {{ prob }}</li>
       {%endfor%}
     </ul>
   </body>
 </html>

这个HTML页面显示了预测的类别和概率,以及按概率降序排列的其他类别列表。

测试

使用python app.py运行服务,然后首页会显示我们创建的上传图片的按钮,可以通过按钮上传图片进行测试,这里我们还可以通过编程方式发送POST请求来测试您的模型。

下面就是发送POST请求的Python代码

 #pip install requests
 importrequests
 
 url='http://localhost:5000/predict'
 
 # Set image file path
 image_path='path/to/image.jpg'
 
 # Read image file and set as payload
 image=open(image_path, 'rb')
 payload= {'image': image}
 
 # Send POST request with image and get response
 response=requests.post(url, headers=headers, data=payload)
 
 print(response.text)

这段代码将向Flask应用程序发送一个POST请求,上传指定的图像文件。我们创建的Flask应用程会处理图像,做出预测并返回响应,最后响应将打印到控制台。

就是这样只要5分钟,我们就可以成功地部署一个ML模型。

https://avoid.overfit.cn/post/4984d0f355b7448c8efd70aee9677739

作者:Daniel Korsz

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

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

相关文章

OAK-PoE设备故障排查详解

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

Linux小黑板(5):磁盘与文件系统

"这月蹦迪没我" 一、浅谈磁盘 磁盘作为计算机硬件里&#xff0c;唯一的机械设备。在数据存储的领域&#xff0c;有着不可磨灭的作用。相较于&#xff0c;保持通电情况下具有保持数据的不丢失的内存&#xff0c;磁盘能够"永久性"地存储 数据。 磁盘是计算机…

1. R语言介绍、Rstudio的基本使用、【R包的安装与使用】、帮助命令、内置数据集

课程视频链接&#xff1a;https://www.bilibili.com/video/BV19x411X7C6?p1 本笔记参照该视频&#xff0c;笔记顺序做了些调整【个人感觉逻辑顺畅】&#xff0c;并删掉一些不重要的内容 系列笔记目录【持续更新】&#xff1a;https://blog.csdn.net/weixin_42214698/category_…

【Linux】进程控制:父进程与子进程

目录1 进程创建1.1 认识fork1.2 进程创建的目的1.3 写时拷贝1.4 进程创建失败的场景2 进程退出2.1 进程退出状态2.2 进程退出的方式2.3 exit、_exit、return2.3.1 概念2.3.2 区别3 进程等待3.1 理解进程等待3.2 进程等待的方式3.2.1 wait和waitpid3.2.2 status位图结构3.3 阻塞…

【一起从0开始学习人工智能0x04】python相关AI复习【超全面】【收藏】

基础小结 数据类型&#xff1a;Numbers、String、list、tuple、dict字符编码&#xff1a;可以直接.encode&#xff08;‘utf-8’&#xff09;、.decode(ascii)循环&#xff1a;for-in迭代器、whilelist列表-最频繁的数据类型。-完成大多数集合类的数据结构实现。它支持字符&am…

十六、状态管理——Vuex(4)

本章概要 表单处理Vuex 与组合 API模块 16.8 表单处理 在表单控件上通常会使用 v-model 指令进行数据绑定&#xff0c;如果绑定的数据是 Vuex 中的状态数据&#xff0c;就会遇到一些问题。看以下代码&#xff1a; form.html <div id"app"><my-component&…

一场衍生于产业的深度变革正在上演,总结起来就是产业互联网的变革

毫无疑问的是&#xff0c;一场衍生于产业的深度变革正在上演。在这样一场深度变革之中&#xff0c;曾经看似无法改变的存在&#xff0c;有了进化的可能性&#xff1b;曾经让玩家们望而却步的领域&#xff0c;有了进军的可能性。如果对这样一场深度变革进行一次总结的话&#xf…

vanishing point detection in autopilot

1. 概述 消失点一种直观的解释是图像中的平行线的交点&#xff0c;也就如下图中路面边界绘制的直线在图像中的交点。 这样的点在自动驾驶场景下可以为解析车辆状态提供一些信息&#xff0c;比如较为常规的运用便是用于车辆的pitch角度。在传统方法中会通过如霍夫算子检测图片…

2022稳定学习年度研究进展系列报告丨精华观点总结

近年来&#xff0c;在独立分布假设的前提下&#xff0c;机器学习模型的表现越来越好。但在实际应用场景中&#xff0c;数据本身却具有很强的异质性和差异性&#xff0c;这就对模型的泛化能力产生了较高的要求。为了解决分布外泛化问题&#xff0c;稳定学习应运而生。12月28日&a…

Python计算机视觉:人脸识别

讲明一下:并没有实现人脸识别的算法,只是利用人脸特征文件(文件从官网上下载),从而进行人脸识别,总感觉识别出来的效果还是有问题的,如:图片最好是人脸的正脸。 1. 人脸特征文件下载 直接去github或者gitee(建议gitee)上去搜索opencv即可,如下: 选择第一个直接进入即…

一篇文章带你了解——Linux中 文件权限 和 粘滞位的 概念 / 作用 及 实现方法

粘滞位首言用户权限文件权限文件类型分类文件访问者的分类实际解读文件权限文件权限设置方法为啥要有文件权限为啥要有粘滞位粘滞位的好处如何添加粘滞位首言 要了解粘滞位&#xff0c;首先得了解文件及用户权限 用户权限 Linux下有两种用户&#xff1a;超级用户&#xff08…

共享内存原理与使用

共享内存是System V版本的最后一个进程间通信方式。共享内存&#xff0c;顾名思义就是允许两个不相关的进程访问同一个逻辑内存&#xff0c;共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一…

vite学习详解

简介 前言 之前vite2刚出的时候其实已经自学过一波&#xff0c;但是老实说学起来完全不入脑&#xff0c;一方面本来这方面的基础就很差&#xff08;指项目配置&#xff09;&#xff0c;另一方面学的时候没有跟着去动手&#xff0c;纯理论的学那完全就是越看越困。最后就是急躁…

java书店带商家商城书店多单商书店系统源码

简介 Java ssm开发的多商家书店商城&#xff0c;用户可以浏览商品&#xff0c;加入购物车&#xff0c;直接下单支付&#xff0c;在我的个人中心里可以管理自己的订单&#xff0c;收货地址&#xff0c;编辑资料等&#xff0c;还可以申请开店&#xff0c;店铺开通后可以发布商品…

C++--list

前言 这篇文章对于理解封装是非常有帮助的&#xff0c;list的底层是双向链表结构&#xff0c;我们在学习数据结构是就已经学过了双向链表&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。因为list独特的结…

nsis打包程序自动生成的快捷方式打不开

nsis 打包程序自动生成的快捷方式打不开 一: 问题描述: nsis 打包程序自动生成的快捷方式打不开, 报的是: 打不开数据库 , 但是在目录下双击exe 是能够打开的 一: 问题推导: 我是先右击自动生成的快捷方式 选择打开文件所在位置, 我发现确实是 我想要那个exe 的所在位置然后…

Zynq PL端调用PS端的时钟

ZYNQ PS端最多可以分配4个时钟供给PL端使用&#xff0c;见下图。 本文的目的&#xff1a;在XCZU21DR环境下&#xff0c;PS给PL提供一个100MHz的时钟&#xff0c;PL端根据此时钟产生1S信号&#xff0c;点亮LED。 添加&配置Zynq UltraScale MPSoc IP 双击该IP&#xff0c;在…

【C++】C++入门知识(一)

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《C》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 1.C关键字 2.命名空间 2.1局部变量和全局变量 2.2命名空间的概念及使用 2.3…

本硕985计算机,34岁的字节大头兵,上司很器重我,给我加薪不少,但国企也欢迎我,好犹豫该不该去国企!...

互联网VS国企&#xff0c;该怎么选&#xff1f;这是一位34岁的字节程序员面临的选择&#xff1a;在头条是2-2大头兵&#xff0c;本硕985计算机&#xff0c;国企还是比较欢迎他的。原本的想法是在私企干几年&#xff0c;如果干不成管理就去国企。如今没当成管理&#xff0c;但上…

【蓝桥杯嵌入式】第十三届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解

原题展示 &#x1f4c4; 本试题目的是制作一个商品管理系统&#xff0c;其主要功能为&#xff1a;购买商品、增加商品储量、调节商品价格、查询商品价格&#xff0c;并且能够保存改变后的商品数量与商品价格&#xff0c;总体上看跟第一场的试题差不多&#xff0c;下面就让我们一…