深度学习——卷积神经网络(CNN)基础三

news2025/1/17 5:48:49

深度学习——卷积神经网络(CNN)基础三

文章目录

  • 前言
  • 五、汇聚层(池化层)
    • 5.1. 最大池化和平均池化
    • 5.2. 填充和步幅
    • 5.3. 多个通道
    • 5.3. 小结
  • 六、卷积神经网络(LeNet)
    • 6.1. LeNet
    • 6.2. 模型训练
    • 6.3. 小结
  • 总结


前言

前文介绍了卷积神经网络的一些基础知识,本章将继续学习池化层的概念,以及早期卷积神经网络(LeNet)的实现。

参考书:
《动手学深度学习》


五、汇聚层(池化层)

在处理图像时,我们希望逐渐减少隐藏表示的空间分辨率,将信息进行聚合。这样做的目的是,随着神经网络层次的增加,每个神经元对于输入的感受野(即其所关注的输入区域)也会变得更大。

池化层是神经网络中的一种常用层,其作用是降低卷积层对位置的敏感性,同时降低对空间降采样表示的敏感性

通过池化层的使用,神经网络可以逐渐降低输入数据的空间分辨率,聚集信息,提取更高级别的特征。这有助于网络在处理图像等复杂数据时更好地理解和捕捉图像的整体结构和重要特征。

5.1. 最大池化和平均池化

与卷积层类似,池化层运算符由一个固定形状的窗口(池化窗口)组成,
然而,不同于卷积层中的输入与卷积核之间的互相关计算,池化层不包含参数。
相反,池运算是确定性的,我们通常计算池化窗口中所有元素的最大值或平均值。这些操作分别称为最大池化层(maximum pooling)和平均池化层(average pooling)。

在这里插入图片描述

pooling通常被译为“池化”,在学习的这本书中,被译为“汇聚”。

汇聚窗口形状为 p × q p \times q p×q的汇聚层称为 p × q p \times q p×q汇聚层,汇聚操作称为 p × q p \times q p×q汇聚。

回到上章提到的对象边缘检测示例,现在我们将使用卷积层的输出作为 2 × 2 2\times 2 2×2最大汇聚的输入。
设置卷积层输入为X,汇聚层输出为Y
无论X[i, j]X[i, j + 1]的值相同与否,或X[i, j + 1]X[i, j + 2]的值相同与否,汇聚层始终输出Y[i, j] = 1
也就是说,使用 2 × 2 2\times 2 2×2最大汇聚层,即使在高度或宽度上移动一个元素,卷积层仍然可以识别到模式。

在下面的代码中的pool2d函数,我们实现汇聚层的前向传播

def pool2d(X, pool_size, mode='max'):
    p_h, p_w = pool_size
    Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            if mode == 'max':
                Y[i, j] = X[i: i + p_h, j: j + p_w].max()
            elif mode == 'avg':
                Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
    return Y

X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
print(pool2d(X, (2, 2)))
print(pool2d(X, (2, 2),mode="avg"))


#结果:
tensor([[4., 5.],
        [7., 8.]])
tensor([[2., 3.],
        [5., 6.]])


5.2. 填充和步幅

与卷积层一样,汇聚层也可以改变输出形状

X = torch.arange(16, dtype=torch.float32).reshape((1, 1, 4, 4))
# print(X)
#使用3×3的汇聚窗口
pool2d =nn.MaxPool2d(3)
print(pool2d(X))
pool2d = nn.MaxPool2d(3,padding=1,stride=2)
print(pool2d(X))
pool2d = nn.MaxPool2d((2, 3), stride=(2, 3), padding=(0, 1))
print(pool2d(X))


#结果:
tensor([[[[10.]]]])
tensor([[[[ 5.,  7.],
          [13., 15.]]]])
tensor([[[[ 5.,  7.],
          [13., 15.]]]])

5.3. 多个通道

在处理多通道输入数据时,汇聚层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总。 这意味着汇聚层的输出通道数与输入通道数相同


#在通道维度上连结张量X和X + 1,以构建具有2个通道的输入
X = torch.cat((X,X+1),1)
print(X)
pool2d = nn.MaxPool2d(3,padding=1,stride=2)
print(pool2d(X))

#结果:
tensor([[[[ 0.,  1.,  2.,  3.],
          [ 4.,  5.,  6.,  7.],
          [ 8.,  9., 10., 11.],
          [12., 13., 14., 15.]],

         [[ 1.,  2.,  3.,  4.],
          [ 5.,  6.,  7.,  8.],
          [ 9., 10., 11., 12.],
          [13., 14., 15., 16.]]]])
