pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速

本来,前辈们用caffe搭建了一个squeezenet的工程,用起来也还行,但考虑到caffe的停更后续转trt应用在工程上时可能会有版本的问题所以搭建了一个pytorch版本的。
以下的环境搭建不再细说,主要就是pyorch,其余的需要什么pip install什么。

网络搭建

squeezenet的网络结构及其具体的参数如下:
在这里插入图片描述
后续对着这张表进行查看每层的输出时偶然发现这张表有问题,一张224×224的图片经过7×7步长为2的卷积层时输出应该是109×109才对,而不是这个111×111。所以此处我猜测要不是卷积核的参数有问题,要不就是这个输出结果有问题。我对了下下面的结果,发现都是从这个111×111的结果得出来的,这个结果没问题;但是我又对了下原有caffe版本的第一个卷积层用的就是这个7×7/2的参数,卷积核也没问题。这就有点矛盾了…这张表出自作者原论文,论文也是发表在顶会上,按道理应该不会有错才对。才疏学浅,希望大家有知道咋回事的能告诉我一声,这里我就还是用这个卷积核的参数了。
在这里插入图片描述
squeezenet有以上三个版本,我对了下发现前辈用的是中间这个带有简单残差的结构,为了进行对比这里也就用这个结构进行搭建了。
如下为网络结构的代码:

import torch
import torch.nn as nnclass Fire(nn.Module):def __init__(self, in_channel, squzee_channel, out_channel):super().__init__()self.squeeze = nn.Sequential(nn.Conv2d(in_channel, squzee_channel, 1),nn.ReLU(inplace=True))self.expand_1x1 = nn.Sequential(nn.Conv2d(squzee_channel, out_channel, 1), nn.ReLU(inplace=True))self.expand_3x3 = nn.Sequential(nn.Conv2d(squzee_channel, out_channel, 3, padding=1),nn.ReLU(inplace=True))def forward(self, x):x = self.squeeze(x)x = torch.cat([self.expand_1x1(x),self.expand_3x3(x)], 1)return xclass SqueezeNet_caffe(nn.Module):"""mobile net with simple bypass"""def __init__(self, class_num=5):super().__init__()self.stem = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=96, kernel_size=7, stride=2),nn.ReLU(inplace=True),nn.MaxPool2d(3, 2, ceil_mode=True))self.fire2 = Fire(96, 16, 64)self.fire3 = Fire(128, 16, 64)self.fire4 = Fire(128, 32, 128)self.fire5 = Fire(256, 32, 128)self.fire6 = Fire(256, 48, 192)self.fire7 = Fire(384, 48, 192)self.fire8 = Fire(384, 64, 256)self.fire9 = Fire(512, 64, 256)self.maxpool = nn.MaxPool2d(3, 2, ceil_mode=True)self.classifier = nn.Sequential(nn.Dropout(p=0.5),nn.Conv2d(512, class_num, kernel_size=1),   nn.ReLU(inplace=True),nn.AdaptiveAvgPool2d((1, 1))  )def forward(self, x):x = self.stem(x)f2 = self.fire2(x)f3 = self.fire3(f2) + f2f4 = self.fire4(f3)f4 = self.maxpool(f4)f5 = self.fire5(f4) + f4f6 = self.fire6(f5)f7 = self.fire7(f6) + f6f8 = self.fire8(f7)f8 = self.maxpool(f8)f9 = self.fire9(f8) + f8x = self.classifier(f9)x = x.view(x.size(0), -1)return xdef squeezenet_caffe(class_num=5):return SqueezeNet_caffe(class_num=class_num)

然后其余的整个工程代码就是pytorch搭建dataset、dataloader,每轮的前向、计算loss、反向传播等都是一个差不多的套路,就不在这里码出来了,直接放上链接,大家有需要可以直接下载(里面也集成了其他的分类网络)。

数据处理

dataset我用的是torchvision.datasets.ImageFolder,所以用目录名称作为数据集的label,目录结构如下:
在这里插入图片描述
将每一类的图片都放在对应的目录中,验证集以及测试集的数据集也是按照这样的格式。

