Pytorch搭建GoogleNet神经网络

一、创建卷积模板文件

因为每次使用卷积层都需要调用Con2d和relu激活函数,每次都调用非常麻烦,就将他们打包在一起写成一个类。

in_channels:输入矩阵深度作为参数输入

out_channels: 输出矩阵深度作为参数输入

经过卷积层和relu激活函数之后通过正向传播得到输出。

class BasicConv2d(nn.Module):
    def __init__(self, in_chaannels, out_channels, **kwargs):
        super(BasicConv2d, self).__init__()
        self.conv = nn.Conv2d(in_chaannels, out_channels, **kwargs)
        self.conv = nn.ReLU(inplace=True)
     # 定义正向传播  
    def forward(self, x):
        x = self.conv(x)
        x = self.relu(x)
        return x

二、定义Inception结构 

 def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):

in_channels:输入特征矩阵的参数

ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj:表格中对应需要的参数。

branch1、2、3、4 分别对应inception结构中的四个分支,第一层只有一个分支,第二、三、四层都有1x1卷积核起到降维的作用。

所有定义的参数都来自于GoogleNet神经网络的参数表格。

详见GoogleNet神经网络介绍-CSDN博客

class Inception(nn.Module):
    def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):
        super(Inception, self).__init__()
        self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)
        
        self.branch2 = nn.Sequential(
            BasicConv2d(in_channels, ch3x3red, kernel_size=1),
            BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1)  # padding=1 保证输出大小等于输入大小
        )

        self.branch3 = nn.Sequential(
            BasicConv2d(in_channels, ch5x5red, kernel_size=1),
            BasicConv2d(ch5x5red, ch5x5, kernel_size=5, padding=2)
        )

        self.branch4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
            BasicConv2d(in_channels, pool_proj, kernel_size=1)
        )
        
    def forward(self, x):  # 将输出的特征矩阵分别输出到branch1234中
        branch1 = self.branch1(x)
        branch2 = self.branch2(x)
        branch3 = self.branch3(x)
        branch4 = self.branch4(x)
        # 将输出放入列表中
        outputs = [branch1, branch2, branch3, branch4]
        # 对四个输出特征矩阵在channel维度进行合并。“1”指需要合并的维度
        return torch.cat(outputs, 1)

三、辅助分类器

 def __init__(self, in_channels, num_classes):表示输入特征矩阵的个数和要分类的类别数。

辅助分类器1对应参数:N x 512 x 14 x 14 ,辅助分类器2对应参数:N x 528 x 14 x 14

在经过平均池化下采样后高度和宽度变成了4 x 4

辅助分类器1对应参数:N x 512 x 4 x 4 ,辅助分类器2对应参数:N x 528 x 4 x 4。

x = F.dropout(x, 0.5, training=self.training)

输入特征矩阵按照50%的比例随机失活。

training=self.training

当实例化一个模型model时,可以通过model.train() 和 model.eval()来控制模型的状态,在model.train()模式下,self.training=True, 在model.eval()模式下,self.training=False。

# 辅助分类器
class InceptionAux(nn.Module):
    def __init__(self, in_channels, num_classes):
        super(InceptionAux, self).__init__()
        self.averagePool = nn.AvgPool2d(kernel_size=5, stride=3)  # 平均池化下采样层
        self.conv = BasicConv2d(in_channels, 128, kernel_size=1)   # 1 x 1 的卷积层

        # 全连接层
        self.fc1 = nn.Linear(2048, 1024)
        self.fc2 = nn.Linear(1024, num_classes)


    # 定义正向传播
    def forward(self, x):
        # aux1:N x 512 x 14 x 14 aux2:N x 528 x 14 x 14
        x = self.averagePool(x)
        # aux1:N x 512 x 4 x 4   aux2:N x 528 x 4 x 4。
        x = self.conv(x)
        x = torch.flatten(x, 1)    # "1"表示按channel维度展平
        x = F.dropout(x, 0.5, training=self.training)
        x = self.fc2(x)
        return x

四、定义层结构

 def __init__(self, num_classes=1000, aux_logits=True, init_weights=False):

num_classes:分类类别个数

aux_logits: 是否使用辅助分类器

init_weight: 是否为权重进行初始化

self.aux_logits = aux_logits:将变量传入变为类变量

conv1、conv2、conv3 都是使用之前定义的卷积模板文件来定义的。

inception结构使用定义的 Inception结构。

self.avgpool = nn.AdaptiveAvgPool2d((1, 1)):自适应平均池化下采样

括号里输入所需要的输出特征矩阵的高和宽。