tensor([[[[ 5.,  7.],
          [13., 15.]],

         [[ 6.,  8.],
          [14., 16.]]]])


5.3. 小结

  1. 对于给定输入元素,最大汇聚层会输出该窗口内的最大值,平均汇聚层会输出该窗口内的平均值。
  2. 汇聚层的主要优点之一是减轻卷积层对位置的过度敏感
  3. 我们可以指定汇聚层的填充和步幅。
  4. 使用最大汇聚层以及大于1的步幅,可减少空间维度(如高度和宽度)。
  5. 汇聚层的输出通道数与输入通道数相同。

六、卷积神经网络(LeNet)

LeNet,它是最早发布的卷积神经网络之一, 这个模型是由AT&T贝尔实验室的研究员Yann LeCun在1989年提出的(并以其命名),目的是识别图像中的手写数字

6.1. LeNet

总体来看,(LeNet(LeNet-5)由两个部分组成:

卷积编码器:由两个卷积层组成;
全连接层密集块:由三个全连接层组成。

在这里插入图片描述

每个卷积块中的基本单元是一个5×5卷积层、一个sigmoid激活函数和平均汇聚层。请注意,虽然ReLU和最大汇聚层更有效,但它们在20世纪90年代还没有出现。

每个 2 × 2 2\times2 2×2池操作(步幅2)通过空间降采样将维数减少4倍。卷积的输出形状由批量大小、通道数、高度、宽度决定。

为了将卷积块的输出传递给稠密块,我们必须在小批量中展平每个样本(即将这个四维输入转换成全连接层所期望的二维输入)

LeNet的稠密块有三个全连接层,分别有120、84和10个输出。因为我们在执行分类任务,所以输出层的10维对应于最后输出结果的数量。

网络模型实现代码如下:

import torch
from torch import nn
from d2l import torch as d2l

net = nn.Sequential(
    nn.Conv2d(1,6,kernel_size=5,padding=2),nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2,stride=2),
    nn.Conv2d(6,16,kernel_size=5),nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2,stride=2),
    nn.Flatten(),
    nn.Linear(16*5*5,120),nn.Sigmoid(),
    nn.Linear(120,84),nn.Sigmoid(),
    nn.Linear(84,10)
)

X = torch.rand(size=(1,1,28,28),dtype=torch.float32)
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,"output shape:\t",X.shape)


#结果:
Conv2d output shape:	 torch.Size([1, 6, 28, 28])
Sigmoid output shape:	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape:	 torch.Size([1, 6, 14, 14])
Conv2d output shape:	 torch.Size([1, 16, 10, 10])
Sigmoid output shape:	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape:	 torch.Size([1, 16, 5, 5])
Flatten output shape:	 torch.Size([1, 400])
Linear output shape:	 torch.Size([1, 120])
Sigmoid output shape:	 torch.Size([1, 120])
Linear output shape:	 torch.Size([1, 84])
Sigmoid output shape:	 torch.Size([1, 84])
Linear output shape:	 torch.Size([1, 10])

在整个卷积块中,与上一层相比,每一层特征的高度和宽度都减小了。
第一个卷积层使用2个像素的填充,来补偿 5 × 5 5 \times 5 5×5卷积核导致的特征减少。第二个卷积层没有填充,因此高度和宽度都减少了4个像素。

随着层叠的上升,通道的数量从输入时的1个,增加到第一个卷积层之后的6个,再到第二个卷积层之后的16个。
同时,每个汇聚层的高度和宽度都减半。最后,每个全连接层减少维数,最终输出一个维数与结果分类数相匹配的输出。

6.2. 模型训练

我们已经实现了LeNet,让我们看看LeNet在Fashion-MNIST数据集上的表现

如下所示,训练函数train_ch6也类似于之前定义的train_ch3
由于我们将实现多层神经网络,因此我们将主要使用高级API。
以下训练函数假定从高级API创建的模型作为输入,并进行相应的优化。
我们使用Xavier随机初始化模型参数。
与全连接层一样,我们使用交叉熵损失函数和小批量随机梯度下降。

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)


def evaluate_accuracy_gpu(net, data_iter, device=None): #@save
    if isinstance(net, nn.Module):
        net.eval()  # 设置为评估模式
        if not device:
            device = next(iter(net.parameters())).device
    # 正确预测的数量,总预测的数量
    metric = d2l.Accumulator(2)
    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(X, list):
                # BERT微调所需的(之后将介绍)
                X = [x.to(device) for x in X]
            else:
                X = X.to(device)
            y = y.to(device)
            metric.add(d2l.accuracy(net(X), y), y.numel())
    return metric[0] / metric[1]