运行命令

训练命令:

python train.py -net squeezenet_caffe -gpu -b 64 -t_data 训练集路径 -v_data 验证集路径 -imgsz 100

-net后面跟着是网络类型,都集成了如下的分类网络:
在这里插入图片描述
如果有n卡则-gpu使用gpu训练,-b是batch size,-imgsz是数据的input尺寸即resize的尺寸。
测试命令:

python test.py -net squeezenet_caffe -weights 训练好的模型路径 -gpu -b 64 -data 测试集路径 -imgsz 100

出现问题

一开始进行训练一切正常,到后面却忽然画风突变:
在这里插入图片描述
loss忽然大幅度上升,acc也同一时刻大幅度下降,然后数值不变呈斜率为0的一条直线。估计是梯度爆炸了(也是到这一步我先从网络结构找原因,对本文的第一张表一层一层对参数和结果才发现表中的问题),网络结构对完没问题,于是打印每个batch的梯度,顺便使用clip进行剪枝限定其最大阈值。

optimizer.zero_grad()
outputs = net(images)
loss = loss_function(outputs, labels)
loss.backward()grad_max = 0
grad_min = 10
for p in net.parameters():# 打印每个梯度的模,发现打印太多了一直刷屏所以改为下面的print最大最小值# print(p.grad.norm())gvalue = p.grad.norm()if gvalue > grad_max:grad_max = gvalueif gvalue < grad_min:grad_min = gvalue
print("grad_max:")
print(grad_max)
print("grad_min:")
print(grad_min)
# 将梯度的模clip到小于10的范围
torch.nn.utils.clip_grad_norm(p,10)optimizer.step()

按道理来说应该会有所改善,但结果是,训练几轮之后依旧出现这个问题。
但是,果然梯度在曲线异常的时候数值也是异常的:
在这里插入图片描述
刚开始正常学习的时候梯度值基本上都在e-1数量级的,曲线异常阶段梯度值都如图所示无限接近0,难怪不学习。
我们此时看一下tensorboard,我将梯度的最大最小值write进去,方便追踪:
在这里插入图片描述

可以发现在突变处梯度值忽然爆炸激增,猜测原因很可能是学习率太大了,动量振动幅度太大了跳出去跳不回来了。查看设置的学习率超参发现初始值果然太大了(0.1),于是改为0.01。再次运行后发现查看其tensorboard:
在这里插入图片描述
这回是正常的了。
但其实我放大查看了梯度爆炸点的梯度值:
在这里插入图片描述

发现其最大值没超过10,所以我上面的clip没起到作用,我如果将阈值改成2,结果如下:
在这里插入图片描述

发现起到了作用,但曲线没那么平滑,可能改成1或者再小一些效果会更好。但我觉得还是直接改学习率一劳永逸比较简单。

Pytorch模型转TensorRT模型

在训练了神经网络之后,TensorRT可以对网络进行压缩、优化以及运行时部署,并且没有框架的开销。TensorRT通过combines
layers,kernel优化选择,以及根据指定的精度执行归一化和转换成最优的matrix math方法,改善网络的延迟、吞吐量以及效率。
总之,通俗来说,就是训练的模型转trt后可以在n卡上高效推理,对于实际工程应用更加有优势。

首先将pth转onnx:

