Pytorch 第八回:卷积神经网络——GoogleNet模型

ops/2025/3/6 7:43:56/

Pytorch 第八回:卷积神经网络——GoogleNet模型

本次开启深度学习第八回,基于Pytorch的GoogleNet卷积神经网络模型。对于卷积神经网络,咱们讲过了AlexNe模型和VGG模型。本回再分享一个新的模型,叫做GoogleNet模型。这个模型的突出点是采用了不同大小的卷积核进行组合训练。接下来给大家分享具体思路。
本次学习,借助的平台是PyCharm 2024.1.3,python版本3.11 numpy版本是1.26.4,pytorch版本2.0.0+cu118

文章目录

  • Pytorch 第八回:卷积神经网络——GoogleNet模型
  • 前言
    • 1、GoogleNet模型
    • 2、inception块
    • 3、批量规范化
    • 4、影响神经网络的训练因素有哪些,可以先总结一下:
  • 一、数据准备
  • 二、模型准备
    • 1.搭建inception块
    • 2.GoogleNet网络搭建
    • 3.定义损失函数和优化器
  • 二、模型训练
    • 1、实例化模型
    • 2、迭代训练
    • 3、输出展示
  • 总结


前言

讲解模型前,先分享几个概念,统一下思想:

1、GoogleNet模型

2014年的ImageNet大规模视觉竞赛中,出彩的不止有VGG模型,还有GoogleNet模型。GoogleNet模型在当年是夺得了比赛的冠军,VGG模型夺得了亚军。GoogLeNet模型,在不大量增加硬件计算力的前提下,采用提高网络模型深度和宽度的方法,提高了模型的准确率‌。其中,GooogleNet模型的核心结构是Inception块。Inception块架构如下图所示:
在这里插入图片描述

2、inception块

如上图所示,inception块有四条路径并联组成。左一路径有一层卷积;左二路径有两层不同卷积核的卷积层;右二路径有两层不同卷积核的卷积;右一路径有一层卷积和一层池化。具体代码可以继续看下文。
该结构的成功,表明不同尺寸的滤波器可以有效识别不同范围的图像细节。那这个块有可改变的的变量吗?肯定有,它的超参数是每层输入和输出的通道数。
注:
在机器学习中,超参数是模型训练过程的配置变量。

3、批量规范化

通过批量规范化,可以帮助深层神经网络在短时间进行收敛。
其公式如下:
在这里插入图片描述
其中,x为小批量的输入,u’为小批量样本的均值,p’为小批量样本的标准差。应用标准化后,生成的小批量的均值为0,单位方差为1。由于单位方差是人为的影响,因此需要拉伸参数a和偏移参数b进行矫正。同时,参数a和b是需要在模型训练过程中进行学习优化的。
注:
在训练模式下,数据的均值和方差只能通过小批量的方式来获取,而测试模式下,可以根据整个测试集进行精确计算均值和方差。

4、影响神经网络的训练因素有哪些,可以先总结一下:

1)数据预处理的效果;
2)随着神经网络的加深,中间层的变量具有更大的变化范围;
3)网络的层数增多时,其过拟合的几率也在加大。

闲言少叙,直接展示逻辑,先上引用:

import numpy as np
import torch
from torch import nn
from torchvision.datasets import CIFAR10
import time
from torch.utils.data import DataLoader

一、数据准备

如前几回一样,本次仍然采用CIFAR10数据集,因此不做重点解释(有兴趣的可以查看前两回的内容),本回只展示代码:

def data_tf(x):x = x.resize((96, 96), 2)  x = np.array(x, dtype='float32') / 255x = (x - 0.5) / 0.5  x = x.transpose((2, 0, 1))  x = torch.from_numpy(x)return x
train_set = CIFAR10('./data', train=True, transform=data_tf)
train_data = torch.utils.data.DataLoader(train_set, batch_size=64, shuffle=True)

二、模型准备

1.搭建inception块

(展示的代码有点长,大家不要一上来就感到心烦,耐心看一下,还是比较简单。)
如上文所述,inception块是将四个线路的网络合成了一个网络。需要注意的是,这里为了加快数据的收敛,引用了批量标准化。这点可能和原始的inception块结构不一样。
inception块的输入参数由各个路线的通道数量组成,输出为搭建好的inception网络,具体如下:

