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

这篇具有很好参考价值的文章主要介绍了pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

网络搭建

squeezenet的网络结构及其具体的参数如下:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
后续对着这张表进行查看每层的输出时偶然发现这张表有问题,一张224×224的图片经过7×7步长为2的卷积层时输出应该是109×109才对,而不是这个111×111。所以此处我猜测要不是卷积核的参数有问题,要不就是这个输出结果有问题。我对了下下面的结果,发现都是从这个111×111的结果得出来的,这个结果没问题;但是我又对了下原有caffe版本的第一个卷积层用的就是这个7×7/2的参数,卷积核也没问题。这就有点矛盾了…这张表出自作者原论文,论文也是发表在顶会上,按道理应该不会有错才对。才疏学浅,希望大家有知道咋回事的能告诉我一声,这里我就还是用这个卷积核的参数了。
更新
如上的疑问刚开始以为是我自己的问题,进行了多角度猜测,有猜测会不会是不同的框架卷积后有的是向上取整有的是向下取整,又或者前辈使用的caffe框架没有特别说明padding会自动padding而不浪费边角信息呢…最后发现论文是有开源github的于是点开一看,发现是论文的图中作者大意不小心写错了,我也特别向作者说明了并得到本人的回复确实如此。本人向做作者的说明:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
作者的回应:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习


pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
squeezenet有以上三个版本,我对了下发现前辈用的是中间这个带有简单残差的结构,为了进行对比这里也就用这个结构进行搭建了。
如下为网络结构的代码:

import torch
import torch.nn as nn


class 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 x

class 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) + f2
        f4 = self.fire4(f3)
        f4 = self.maxpool(f4)

        f5 = self.fire5(f4) + f4
        f6 = self.fire6(f5)
        f7 = self.fire7(f6) + f6
        f8 = self.fire8(f7)
        f8 = self.maxpool(f8)

        f9 = self.fire9(f8) + f8

        x = self.classifier(f9)

        x = x.view(x.size(0), -1)

        return x

def squeezenet_caffe(class_num=5):
    return SqueezeNet_caffe(class_num=class_num)

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

数据处理

dataset我用的是torchvision.datasets.ImageFolder,所以用目录名称作为数据集的label,目录结构如下:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
将每一类的图片都放在对应的目录中,验证集以及测试集的数据集也是按照这样的格式。

运行命令

训练命令:

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

-net后面跟着是网络类型,都集成了如下的分类网络:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
如果有n卡则-gpu使用gpu训练,-b是batch size,-imgsz是数据的input尺寸即resize的尺寸。
测试命令:

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

出现问题

一开始进行训练一切正常,到后面却忽然画风突变:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
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 = gvalue
    if 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()

按道理来说应该会有所改善,但结果是,训练几轮之后依旧出现这个问题。
但是,果然梯度在曲线异常的时候数值也是异常的:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
刚开始正常学习的时候梯度值基本上都在e-1数量级的,曲线异常阶段梯度值都如图所示无限接近0,难怪不学习。
我们此时看一下tensorboard,我将梯度的最大最小值write进去,方便追踪:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习

可以发现在突变处梯度值忽然爆炸激增,猜测原因很可能是学习率太大了,动量振动幅度太大了跳出去跳不回来了。查看设置的学习率超参发现初始值果然太大了(0.1),于是改为0.01。再次运行后发现查看其tensorboard:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习
这回是正常的了。
但其实我放大查看了梯度爆炸点的梯度值:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习

发现其最大值没超过10,所以我上面的clip没起到作用,我如果将阈值改成2,结果如下:
pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速,pytorch,pytorch,人工智能,分类算法,计算机视觉,神经网络,深度学习

发现起到了作用,但曲线没那么平滑,可能改成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_caffe

batch_size = 1    # just a random number

current_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 run
                  x,                         # 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 file
                  opset_version=10,          # the ONNX version to export the model to
                  do_constant_folding=True,  # whether to execute constant folding for optimization
                  input_names = ['input'],   # the model's input names
                  output_names = ['output'], # the model's output names
                  dynamic_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 Image


def load_engine(engine_path):
    # TRT_LOGGER = trt.Logger(trt.Logger.WARNING)  # INFO
    TRT_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])

下一篇升级版本,针对此网络的微调改进,训练更方便,效果也更佳。文章来源地址https://www.toymoban.com/news/detail-703422.html