使用自适应平均池化下采样的好处:无论输入特征矩阵的高和宽时一个什么样的大小,都能得到所指定的高和宽,这样就可以不用限定输入图像的尺寸了。

class GoogleNet(nn.Module):
    def __init__(self, num_classes=1000, aux_logits=True, init_weights=False):
        super(GoogleNet, self).__init__()
        self.aux_logits = aux_logits

        self.conv1 = BasicConv2d(3, 64, kernel_size=7, stride=2, padding=3)
        self.maxpool1 = nn.MaxPool2d(3, stride=2, ceil_mode=True)
        self.conv2 = BasicConv2d(64, 64, kernel_size=1)
        self.conv3 = BasicConv2d(64, 192, kernel_size=3, padding=1)
        self.maxpool2 = nn.MaxPool2d(3, stride=2, ceil_mode=True)

        self.inception3a = Inception(192, 64, 96, 128, 16, 32, 32)
        self.inception3b = Inception(256, 128, 128, 192, 32, 96, 64)
        self.maxpool3 = nn.MaxPool2d(3, stride=2, ceil_mode=True)

        self.inception4a = Inception(480, 192, 96, 208, 16, 48, 64)
        self.inception4b = Inception(512, 160, 112, 224, 24, 64, 64)
        self.inception4c = Inception(512, 128, 128, 256, 24, 64, 64)
        self.inception4d = Inception(512, 112, 144, 288, 32, 64, 64)
        self.inception4e = Inception(528, 256, 160, 320, 32, 128, 128)
        self.maxpool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True)

        self.inception5a = Inception(832, 256, 160, 320, 32, 128, 128)
        self.inception5b = Inception(832, 384, 192, 384, 48, 128, 128)

        if self.aux_logits:  # 如果使用辅助分类器
            self.aux1 = InceptionAux(512, num_classes)   # 创建辅助分类器1
            self.aux2 = InceptionAux(528, num_classes)   # 创建辅助分类器2

        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.dropout = nn.Dropout(0.4)  # 40%比例随机失活
        self.fc = nn.Linear(1024, num_classes)
        if init_weights:
            self._initialize_weights()  # 如果需要初始化,将会进入模型权重初始化函数

定义正向传播 

将整个层结构输出出来。

if self.training and self.aux_logits:
            aux2 = self.aux2(x)

判断模型是处于训练模式还是验证模式?并判断是否要使用辅助分类器。

    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.maxpool2(x)
        x = self.inception3a(x)
        x = self.inception3b(x)
        x = self.maxpool3(x)
        x = self.inception4a(x)
        if self.training and self.aux_logits:
            aux1 = self.aux1(x)

        x = self.inception4a(x)
        x = self.inception4b(x)
        x = self.inception4c(x)
        x = self.inception4d(x)
        if self.training and self.aux_logits:
            aux2 = self.aux2(x)

        x = self.inception4e(x)

        x = self.maxpool4(x)
        x = self.inception5a(x)
        x = self.inception5b(x)

        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.dropout(x)
        x = self.fc(x)

        if self.training and self.aux_logits:  # 如果处于训练模式并使用了辅助分类器
            return x, aux2, aux1  # 将返回 主分类器、辅助分类器2、辅助分类器1 这样3个参数
        return x  # 否则只返回主分类器这一个函数

初始化权重函数

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):  # 卷积层
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            elif isinstance(m, nn.Linear):  # 全连接层
                nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)

五、训练模型 

没有报错,训练成功。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI:156-利用Python进行自然语言处理(NLP):情感分析与文本分类

本文收录于专栏:精通AI实战千例专栏合集 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 每一个案例都附带关键代码,详细讲解供大家学习,希望可以帮到大家。正…

JDK5.0新特性

目录 1、JDK5特性 1.1、静态导入 1.2 增强for循环 1.3 可变参数 1.4 自动装箱/拆箱 1.4.1 基本数据类型包装类 1.5 枚举类 1.6 泛型 1.6.1 泛型方法 1.6.2 泛型类 1.6.3 泛型接口 1.6.4 泛型通配符 1、JDK5特性 JDK5中新增了很多新的java特性,利用这些新…

你的RPCvs佬的RPC