# @save
def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):
    def init_weights(m):
        if type(m) == nn.Linear or type(m) == nn.Conv2d:
            nn.init.xavier_uniform_(m.weight)
    net.apply(init_weights)
    print('training on', device)
    net.to(device)
    optimizer = torch.optim.SGD(net.parameters(), lr=lr)
    loss = nn.CrossEntropyLoss()
    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],
                            legend=['train loss', 'train acc', 'test acc'])
    timer, num_batches = d2l.Timer(), len(train_iter)
    for epoch in range(num_epochs):
        # 训练损失之和,训练准确率之和,样本数
        metric = d2l.Accumulator(3)
        net.train()
        for i, (X, y) in enumerate(train_iter):
            timer.start()
            optimizer.zero_grad()
            X, y = X.to(device), y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            l.backward()
            optimizer.step()
            with torch.no_grad():
                metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])
            timer.stop()
            train_l = metric[0] / metric[2]
            train_acc = metric[1] / metric[2]
            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:
                animator.add(epoch + (i + 1) / num_batches,
                             (train_l, train_acc, None))
        test_acc = evaluate_accuracy_gpu(net, test_iter)
        animator.add(epoch + 1, (None, None, test_acc))
    print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
          f'test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
          f'on {str(device)}')



#训练和评估LeNet-5模型
lr, num_epochs = 0.9, 10
train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())

d2l.plt.show()


#结果:
loss 0.467, train acc 0.824, test acc 0.814
7376.9 examples/sec on cpu

在这里插入图片描述

6.3. 小结

  1. 卷积神经网络(CNN)是一类使用卷积层的网络。
  2. 在卷积神经网络中,我们组合使用卷积层、非线性激活函数和汇聚层。
  3. 为了构造高性能的卷积神经网络,我们通常对卷积层进行排列,逐渐降低其表示的空间分辨率,同时增加通道数。
  4. 在传统的卷积神经网络中,卷积块编码得到的表征在输出之前需由一个或多个全连接层进行处理。

总结

回顾这三章,学习了与全连接层不同的卷积层以及池化层。在卷积神经网络中这三个都是基本的神经网络层。其中卷积层通过卷积核提取图像的特征,池化层通过最大池化或平均池化进行下采样并提取显著特征以减小计算复杂度,而全连接层则通过神经元之间的全连接进行最后的分类或回归。
按我的理解,可以把卷积层看作探测器(提取出探测到的特征),池化层看作集成器(将重要的特征汇聚起来),全连接层则是最后的数据处理器(对汇聚出来的特征数据做分类处理)。

到这里有关CNN的基础理论已经构建,之后将继续学习一些流行且较为经典的CNN模型,如AlexNet、VGG、残差神经网络等等。

人之所恶,唯孤、寡、不谷,而王公以为称。

–2023-10-13 进阶篇

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

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

相关文章

Centos7 安装 MySQL5.7 步骤

Centos7 安装 MySQL5.7 步骤 前言:一 .使用yum源方式安装1、卸载系统自带 mariadb查看并卸载系统自带的 Mariadb 2、下载并安装MySQL官方的 Yum2.1 下载mysql的yum源配置2.2 安装mysql的yum源2.3 使用yum方式安装mysql2.3.1 安装过程中报错解决问题描述解决方案 3、…

JTS-通过Coordinate点截断几何Geometry