到了这里,关于pytorch搭建squeezenet网络的整套工程,及其转tensorrt进行cuda加速的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 测试环境搭建整套大数据系统(三:搭建集群zookeeper,hdfs,mapreduce,yarn,hive)

    https://blog.csdn.net/weixin_43446246/article/details/123327143 java_home填写自己安装的路径。 vim core-site.xml 将以下信息填写到configuration中 vim hdfs-site.xml vim mapred-site.xml vim yarn-site.xml vim workers 启动zk 三台机器全部执行 在node01执行 格式化NameNode 。 在node01执行 启动hdfs 在node01执行 启动yarn jps

    2024年02月20日
    浏览(37)
  • PyTorch入门学习(十一):神经网络-线性层及其他层介绍

    目录 一、简介 二、PyTorch 中的线性层 三、示例:使用线性层构建神经网络 四、常见的其他层 一、简介 神经网络是由多个层组成的,每一层都包含了一组权重和一个激活函数。每层的作用是将输入数据进行变换,从而最终生成输出。线性层是神经网络中的基本层之一,它执

    2024年02月05日
    浏览(32)
  • Pytorch TensorRT 安装使用流程

    安装流程1 安装流程2 执行命令: 需要等待一会,等待安装完成。 配置 trtexec或路径工具创建engine文件 创建完成后,生成对应engine文件

    2024年02月13日
    浏览(29)
  • 【Pytorch】神经网络搭建

    在之前我们学习了如何用Pytorch去导入我们的数据和数据集,并且对数据进行预处理。接下来我们就需要学习如何利用Pytorch去构建我们的神经网络了。 目录 基本网络框架Module搭建 卷积层 从conv2d方法了解原理 从Conv2d方法了解使用 池化层 填充层 非线性层 线性层 Pytorch里面有一

    2023年04月17日
    浏览(26)
  • PyTorch 神经网络搭建模板

    在 PyTorch 中, Dataset 和 DataLoader 是用来处理数据的重要工具。它们的作用分别如下: Dataset : Dataset 用于存储数据样本及其对应的标签。在使用神经网络训练时,通常需要将原始数据集转换为 Dataset 对象,以便能够通过 DataLoader 进行批量读取数据,同时也可以方便地进行数据

    2023年04月08日
    浏览(30)
  • 人工智能(Pytorch)搭建模型6-使用Pytorch搭建卷积神经网络ResNet模型

    大家好,我是微学AI,今天给大家介绍一下人工智能(Pytorch)搭建模型6-使用Pytorch搭建卷积神经网络ResNet模型,在本文中,我们将学习如何使用PyTorch搭建卷积神经网络ResNet模型,并在生成的假数据上进行训练和测试。本文将涵盖这些内容:ResNet模型简介、ResNet模型结构、生成假

    2024年02月06日
    浏览(41)
  • 人工智能(pytorch)搭建模型10-pytorch搭建脉冲神经网络(SNN)实现及应用

    大家好,我是微学AI,今天给大家介绍一下人工智能(pytorch)搭建模型10-pytorch搭建脉冲神经网络(SNN)实现及应用,脉冲神经网络(SNN)是一种基于生物神经系统的神经网络模型,它通过模拟神经元之间的电信号传递来实现信息处理。与传统的人工神经网络(ANN)不同,SNN 中的

    2024年02月08日
    浏览(31)
  • 搭建PyTorch神经网络进行气温预测

    数据表中 year,moth,day,week分别表示的具体的时间 temp_2:前天的最高温度值 temp_1:昨天的最高温度值 average:在历史中,每年这一天的平均最高温度值 actual:这就是我们的标签值了,当天的真实最高温度 friend:这一列可能是凑热闹的,你的朋友猜测的可能值,咱们不管它就好了

    2024年02月09日
    浏览(29)
  • pytorch搭建AlexNet网络实现花分类

    使用Dropout的方式在网络正向传播过程中随机失活一部分神经元,以减少过拟合 对其中的卷积层、池化层和全连接层进行分析 1,Conv1 注意:图片中用了两块GPU并行计算,上下两组图结构一样。 输入:input_size = [224, 224, 3] 卷积层: kernels = 48 * 2 = 96 组卷积核 kernel_size = 11 paddi

    2024年02月09日
    浏览(28)
  • 【搭建PyTorch神经网络进行气温预测】

    year month day week temp_2 temp_1 average actual friend 0 2016 1 1 Fri 45 45 45.6 45 29 1 2016 1 2 Sat 44 45 45.7 44 61 2 2016 1 3 Sun 45 44 45.8 41 56 3 2016 1 4 Mon 44 41 45.9 40 53 4 2016 1 5 Tues 41 40 46.0 44 41 数据表中 year,moth,day,week分别表示的具体的时间 temp_2:前天的最高温度值 temp_1:昨天的最高温度值 average:在历

    2024年02月14日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包