动手学深度学习(四)卷积神经网络-下

全连接层存在的问题:参数过大,计算成本过高。

一、网络中的网络(NiN)

1、NiN块

①NiN块的结构

NiN串联多个由卷积层和“全连接”层构成的小网络来构建一个深层网络。这种由卷积层和“全连接”层构成的小网络就是NiN块

(1)为什么卷积层不后接真的全连接层

卷积层的输入和输出通常是四维数组(样本,通道,高,宽),而全连接层的输入和输出则通常是二维数组(样本,特征)。如果想在全连接层后再接上卷积层,则需要将全连接层的输出变换为四维。

(2)1x1卷积层

1×1卷积层可以看成全连接层,其中空间维度(高和宽)上的每个元素相当于样本,通道相当于特征。因此,NiN使用1×1卷积层来替代全连接层,从而使空间信息能够自然传递到后面的层中去。

def nin_block(in_channels, out_channels, kernel_size, stride, padding):blk = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding),nn.ReLU(),nn.Conv2d(out_channels, out_channels, kernel_size=1),nn.ReLU(),nn.Conv2d(out_channels, out_channels, kernel_size=1),nn.ReLU())return blk

②NiN模型

(1)组成结构

NiN模型在每个NiN块后接一个步幅为2、窗口形状为3×3的最大池化层。

(2)输出结构

NiN去掉了AlexNet最后的3个全连接层,取而代之地,NiN使用了输出通道数等于标签类别数的NiN块,然后使用全局平均池化层对每个通道中所有元素求平均并直接用于分类。

这样设计的优点是:可以显著减小模型参数尺寸,从而缓解过拟合。