背景 通过一堆点,线上的点或者靠近线的点,来截取线段,将线段截取成多段 代码片段 /*** 通过点截取线,点可以是线上的形状点也可以是靠近线的点** 线 ------------------------------------------* 点 . . . …

YOLO目标检测——复杂场景人员数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用:安防监控、人群管理、自动驾驶、城市规划、人机交互等等数据集说明:YOLO目标检测数据集,真实场景的高质量图片数据,数据场景丰富。使用lableimg标注软件标注,标注框质量高,含voc(xml)、coco(j…

C++模版初阶讲解

今日为大家分享C的模版,这里先把模版的初阶讲解一下,以后再讲解模版进阶! 前言:模版的引入 在我们进行学习的编程中,常常会有许多函数的功能相同,有些不同点可能就是其中的数据类型不同!如果我…

Jmeter连接Mysql数据库

一.下载mysql数据驱动 https://dev.mysql.com/downloads/connector/j/ 二、在Jmeter测试计划中添加驱动包 三、jmeter添加配置元件:JDBC Connection Configuration 四、Jmeter发送JDBC请求 五、提取mysql查询结果

工业交换机的应用场景

在选择工业交换机的时候,很多人会疑惑自己的场景是否适用工业交换机,工业交换机广泛应用于以下场景,大家可以参考了解 1. 工业自动化:工业交换机用于连接各种工业设备,如PLC(可编程逻辑控制器)、…

【探索C++】三大特性以及类和对象(包括类的特殊函数成员)

(꒪ꇴ꒪ ),Hello我是祐言QAQ我的博客主页:C/C语言,数据结构,Linux基础,ARM开发板,网络编程等领域UP🌍快上🚘,一起学习,让我们成为一个强大的攻城狮&#xff0…

遇到的问题总结

1、在实验室服务器里运行新项目的时候遇到 conda activate pytorch3_7(我的环境名字) conda install -c anaconda tensorboard (失败 一直堵在"Solving environment" ) pip install tensorboard

VS使用Visual Assist添加代码说明信息

写代码时,我们一般需要在代码的最前面添加一些说明信息,作者的联系方式等等。一些高级的 IDE 工具提供修改代码模板的功能,这样就能够在创建新代码时自动加上版权信息。Visual Studio 虽然没有提供这样的操作界面,但是我们可以通过…

Cron表达式每周三周五18点执行

Cron表达式每周三周五18点执行 0 0 18 ? * WED,FRI验证正确性:

C# Winform编程(5)菜单栏和工具栏

菜单和菜单组件 添加菜单编辑菜单菜单栏和工具栏 添加菜单 将MenuStrip控件拖拽到Form窗体顶部添加菜单 编辑菜单 添加菜单项,编辑菜单属性等功能。 右键单击已添加的菜单项可以弹出右键菜单: 可以设置菜单图标,使能菜单,显示…

[Python中常用的回归模型算法大全:从线性回归到XGBoost]

文章目录 概要保序回归:理论与实践多项式回归:探索数据曲线关系多输出回归的示例 概要 在数据科学和机器学习领域,回归分析是一项关键任务,用于预测连续型变量的数值。除了传统的线性回归模型外,Python提供了丰富多样…

每周电子W4——电路与电路模型

文章目录 每周电子W4——电路与电路模型电路电路模型电流和电压的参考方向电流的参考方向电压的参考方向 电功率 每周电子W4——电路与电路模型 电路 实际电路:由电工设备和电气器件按预期目的连接构成的电流的通路。 为完成某种预期的目的而设计、安装、运行的&a…

latex:表格水平宽度调整

解决方案 结果如下: 源代码如下: \documentclass{article} % \usepackage[utf8]{ctex} \usepackage{multirow} \usepackage{graphicx} \usepackage{booktabs} \usepackage{caption}\begin{document}\captionsetup{font{large}}\begin{table}[] \centeri…

数据结构 - 7(Map和Set 15000字详解)

一: 二叉搜索树 1.1 二叉搜索树的概念 概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所…

萝卜刀真的太危险了,于是我用Cocos做了一个

点击上方亿元程序员关注和★星标 引言 大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。 昨天,我女儿和我说想买一把萝卜刀,众所周知,萝卜刀在潜意识当中是存在一定的危险的,所以我果断拒绝了&…

Elasticsearch介绍及插件head和kibana下载

目录标题 一、Elasticsearch介绍二、Elasticsearch下载三、Elasticsearch-head四、Elasticsearch-kibana 一、Elasticsearch介绍 Elasticsearch是什么? Elasticsearch 是一个基于Lucene的分布式搜索和分析引擎,ES是elaticsearch简写,Elasticsearch是一…

Lite-UNet: 轻量且高效的细胞定位模型,轻量化的U-Net

论文:Lite-UNet: A Lightweight and Efficent Network for Cell Localization Paper Link:Lite-UNet: A Lightweight and Efficent Network for Cell Localization Code: https://github.com/Boli-trainee/Lite-UNet 核心思想:魔…

OpenHarmony 应用全局的 UI 状态存储:AppStorage

AppStorage 是应用全局的 UI 状态存储,是和应用的进程绑定的,由 UI 框架在应用程序启动时创建,为应用程序 UI 状态属性提供中央存储。 和 AppStorage 不同的是,LocalStorage 是页面级的,通常应用于页面内的数据共享。而…

cs231n

计算机视觉概述 a study of visual data visual data has exploded to a ridiculous degree 手机上两三个摄像头,more camera than people,视觉传感器,摄像头终端,产生很多视觉数据 visual data构成互联网上传输的的大部分数据 8…