# pth->onnx->trtexec
# (optional) Exporting a Model from PyTorch to ONNX and Running it using ONNX Runtime
import torchvision
import torch,os
from models.squeezenet_caffe import squeezenet_caffebatch_size = 1    # just a random numbercurrent_dir=os.path.dirname(os.path.abspath(__file__)) # 获取当前路径
device = 'cuda' if torch.cuda.is_available() else 'cpu'model = squeezenet_caffe().cuda()model_path='/data/cch/pytorch-cifar100-master/checkpoint/squeezenet_caffe/Monday_04_September_2023_11h_48m_33s/squeezenet_caffe-297-best.pth'  # cloth
state_dict = torch.load(model_path, map_location=device)
print(1)
# mew_state_dict = OrderedDict()
model_dict = model.state_dict()
pretrained_dict = {k: v for k, v in state_dict.items() if (k in model_dict and 'fc' not in k)}
model_dict.update(pretrained_dict)
print(2)
model.load_state_dict(model_dict)
model.eval()
print(3)
# output = model(data)# Input to the model
x = torch.randn(batch_size, 3, 100, 100, requires_grad=True)
x = x.cuda()
torch_out = model(x)# Export the model
torch.onnx.export(model,               # model being runx,                         # model input (or a tuple for multiple inputs)"/data/cch/pytorch-cifar100-master/checkpoint/squeezenet_caffe/Monday_04_September_2023_11h_48m_33s/squeezenet_caffe-297-best.onnx",   # where to save the model (can be a file or file-like object)export_params=True,        # store the trained parameter weights inside the model fileopset_version=10,          # the ONNX version to export the model todo_constant_folding=True,  # whether to execute constant folding for optimizationinput_names = ['input'],   # the model's input namesoutput_names = ['output'], # the model's output namesdynamic_axes={'input' : {0 : 'batch_size'},    # variable length axes'output' : {0 : 'batch_size'}})

只需要修改一下输入输出的路径和输入的size即可。
然后是onnx转trt,这里需要自己先安装搭建好tensorrt的环境(环境搭建可能会有点复杂需要编译,有时间单独出一个详细的搭建过程),然后在tensorrt工程下的bin目录下运行命令:

./trtexec --onnx=/data/.../best.onnx --saveEngine=/data.../best.trt --workspace=6000

TensorRT可以提供workspace作为每层网络执行时的临时存储空间,该空间是共享的以减少显存占用(单位是M)。具体的原理可以参考这篇。

前向推理

代码如下:

# 动态推理
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import numpy as np
import torchvision.transforms as transforms
from PIL import Imagedef load_engine(engine_path):# TRT_LOGGER = trt.Logger(trt.Logger.WARNING)  # INFOTRT_LOGGER = trt.Logger(trt.Logger.ERROR)print('---')print(trt.Runtime(TRT_LOGGER))print('---')with open(engine_path, 'rb') as f, trt.Runtime(TRT_LOGGER) as runtime:return runtime.deserialize_cuda_engine(f.read())# 2. 读取数据,数据处理为可以和网络结构输入对应起来的的shape,数据可增加预处理
def get_test_transform():return transforms.Compose([transforms.Resize([100, 100]),transforms.ToTensor(),# transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),transforms.Normalize(mean=[0.4796262, 0.4549252, 0.43396652], std=[0.27888104, 0.28492442, 0.27168077])])image = Image.open('/data/.../dog.jpg') 
image = get_test_transform()(image)
image = image.unsqueeze_(0) # -> NCHW, 1,3,224,224
print("input img mean {} and std {}".format(image.mean(), image.std()))
image =  np.array(image)path = '/data/.../squeezenet_caffe-297-best.trt'
# 1. 建立模型,构建上下文管理器
engine = load_engine(path)
print(engine)
context = engine.create_execution_context()
context.active_optimization_profile = 0# 3.分配内存空间,并进行数据cpu到gpu的拷贝
# 动态尺寸,每次都要set一下模型输入的shape,0代表的就是输入,输出根据具体的网络结构而定,可以是0,1,2,3...其中的某个头。
context.set_binding_shape(0, image.shape)
d_input = cuda.mem_alloc(image.nbytes)  # 分配输入的内存。
output_shape = context.get_binding_shape(1)
buffer = np.empty(output_shape, dtype=np.float32)
d_output = cuda.mem_alloc(buffer.nbytes)  # 分配输出内存。
cuda.memcpy_htod(d_input, image)
bindings = [d_input, d_output]# 4.进行推理,并将结果从gpu拷贝到cpu。
context.execute_v2(bindings)  # 可异步和同步
cuda.memcpy_dtoh(buffer, d_output)
output = buffer.reshape(output_shape)
y_pred_binary = np.argmax(output, axis=1)
print(y_pred_binary[0])

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ABAP BAPI_ACC_DOCUMENT_POST 中 EXTENSION1的用法

BAPI_ACC_DOCUMENT_POST 在过账会计凭证时候&#xff0c;经常会发现一些标准字段在参数中并没有 可以通过CMOD/SMOD增强出口--》ACBAPI01--》EXIT_SAPLACC4_001--》ZXACCU15 示例代码&#xff1a; DATA: wa_extension TYPE bapiextc,it_extension TYPE STANDARD TABLE OF ba…

OpenCV(二十一):椒盐噪声和高斯噪声的产生

目录 1.图像噪声介绍 2.椒盐噪声的产生 3.高斯噪声的产生 1.图像噪声介绍 噪声介绍 图像噪声是指在图像中存在的不期望的、随机的像素值变化&#xff0c;这些变化来源于多种因素。噪声可能导致图像细节模糊、失真或难以分辨。 以下是几种常见的图像噪声类型&#xff1a; 1…

javascritp如何判断是从刷新(重新加载)、正常打开(或链接打开)、还是从浏览器回退进入页面的

重点先下另外一个知识点&#xff1a; 当我们的Web站点采用主体页面的iframe导航各个子页面&#xff08;浏览器地址保持不变&#xff09;的情况&#xff0c;如果我们希望每次iframe中打开的新的子页面&#xff0c;也都能够像在不采用iframe的情况那样&#xff0c;后续能够在浏览…

Tailwind 练手项目

Tailwind 练手项目 用到的技巧 Tailwind CSS 速成 应该都提过了&#xff0c;我不记得这里有什么特别新的知识 整体完成图大概这样&#xff1a; 一个纯静态页面&#xff0c;没有做 JS 之类的特效&#xff0c;不过做了移动端适配&#xff0c;说实话我写到一半的时候改了不少………

易云维®医院后勤管理系统软件利用物联网智能网关帮助实现医院设备实现智能化、信息化管理

近年来&#xff0c;我国医院逐渐意识到医院设备信息化管理的重要性&#xff0c;逐步建立医院后勤管理系统软件&#xff0c;以提高信息化管理水平。该系统是利用数据库技术&#xff0c;为医院的中央空调、洁净空调、电梯、锅炉、医疗设备等建立电子档案&#xff0c;把设备监控、…

mysql 安全加固

PS&#xff1a;之前在做安全测试的时候&#xff0c;报告mysql有安全漏洞&#xff0c;于是研究了下如何修复&#xff0c;于是记录下来分享给大家 1.1修改mysql 存放位置 修复 1.停服务 service mysqld stop2.迁位置 2.1 新建迁移目录 mkdir /home/database2.2 迁移数据文件…

【业务功能篇96】微服务-springcloud-springboot-认证服务-登录注册功能-Auth2.0-分布式session

5.登录功能 通过最基础的登录操作来完成登录处理 登录页面处理 认证服务的处理 /*** 注册的方法* return*/PostMapping("/login")public String login(LoginVo loginVo , RedirectAttributes redirectAttributes){R r memberFeginService.login(loginVo);if(r.getC…

数据结构:线性表之-单向链表(无头)

目录 什么是单向链表 顺序表和链表的区别和联系 顺序表&#xff1a; 链表&#xff1a; 链表表示(单项)和实现 1.1 链表的概念及结构 1.2单链表(无头)的实现 所用文件 将有以下功能&#xff1a; 链表定义 创建新链表元素 尾插 头插 尾删 头删 查找-给一个节点的…

(二十二)大数据实战——Flume数据采集之故障转移案例实战

前言 本节内容我们完成Flume数据采集的故障转移案例&#xff0c;使用三台服务器&#xff0c;一台服务器负责采集nc数据&#xff0c;通过使用failover模式的Sink处理器完成监控数据的故障转移&#xff0c;使用Avro的方式完成flume之间采集数据的传输。整体架构如下&#xff1a;…

OpenCV 01(图像加载与显示)

一、机器视觉 现在说的机器视觉(Machine Vision)一般指计算机视觉(Computer Vision), 简单来说就是研究如何使机器看懂东西。就是是指用摄影机和电脑代替人眼对目标进行识别、跟踪和测量等机器视觉&#xff0c;并进一步做图形处理&#xff0c;使电脑处理成为更适合人眼观察或传…

VS编译.cu文件源文件无法打开matrix.h和mex.h问题

配置好cu和VS相关库文件后CUDA程序仍然报错&#xff1a;无法打开matrix.h和mex.h&#xff0c;解决办法&#xff1a; &#xff08;1&#xff09;这两个头文件是matlab中的&#xff0c;可能无法直接在VS中调用&#xff0c;可以通过添加外部依赖项的方法将matlab中的头文件的文件路…

1600*C. Maximum Set

解析&#xff1a; 尽可能的增大集合内的数&#xff0c;所以倍数要尽可能的小&#xff0c;所以让最小的数不断乘 2&#xff0c;即可找到最大的数量。 所以&#xff0c;每次计算 k log2&#xff08; y / x &#xff09;,这样可得出最小的 x&#xff0c;乘多少个 2&#xff0c;能…

VS Code断点调式Cesium

1.在VS Code中安装Debugger for Firefox插件 2.下载安Firefox Developer Edition 3. 创建launch.json 编辑并保存launch.json {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, vis…

MJDK 如何实现压缩速率的 5 倍提升?

MJDK 是基于 OpenJDK 构建的美团 JDK 发行版。本文主要介绍 MJDK 是如何在保障 java.util.zip.* API 及压缩格式兼容性的前提下&#xff0c;实现压缩/解压缩速率提升 5-10 倍的效果。希望相关的经验能够帮助到更多的技术同学。 1 前言 数据压缩技术[1]因可有效降低数据存储及…

strerror函数

目录 strerror 函数介绍&#xff1a; 举例&#xff1a; 使用案例&#xff1a; 优化&#xff1a; perror&#xff1a; strerror 函数介绍&#xff1a; 函数声明&#xff1a; char * strerror ( int errnum );头 文 件&#xff1a;#include <string.h>返 回 值&a…

01_前端css编写的三种方式

前言 CSS的引入方式共有三种&#xff1a;行内样式、内部样式表、外部样式表 一、内联式引入 用法&#xff1a; 在元素上直接通过style属性进行设置css样式设置 示例&#xff1a; <h1 style"color:red;">style属性的应用</h1> <p style"font-si…

hive指定字段插入数据,包含了分区表和非分区表

1、建表 语句如下&#xff1a; CREATE EXTERNAL TABLE ods_lineitem_full (l_shipdate date,l_orderkey bigint,l_linenumber int,l_partkey int,l_suppkey int,l_quantity decimal(15, 2),l_extendedprice decimal(15, 2),l_discount de…

数据结构-第一期——数组(Python)

目录 00、前言&#xff1a; 01、一维数组 一维数组的定义和初始化 一维变长数组 一维正向遍历 一维反向遍历 一维数组的区间操作 竞赛小技巧&#xff1a;不用从a[0]开始&#xff0c;从a[1]开始 蓝桥杯真题练习1 读入一维数组 例题一 例题二​ 例题三 实战训…

每日刷题|回溯法解决全排列问题第二弹之解决字符串、字母大小排列问题

食用指南&#xff1a;本文为作者刷题中认为有必要记录的题目 前置知识&#xff1a;回溯法经典问题之全排列 ♈️今日夜电波&#xff1a;带我去找夜生活—告五人 0:49 ━━━━━━️&#x1f49f;──────── 4:59 …

安科瑞铁塔基站能耗监控解决方案

安科瑞 华楠 1 背景概述 5G发展&#xff0c;基站先行。5G基站的选址建设&#xff0c;是保证5G信号覆盖的基础&#xff0c;因此5G基站建设是5G产业布局的一部分&#xff0c;也是5G成熟的基础。 2G、3G、4G均是低频段信号传输&#xff0c;宏基站几乎能应付所有的信号覆盖。但由…