net = nn.Sequential(nin_block(1, 96, kernel_size=11, stride=4, padding=0),nn.MaxPool2d(kernel_size=3, stride=2),nin_block(96, 256, kernel_size=5, stride=1, padding=2),nn.MaxPool2d(kernel_size=3, stride=2),nin_block(256, 384, kernel_size=3, stride=1, padding=1),nn.MaxPool2d(kernel_size=3, stride=2), nn.Dropout(0.5),# 标签类别数是10nin_block(384, 10, kernel_size=3, stride=1, padding=1),# 全局平均池化层可通过将窗口形状设置成输入的高和宽实现nn.AvgPool2d(kernel_size=5),# 将四维的输出转成二维的输出,其形状为(批量大小, 10)d2l.FlattenLayer())

二、含并行连结的网络(GoogLeNet)

GoogLeNet中的基础卷积块叫作Inception块。

Inception块里有4条并行的线路:前3条线路使用窗口大小分别是1×1、3×3和5×5的卷积层来抽取不同空间尺寸下的信息,其中中间2个线路会对输入先做1×1卷积来减少输入通道数,以降低模型复杂度。第四条线路则使用3×3最大池化层,后接1×1卷积层来改变通道数。4条线路都使用了合适的填充来使输入与输出的高和宽一致。最后我们将每条线路的输出在通道维上连结,并输入接下来的层中去。

Inception块中可以自定义的超参数是每个层的输出通道数,我们以此来控制模型复杂度。

每一条线路的输出在空间维度(即高和宽)上保持一致,不同线路之间的主要差异在于输出通道数,将每条线路的输出在通道维度上拼接。假如当每条线路经过自己的卷积或池化操作后,输出的特征图的形状是 H×W×C1,H×W×C2​,H×W×C43,H×W×C4​,其中 C1​、C2​、C3​、C4 是不同线路输出的通道数。

class Inception(nn.Module):# c1 - c4为每条线路里的层的输出通道数def __init__(self, in_c, c1, c2, c3, c4):super(Inception, self).__init__()# 线路1,单1 x 1卷积层self.p1_1 = nn.Conv2d(in_c, c1, kernel_size=1)# 线路2,1 x 1卷积层后接3 x 3卷积层self.p2_1 = nn.Conv2d(in_c, c2[0], kernel_size=1)self.p2_2 = nn.Conv2d(c2[0], c2[1], kernel_size=3, padding=1)# 线路3,1 x 1卷积层后接5 x 5卷积层self.p3_1 = nn.Conv2d(in_c, c3[0], kernel_size=1)self.p3_2 = nn.Conv2d(c3[0], c3[1], kernel_size=5, padding=2)# 线路4,3 x 3最大池化层后接1 x 1卷积层self.p4_1 = nn.MaxPool2d(kernel_size=3, stride=1, padding=1)self.p4_2 = nn.Conv2d(in_c, c4, kernel_size=1)def forward(self, x):p1 = F.relu(self.p1_1(x))p2 = F.relu(self.p2_2(F.relu(self.p2_1(x))))p3 = F.relu(self.p3_2(F.relu(self.p3_1(x))))p4 = F.relu(self.p4_2(self.p4_1(x)))return torch.cat((p1, p2, p3, p4), dim=1)  # 在通道维上连结输出

三、批量归一化

底部的层指的是靠近原始输入数据的层。 

1、为什么要做批量归一化

即使输入数据已做标准化,训练中模型参数的更新依然很容易造成靠近输出层输出的剧烈变化。这种计算数值的不稳定性通常令我们难以训练出有效的深度模型。

2、批量归一化思路

在模型训练时,批量归一化利用小批量上的均值和标准差,不断调整神经网络中间输出,从而使整个神经网络在各层的中间输出的数值更稳定。

3、对全连接层做批量归一化

①批量归一化层处于的位置

位于全连接层中的仿射变换和激活函数之间。

②方法实现

全连接层的输入为u,权重参数和偏差参数分别为W和b,激活函数为ϕ,设批量归一化的运算符为BN:

小批量B由若干样本组成,其中任意样本x_i是d维的,批量归一化层的输出同样是d维向量:

具体的批量归一化实现如下:

(1)对小批量B求均值和方差,其中的平方计算是按元素求平方:

(2)使用按元素开方和按元素除法对x(i)标准化,这里ϵ>0是一个很小的常数,保证分母大于0:

(3)在上面标准化的基础上,批量归一化层引入了两个可以学习的模型参数,拉伸(scale)参数 γ 和偏移(shift)参数 β,这两个参数和x(i)形状相同,皆为d维向量。它们与x̂ (i)分别做按元素乘法(符号⊙)和加法计算::

可学习的拉伸和偏移参数保留了不对x(i)做批量归一化的可能:此时只需学出√γ=σB2+ϵ和β==μB。可以这样理解:如果批量归一化无益,理论上,学出的模型可以不使用批量归一化。

4、对卷积层做批量归一化

①批量归一化层处于的位置

对卷积层来说,批量归一化发生在卷积计算之后、应用激活函数之前。

②方法实现

如果卷积计算输出多个通道,我们需要对这些通道的输出分别做批量归一化,且每个通道都拥有独立的拉伸和偏移参数,并均为标量。

设小批量中有m个样本。在单个通道上,假设卷积计算输出的高和宽分别为p和q。我们需要对该通道中m×p×q个元素同时做批量归一化。对这些元素做标准化计算时,我们使用相同的均值和方差,即该通道中m×p×q个元素的均值和方差。

5、预测时的批量归一化

批量归一化确实在训练模式预测模式下表现不同,这主要是因为在训练时需要使用小批量样本的均值和方差,而在预测时为了确保输出的确定性,使用的是整个训练数据的均值和方差的估计值。

  • nn.BatchNorm1d:用于全连接层输出或一维序列数据的归一化。
  • nn.BatchNorm2d:用于卷积层输出的归一化,特别是图像或二维特征图数据。
def batch_norm(is_training, X, gamma, beta, moving_mean, moving_var, eps, momentum):# 判断当前模式是训练模式还是预测模式if not is_training:# 如果是在预测模式下,直接使用传入的移动平均所得的均值和方差X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)else:assert len(X.shape) in (2, 4)if len(X.shape) == 2:# 使用全连接层的情况,计算特征维上的均值和方差mean = X.mean(dim=0)var = ((X - mean) ** 2).mean(dim=0)else:# 使用二维卷积层的情况,计算通道维上(axis=1)的均值和方差。这里我们需要保持# X的形状以便后面可以做广播运算mean = X.mean(dim=0, keepdim=True).mean(dim=2, keepdim=True).mean(dim=3, keepdim=True)var = ((X - mean) ** 2).mean(dim=0, keepdim=True).mean(dim=2, keepdim=True).mean(dim=3, keepdim=True)# 训练模式下用当前的均值和方差做标准化X_hat = (X - mean) / torch.sqrt(var + eps)# 更新移动平均的均值和方差moving_mean = momentum * moving_mean + (1.0 - momentum) * meanmoving_var = momentum * moving_var + (1.0 - momentum) * varY = gamma * X_hat + beta  # 拉伸和偏移return Y, moving_mean, moving_var
net = nn.Sequential(nn.Conv2d(1, 6, 5), # in_channels, out_channels, kernel_sizenn.BatchNorm2d(6),nn.Sigmoid(),nn.MaxPool2d(2, 2), # kernel_size, stridenn.Conv2d(6, 16, 5),nn.BatchNorm2d(16),nn.Sigmoid(),nn.MaxPool2d(2, 2),d2l.FlattenLayer(),nn.Linear(16*4*4, 120),nn.BatchNorm1d(120),nn.Sigmoid(),nn.Linear(120, 84),nn.BatchNorm1d(84),nn.Sigmoid(),nn.Linear(84, 10))

四、残差网络(ResNet)

1、ResNet的提出背景

ResNet主要解决了深度神经网络在训练过程中出现的退化问题。在深层网络中,随着网络深度的增加,模型的训练效果并不总是变好,反而可能变得更差。具体表现为,较深的网络不仅会导致梯度消失或梯度爆炸的问题,还会使得训练误差增大,模型性能下降。

2、残差块

ResNet的核心设计是残差学习(Residual Learning)。它通过引入残差连接(skip connections)解决了深层网络中的优化问题,核心设计点包括:

①残差块

Net中每一层并不直接学习期望的输出,而是学习残差,即输入与输出之间的差异。对于每一个残差块,输入直接通过“跳跃连接”传递到输出,并且与通过卷积层学习的输出叠加:

F(x)是通过若干层卷积和非线性变换学习得到的残差函数(F(x)即输入与输出之间的差值),y残差块的输出x 输入数据。

  • 如果 F(x)很小(接近零),意味着输出与输入相差不大,此时网络可以很容易地学到恒等映射 H(x)≈x,因此即使网络非常深也不会出现退化问题。
  • 如果 F(x)较大,网络会逐渐学习输入与输出之间的差异,这也比直接去学习复杂的 H(x)容易得多。

跳跃连接(Skip Connection)

传统的深度网络在每一层都会完全依赖前一层的输出,而在ResNet中,通过跳跃连接,输入 x 直接跳过中间的非线性变换,参与到后面的计算中。这种设计减少了信息丢失,使得梯度更容易传播,缓解了梯度消失的问题。

恒等映射(Identity Mapping)

如果某一层的输出与输入相同,理论上通过跳跃连接可以确保这一层对网络的最终表现没有负面影响。这使得即使网络加深,也不会因为层数增加而使训练误差变得更高。

3、ResNet模型

①ResNet块的连接

②ResNet整体架构图 

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

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

相关文章

SpringBoot框架之KOB项目 - 配置Mysql与注册登录模块(上)

框架模型 每一个客户端(client)都会和后端(SpringBoot)进行通信,例如如果一个用户进行登录,需要向后端发送username、password,SpringBoot可以理解为一个一直在跑的程序,不断对用户…

3.Java高级编程实用类介绍(一)

三、Java高级编程实用类介绍(一) 文章目录 三、Java高级编程实用类介绍(一)一、枚举类型二、包装类三、Math 一、枚举类型 使用enum进行定义 public enum 枚举名字{值1,值2.... }二、包装类 每个基本类型在java.lang包中都有一个相应的包装类 /** new包装类(字符…

上海儿童自闭症寄宿制学校,让孩子找到归属感

在探讨自闭症儿童教育的广阔图景中,上海作为一座充满人文关怀的城市,始终致力于为这些特殊的孩子提供更加全面、专业的支持体系。而当我们把这份关注与努力投射到具体实践上,广州的星贝育园自闭症儿童寄宿制学校便成为了这样一个温馨而有力的…

JVM OutOfMemoryError 与 StackOverflowError 异常

目录 前言 堆溢出 虚拟机栈和本地方法栈溢出 方法区溢出 前言 JVM规范中规定, 除了程序计数器之外, 其他的运行时数据区域, 例如堆栈, 方法区, 都会出现OutOfMemoryError异常. 那么到底是怎么样的代码, 才会引起堆溢出, 栈溢出, 或者是方法区的溢出呢? 如果遇到了又该如何…

鸿蒙next json解析 ArkUI 带你玩转 arkts json解析

前言导读 相信很多同学再开发过程中都会遇到json解析的处理,不管是跟服务端交互 或者是读取本地的json 都会遇到json解析 那么正好今天有空正好讲一下鸿蒙next里面的json解析 JSON解析与生成 本模块提供了将JSON文本转换为JSON对应对象或值,以及将对象…

Mac OS系统如何下载安装Python解释器

目录 Mac安装Python的教程 mac下载并安装python解释器 如何下载和安装最新的python解释器 访问python.org(受国内网速的影响,访问速度会比较慢,不过也可以去我博客的资源下载) 打开历史发布版本页面 进入下载页 鼠标拖到页面…

【经典文献】双边滤波

文章目录 ICCV 1998基本思路双边高斯滤波 ICCV 1998 1995年,Aurich和Weule提出一种非线性高斯滤波器,三年后,Tomasi和Manduchi将其用于图像平滑,并将其命名为双边滤波。 Aurich, V., & Weule, J. (1995). Non-linear Gaussi…

【C++】list常见用法

🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:C从小白到高手 🌹往期回顾🌹:[C]vector常见用法 🔖 流水不争,争的是滔滔不息。 文章目录 一、list的介绍li…

web安全测试入门

参考课程: 04-软件安全测试基础-网络协议基础-网络模型_哔哩哔哩_bilibili 1.软件安全测试概述 安全测试: 安全性测试指有关验证应用程序的安全等级和识别潜在安全性缺陷的过程 导致软件出现安全问题的主要原因或根源是软件的安全漏洞 安全漏洞&#x…

Vue2源码解读

vue源码_哔哩哔哩_bilibili 1.Vue源码路径目录解读 Vue2源码的路径目录被设计得非常清晰,每个文件夹都承担着特定的职责和功能。以下是这些主要文件夹(compiler、core、platform、server、sfc、shared)的详细解读: 1. compiler …

变压器漏感对整流电路的影响

目录 1. 电压波形畸变 2. 输出电压波动 3. 电流纹波增加 4. 降低整流效率 5. 影响开关器件的性能 6. EMI(电磁干扰)增加 总结与应对措施 变压器漏感在整流电路中会产生一些影响,尤其在高频应用或电流变化较大的情况下,其影…

【Java】多线程:Thread类并行宇宙

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! 在现代编程中,多线程是提高程序性能和响应能力的一种重要手段。Java 通过 Thread 类和 Runnable 接口提供了丰富的线程管理功能。本文是对 Thread 类基本用法的总结。 线程创建 线程可以…

GEE 案例:利用2001-2024年的MODIS数据长时序ndvi指数归一化后的结果分析

目录 简介 指数 数据 代码 结果 简介 利用2001-2024年的MODIS数据长时序ndvi指数归一化后的结果分析,并加载时序图。 指数 NDVI指数(Normalized Difference Vegetation Index)是用来评估地表植被覆盖度和健康程度的指数。它通过计算红…

PMP--一模--解题--121-130

文章目录 12.采购管理--投标人会议(又称承包商会议、供应商会议或投标前会议)是在卖方提交建议书之前,在买方和潜在卖方之间召开的会议,其目的是确保所有潜在投标人对采购要求都有清楚且一致的理解,并确保没有任何投标…

【数据结构取经之路】图解AVL树

目录 AVL树的前世今生 走进AVL AVL树的实现 1、AVL树节点的定义 2、AVL树的插入 3、完整代码 AVL树的性能 AVL树的前世今生 我们知道,普通的二叉搜索树在不少场景下可以提高我们的查找效率。例如下面这种情况,我们要找22。从根开始,…

搭建一个基于角色的权限验证框架

说明:基于角色的权限验证(Role-Based Access Control,RBAC)框架,是目前大多数服务端的框架。本文介绍如何快速搭建一个这样的框架,不用Shiro、Spring Security、Sa-Token这样的“大框架”实现。 RBAC 基于…

[Meachines] [Medium] Bart Server Monitor+Internal Chat+UA投毒+Winlogon用户密码泄露权限提升

信息收集 IP AddressOpening Ports10.10.10.81TCP:80 $ nmap -p- 10.10.10.81 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-server-header: Micros…

在沉浸式翻译中使用SiliconCloud API:提升翻译体验

沉浸式翻译,作为广受好评的双语对照网页翻译插件,结合了硅基流动(SiliconFlow)的大语言模型,为用户提供了快速、准确的跨语言翻译服务。自2023年上线以来,这款AI双语对照网页翻译扩展已帮助超过100万用户跨…

【C++11 —— 异常】

C —— 异常 C语言传统的处理错误的方式C异常概念异常的使用异常的抛出和捕获异常的重新抛出异常安全异常规范 自定义异常体系自定义异常体系的目的 C标准库的异常体系异常的优缺点 C语言传统的处理错误的方式 在C语言中,错误处理通常依赖于返回值和全局变量的方式…

【程序人生】《把时间当做朋友》李笑来思维导图

李笑来,男,朝鲜族,1972年7月12日生,吉林人,畅销书作家、区块链专家、天使投资人。 INBlockchain硬币资本创始人,投资了区块链项目。曾在央视采访中自曝拥有六位数比特币。 出版发行《把时间当做朋友》 [9]、…