一、课程目标 了解常见系统库的hook了解frida_rpc 二、工具 教程Demo(更新)jadx-guiVS CodejebIDLE 三、课程内容 1.Hook_Libart libart.so: 在 Android 5.0(Lollipop)及更高版本中,libart.so 是 Android 运行时(ART&#x…

计算机网络----第十二天

交换机端口安全技术和链路聚合技术 1、端口隔离技术: 用于在同vlan内部隔离用户; 同一隔离组端口不能通讯,不同隔离组端口可以通讯; 2、链路聚合技术: 含义:把连接到同一台交换机的多个物理端口捆绑为一个逻辑端口…

【前后端的那些事】SpringBoot 基于内存的ip访问频率限制切面(RateLimiter)

文章目录 1. 什么是限流2. 常见的限流策略2.1 漏斗算法2.2 令牌桶算法2.3 次数统计 3. 令牌桶代码编写4. 接口测试5. 测试结果 1. 什么是限流 限流就是在用户访问次数庞大时,对系统资源的一种保护手段。高峰期,用户可能对某个接口的访问频率急剧升高&am…

十大排序——6.插入排序

这篇文章我们来介绍一下插入排序 目录 1.介绍 2.代码实现 3.总结与思考 1.介绍 插入排序的要点如下所示: 首先将数组分为两部分[ 0 ... low-1 ],[ low ... arr.length-1 ],然后,我们假设左边[ 0 ... low-1 ]是已排好序的部分…

Spring Boot 多环境配置:YML 文件的三种高效方法

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

力扣:141. 环形链表

力扣:141. 环形链表 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾…

uni-app学习

目录 一、安装HBuilderX 二、创第一个uni-app 三、项目目录和文件作用 四、全局配置文件(pages.json) 4.1 globalStyle(全局样式) 导航栏:背景颜色、标题颜色、标题文本 导航栏:开启下拉刷新、下拉背…

LeetCode 409—— 最长回文串

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 要想组成回文串,那么只有最中间的字符可以是奇数个,其余字符都必须是偶数个。 所以,我们先遍历一遍字符串,统计出每个字符出现的次数。 然后如果某个字符出现了偶…

【数据分享】历次人口普查数据(一普到七普)

国之情,民之意,查人口,定大计。 第七次人口普查已经结束,那么,为了方便大家把七普数据与之前的数据做对比,地理遥感生态网整理了从一普到七普人口数据,并且把第七次人口普查的数据也一并分享给…

当全连接队列满了,tcp客户端收到服务端RST信令的模拟

当tcp服务端全连接队列满了后,并且服务端也不accept取出连接,客户端再次连接时,服务端能够看到SYN_RECV状态。但是客户端看到的是ESTABLISHED状态,所以客户端自认为成功建立了连接,故其写往服务端写数据,发…

JVM之本地方法栈和程序计数器和堆

本地方法栈 本地方法栈是为虚拟机执行本地方法时提供服务的 JNI:Java Native Interface,通过使用 Java 本地接口程序,可以确保代码在不同的平台上方便移植 不需要进行 GC,与虚拟机栈类似,也是线程私有的,…

C语言--函数递归

目录 1、什么是递归? 1.1 递归的思想 1.2 递归的限制条件 2. 递归举例 2.1 举例1:求n的阶乘 2.2 举例2:顺序打印⼀个整数的每⼀位 3. 递归与迭代 扩展学习: 早上好,下午好,晚上好 1、什么是递归&…

【鸿蒙开发】生命周期

1. UIAbility组件生命周期 UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态。 UIAbility生命周期状态 1.1 Create状态 Create状态为在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中…

gcc常用命令指南(更新中...)

笔记为gcc常用命令指南(自用),用到啥方法就具体研究一下,更新进去... 编译过程的分布执行 64位系统生成32位汇编代码 gcc -m32 test.c -o test -m32用于生成32位汇编语言

大学生前端学习第一天:了解前端

引言: 哈喽,各位大学生们,大家好呀,在本篇博客,我们将引入一个新的板块学习,那就是前端,关于前端,GPT是这样描述的:前端通常指的是Web开发中用户界面的部分,…

【读论文】【泛读】三篇生成式自动驾驶场景生成: Bevstreet, DisCoScene, BerfScene

文章目录 1. Street-View Image Generation from a Bird’s-Eye View Layout1.1 Problem introduction1.2 Why1.3 How1.4 My takeaway 2. DisCoScene: Spatially Disentangled Generative Radiance Fields for Controllable 3D-aware Scene Synthesis2.1 What2.2 Why2.3 How2.4…

解决QtCreator不能同时运行多个程序的方法

当我们运行QtCreator代码的时候,往往一个代码,可能需要打开好几个运行,但是会出现的情况就是,如果打开了一个界面,当我么再运行的时候,第一个界面就没有了,而且可能会出现终端报错的情况&#x…

虚拟环境下的Pip引用外部环境的解决方法

当你使用新创建的虚拟环境时,测试pip list却显示了一堆自己没有的功能包,这是因为你的环境错乱了,废话不多说直接上解决办法。 设置-》高级系统设置 环境变量 在系统变量部分,Anaconda要求前边没有其余的python环境路径。
最新文章