class inception(nn.Module):def __init__(self, channel_in, channel_out1,  channel_out2,  channel_out3, channel_out4):super(inception, self).__init__()channel_out2_1 = channel_out2[0]channel_out2_2 = channel_out2[1]channel_out3_1 = channel_out3[0]channel_out3_2 = channel_out3[1]# 第一条线路 1*1卷积self.path1 = nn.Sequential(nn.Conv2d(channel_in, channel_out1, kernel_size=1, stride=1),nn.BatchNorm2d(channel_out1, eps=1e-3),nn.ReLU(True))# 第二条线路 1*1卷积-> 3*3卷积+填充1self.path2 = nn.Sequential(nn.Conv2d(channel_in, channel_out2_1, kernel_size=1, stride=1),nn.BatchNorm2d(channel_out2_1, eps=1e-3),nn.ReLU(True),nn.Conv2d(channel_out2_1, channel_out2_2, kernel_size=3, stride=1, padding=1),nn.BatchNorm2d(channel_out2_2, eps=1e-3),nn.ReLU(True))# 第三条线路 1*1卷积-> 5*5卷积+填充2self.path3 = nn.Sequential(nn.Conv2d(channel_in, channel_out3_1, kernel_size=1, stride=1),nn.BatchNorm2d(channel_out3_1, eps=1e-3),nn.ReLU(True),nn.Conv2d(channel_out3_1, channel_out3_2, kernel_size=5, stride=1, padding=2),nn.BatchNorm2d(channel_out3_2, eps=1e-3),nn.ReLU(True))# 第四条线路 3*3池化+填充1-> 3*3卷积self.path4 = nn.Sequential(nn.MaxPool2d(3, stride=1, padding=1),nn.Conv2d(channel_in, channel_out4, kernel_size=1, stride=1),nn.BatchNorm2d(channel_out4, eps=1e-3),nn.ReLU(True))def forward(self, x):y1 = self.path1(x)y2 = self.path2(x)y3 = self.path3(x)y4 = self.path4(x)output = torch.cat((y1, y2, y3, y4), dim=1)return output

2.GoogleNet网络搭建

GoogleNet模型下有五个网络块,通过使用9个Inception块和池化层的堆叠来完成其数值预测。从代码中可以看出,相比前两回分享的模型,GoogleNet模型的网络是又宽又深。当然,GoogleNet模型主要由卷积层和池化层组成,减少了全连接层,因此其神经元的个数在一定程度上也是优化过的。
GoogleNet模型输入为数据的通道数,输出为分类的类别数目。

class googlenet(nn.Module):def __init__(self, channel_in, class_out):super(googlenet, self).__init__()# 网络块1self.block1 = nn.Sequential(nn.Conv2d(channel_in, 64, kernel_size=7, stride=2,padding=3),nn.BatchNorm2d(64, eps=1e-3),nn.ReLU(True),nn.MaxPool2d(3, 2,padding=1))# 网络块2self.block2 = nn.Sequential(nn.Conv2d(64, 64, kernel_size=1),nn.BatchNorm2d(64, eps=1e-3),nn.ReLU(True),nn.Conv2d(64, 192, kernel_size=3,  padding=1),nn.BatchNorm2d(192, eps=1e-3),nn.ReLU(True),nn.MaxPool2d(3, 2,padding=1))# 网络块3self.block3 = nn.Sequential(inception(192, 64, (96, 128), (16, 32), 32),inception(256, 128, (128, 192), (32, 96), 64),nn.MaxPool2d(3, 2))# 网络块4self.block4 = nn.Sequential(inception(480, 192, (96, 208), (16, 48), 64),inception(512, 160, (112, 224), (24, 64), 64),inception(512, 128, (128, 256), (24, 64), 64),inception(512, 112, (144, 288), (32, 64), 64),inception(528, 256, (160, 320), (32, 128), 128),nn.MaxPool2d(3, 2,padding=1))# 网络块5self.block5 = nn.Sequential(inception(832, 256, (160, 320), (32, 128), 128),inception(832, 384, (182, 384), (48, 128), 128),nn.AvgPool2d(2))# 分类self.classifier = nn.Linear(1024, class_out)def forward(self, x):x = self.block1(x)x = self.block2(x)x = self.block3(x)x = self.block4(x)x = self.block5(x)# 将矩阵拉平x = x.view(x.shape[0], -1)x = self.classifier(x)return x

注:由于篇幅问题,通道数的计算,在这里就不展示了,有兴趣的可以在小记当中观看。

3.定义损失函数和优化器

定义交叉熵损失函数和梯度下降函数优化器(学习率设定为0.01)。

Loss_f = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(classify_GoogleNet.parameters(), lr=0.01)

二、模型训练

1、实例化模型

在实例化时,设定输入通道为3,输出类别数为10。

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("device=", device)
classify_GoogleNet = googlenet(3, 10).to(device)

2、迭代训练

进行20次迭代训练

time1 = time.time()
for k in range(20):train_loss = 0train_acc = 0classify_GoogleNet.train()  # 将模型设为测试模式for x_data, y_data in train_data:x_data = x_data.to(device)y_data = y_data.to(device)# 前向传播y_predict = classify_GoogleNet(x_data)loss_train = Loss_f(y_predict, y_data).to(device)# 反向传播optimizer.zero_grad()  # 梯度清零loss_train.backward()  # 计算梯度optimizer.step()  # 使用优化器更新参数# 记录误差train_loss += loss_train# 计算分类的准确率_, pred = y_predict.max(1)train_correct = (pred == y_data).sum().item() / x_data.shape[0]train_acc += train_correcttime_consume = time.time() - time1print('epoch:{},TrainLoss:{:.6f},TrainAcc:{:.6f},consume time:{:.3f}s'.format(k,train_loss / len(train_data),train_acc / len(train_data),time_consume))
torch.save(classify_GoogleNet.state_dict(), 'classify_GoogleNet_params.pth')

3、输出展示

与前两回相比,此次训练集训练的精度更高,损失值更低,但时间也是花费的更多。

epoch:0,TrainLoss:1.480232,TrainAcc:0.458440,consume time:302.479s
epoch:4,TrainLoss:0.527561,TrainAcc:0.814978,consume time:1512.602s
epoch:8,TrainLoss:0.212731,TrainAcc:0.926031,consume time:2728.588s
epoch:12,TrainLoss:0.093475,TrainAcc:0.967032,consume time:3948.487s
epoch:16,TrainLoss:0.055090,TrainAcc:0.980818,consume time:5171.283s
epoch:19,TrainLoss:0.030331,TrainAcc:0.989950,consume time:6088.418s

总结

1、数据准备:准备CIFAR10数据集
2、模型准备:准备inception块,GoogleNet模型,交叉熵损失函数和优化器
3、数据训练:实例化训练模型,并进行20次数据训练。


http://www.ppmy.cn/ops/163534.html

相关文章

TCP-UDP-WebSocket-组播-单播

1. TCP 通信 TCP(Transmission Control Protocol): 特点: 面向连接,可靠传输。 保证数据顺序和完整性。 适用于需要可靠传输的场景(如文件传输、网页浏览)。 C 语言案例: 服务器端…

全局异常处理器为什么不能处理过滤器异常,有那些解决方案

一、全局异常处理器无法处理过滤器异常的原因 1. 请求生命周期的不同阶段 过滤器(Filter):过滤器是Servlet规范的一部分,它在请求进入Servlet容器时首先被执行。过滤器可以修改请求或响应,甚至可以完全终止请求处理过…

C语言中的野指针如何避免

野指针(Dangling Pointer)是指指向无效内存地址的指针,使用野指针会导致程序出现未定义行为,如程序崩溃、数据损坏等。以下为你详细介绍几种常见的野指针情况: 未初始化的指针 当你声明一个指针变量,但没有…

华为hcie证书有什么作用?

新盟教育 专注华为认证培训十余年 为你提供认证一线资讯! 在当今数字化飞速发展的时代,ICT行业对专业人才的需求日益增长。华为HCIE证书作为华为认证体系中的最高级别认证,无疑是众多IT从业者追求的目标。那么,华为HCIE证书到底有…

探秘大尺寸 PCB 打样:猎板 PCB 解锁高精度制造密码

在当今电子产品的研发与生产领域,大尺寸PCB(通常指尺寸超过600mm600mm的电路板)凭借其强大的功能集成能力和广泛的特殊应用场景,逐渐成为行业关注的焦点。然而,其复杂的特性也对生产工艺提出了极为严苛的要求。猎板PCB…

Beyond Compare for mac v5.0.6.30713 文件对比利器 支持M、Intel芯片

Mac毒搜集到的Beyond Compare是一套超级的文件及文件夹(目录)的比较工具,不仅可以快速比较出两个目录的不同,还可以比较每个文件的内容,而且可以任意显示比较结果。 应用介绍 程序内建了文件浏览器,方便您对文件、文件夹、压缩包…

山东大学计算机科学与技术学院软件工程实验日志

--- Author: "Inori_333" Date: 2025-03-04 --- 实验一 团队建立、阅读开源软件 1.队伍创建与分工 队伍最终确定由5人组成,小组成员之间进行了高效的沟通,并确定了各自的负责的部分内容。 2.代码复现与分析 写在前面:由于“…

C++核心编程之Deque容器

🚀 深入浅出deque容器:双端队列的奇幻漂流 摘要:想拥有既能"头铁"插入数据,又能"尾行"删除元素的神奇容器吗?快来解锁STL中的瑞士军刀——deque容器!本文用趣味比喻实战代码&#xff…