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

news2025/2/25 8:45:21

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

文章目录

  • 前言
  • 三、填充和步幅
    • 3.1. 填充
    • 3.2. 步幅
    • 3.3. 小结
  • 四、多输入多输出通道
    • 4.1. 多输入通道
    • 4.2. 多输出通道
    • 4.3. 1×1卷积层
    • 4.4. 小结
  • 总结


前言

上文对卷积有了初步的认识,其实卷积操作就是通过卷积核对每个通道的矩阵从左到右、从上至下进行互相关运算(可以提取图像中的特征,卷积窗口的填充和滑动步长都是超参数)得到一个输出矩阵,最后把多个通道的值也对应加起来得到最终的输出值。本章将继续学习有关知识。


三、填充和步幅

按前面所学内容,假设输入形状为 n h × n w n_h\times n_w nh×nw,卷积核形状为 k h × k w k_h\times k_w kh×kw,那么输出形状将是 ( n h − k h + 1 ) × ( n w − k w + 1 ) (n_h-k_h+1) \times (n_w-k_w+1) (nhkh+1)×(nwkw+1)
因此,卷积的输出形状取决于输入形状和卷积核的形状。

填充(padding)和*步幅(stride)*这两个因素会影响输出的大小

假设以下情景:
有时,在应用了连续的卷积之后,我们最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于 1 1 1所导致的。比如,一个 240 × 240 240 \times 240 240×240像素的图像,经过 10 10 10 5 × 5 5 \times 5 5×5的卷积后,将减少到 200 × 200 200 \times 200 200×200像素。如此一来,原始图像的边界丢失了许多有用信息。而填充是解决此问题最有效的方法;
有时,我们可能希望大幅降低图像的宽度和高度。例如,如果我们发现原始的输入分辨率十分冗余。步幅则可以在这类情况下提供帮助。

3.1. 填充

如上所述,在应用多层卷积时,我们常常丢失边缘像素。解决这个问题的简单方法即为填充在输入图像的边界填充元素(通常填充元素是 0 0 0

我们将 3 × 3 3 \times 3 3×3输入填充到 5 × 5 5 \times 5 5×5,那么它的输出就增加为 4 × 4 4 \times 4 4×4。阴影部分是第一个输出元素以及用于输出计算的输入和核张量元素:
在这里插入图片描述

通常,如果我们添加 p h p_h ph行填充(大约一半在顶部,一半在底部)和 p w p_w pw列填充(左侧大约一半,右侧一半),则输出形状将为

( n h − k h + p h + 1 ) × ( n w − k w + p w + 1 ) 。 (n_h-k_h+p_h+1)\times(n_w-k_w+p_w+1)。 (nhkh+ph+1)×(nwkw+pw+1)

这意味着输出的高度和宽度将分别增加 p h p_h ph p w p_w pw

在许多情况下,我们需要设置 p h = k h − 1 p_h=k_h-1 ph=kh1 p w = k w − 1 p_w=k_w-1 pw=kw1,使输入和输出具有相同的高度和宽度。

这样可以在构建网络时更容易地预测每个图层的输出形状。

卷积神经网络中卷积核的高度和宽度通常为奇数,例如1、3、5或7。
选择奇数的好处是,保持空间维度的同时,我们可以在顶部和底部填充相同数量的行,在左侧和右侧填充相同数量的列。

此外,使用奇数的核大小和填充大小也提供了书写上的便利。对于任何二维张量X,当满足:

  1. 卷积核的大小是奇数;
  2. 所有边的填充行数和列数相同;
  3. 输出与输入具有相同高度和宽度
    则可以得出:输出Y[i, j]是通过以输入X[i, j]为中心,与卷积核进行互相关计算得到的。

比如,在下面的例子中,我们创建一个高度和宽度为3的二维卷积层,并(在所有侧边填充1个像素)。给定高度和宽度为8的输入,则输出的高度和宽度也是8。

#定义一个计算卷积的函数(初始化卷积层权重,并对输入和输出扩大和缩减相应的维数)
def comp_conv2d(conv2d,x):
    x = x.reshape((1,1)+x.shape)# 这里的(1,1)表示批量样本大小和通道数都为1
    y = conv2d(x)
    return y.reshape(y.shape[2:]) #省去前两个维度

#这里每侧边都填充了1行1列,因此共填充了2行2列
conv2d = nn.Conv2d(1,1,kernel_size=3,padding=1)
x = torch.rand(size=(8,8))
print(comp_conv2d(conv2d,x).shape)

#当卷积核的高度和宽度不同时,我们可以填充不同的高度和宽度
conv2d = nn.Conv2d(1,1,kernel_size=(5,3),padding=(2,1))
print(comp_conv2d(conv2d,x).shape)


#结果:
torch.Size([8, 8])
torch.Size([8, 8])

3.2. 步幅

在计算互相关时,卷积窗口从输入张量的左上角开始,向下、向右滑动。 之前我们默认每次滑动一个元素。 但是,有时候为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素, 而每次滑动元素的数量称为步幅(stride)

如图是垂直步幅为 3 3 3,水平步幅为 2 2 2的二维互相关运算:
在这里插入图片描述

通常,当垂直步幅为 s h s_h sh、水平步幅为 s w s_w sw时,输出形状为:

⌊ ( n h − k h + p h + s h ) / s h ⌋ × ⌊ ( n w − k w + p w + s w ) / s w ⌋ . \lfloor(n_h-k_h+p_h+s_h)/s_h\rfloor \times \lfloor(n_w-k_w+p_w+s_w)/s_w\rfloor. ⌊(nhkh+ph+sh)/sh×⌊(nwkw+pw+sw)/sw.

如果我们设置了 p h = k h − 1 p_h=k_h-1 ph=kh1 p w = k w − 1 p_w=k_w-1 pw=kw1,则输出形状将简化为 ⌊ ( n h + s h − 1 ) / s h ⌋ × ⌊ ( n w + s w − 1 ) / s w ⌋ \lfloor(n_h+s_h-1)/s_h\rfloor \times \lfloor(n_w+s_w-1)/s_w\rfloor ⌊(nh+sh1)/sh×⌊(nw+sw1)/sw
更进一步,如果输入的高度和宽度可以被垂直和水平步幅整除,则输出形状将为 ( n h / s h ) × ( n w / s w ) (n_h/s_h) \times (n_w/s_w) (nh/sh)×(nw/sw)

下面,我们将高度和宽度的步幅设置为2,从而将输入的高度和宽度减半。


#步幅
conv2d = nn.Conv2d(1,1,kernel_size=3,padding=1,stride=2)
print(comp_conv2d(conv2d,x).shape)
conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))
print(comp_conv2d(conv2d, x).shape)

#结果:
torch.Size([4, 4])
torch.Size([2, 2])

默认情况下,填充为0,步幅为1。在实践中,我们很少使用不一致的步幅或填充,也就是说,我们通常有ph=pw和sh=sw。

3.3. 小结

  1. 填充可以增加输出的高度和宽度。这常用来使输出与输入具有相同的高和宽。
  2. 步幅可以减小输出的高和宽,
  3. 填充和步幅可用于有效地调整数据的维度

四、多输入多输出通道

当我们添加通道时,我们的输入和隐藏的表示都变成了三维张量。例如,每个RGB输入图像具有3×h×w的形状。我们将这个大小为3的轴称为通道(channel)维度。

4.1. 多输入通道

当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算

假设输入的通道数为 c i c_i ci,那么卷积核的输入通道数也需要为 c i c_i ci。如果卷积核的窗口形状是 k h × k w k_h\times k_w kh×kw,那么当 c i = 1 c_i=1 ci=1时,我们可以把卷积核看作形状为 k h × k w k_h\times k_w kh×kw的二维张量。

c i > 1 c_i>1 ci>1时,我们卷积核的每个输入通道将包含形状为 k h × k w k_h\times k_w kh×kw的张量。将这些张量 c i c_i ci连结在一起可以得到形状为 c i × k h × k w c_i\times k_h\times k_w ci×kh×kw的卷积核。由于输入和卷积核都有 c i c_i ci个通道,我们可以对每个通道输入的二维张量和卷积核的二维张量进行互相关运算,再对通道求和(将 c i c_i ci的结果相加)得到二维张量。

在这里插入图片描述

对图中所示用代码实现一下:

def corr2d_multi_in(x,k):
    return sum(d2l.corr2d(x,k) for x,k in zip(x,k))
X = torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],
               [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]])
K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])

print(corr2d_multi_in(X, K))

#结果:
tensor([[ 56.,  72.],
        [104., 120.]])

4.2. 多输出通道

每一层有多个输出通道是至关重要的。在最流行的神经网络架构中,随着神经网络层数的加深,我们常会增加输出通道的维数,通过减少空间分辨率以获得更大的通道深度。

我们可以将每个通道看作对不同特征的响应。而现实可能更为复杂一些,因为每个通道不是独立学习的,而是为了共同使用而优化的。因此,多输出通道并不仅是学习多个单通道的检测器。


def corr2d_multi_in_out(X, K):
    # 迭代“K”的第0个维度,每次都对输入“X”执行互相关运算。
    # 最后将所有结果都叠加在一起
    return torch.stack([corr2d_multi_in(X, k) for k in K], 0)

K = torch.stack((K, K + 1, K + 2), 0)
print(K.shape) #卷积核的数量是由K的第一个维度决定的,故这里是有三个卷积核(卷积核的输出通道数与卷积核的数量对应)
print(corr2d_multi_in_out(X,K))


#结果:
torch.Size([3, 2, 2, 2])
tensor([[[ 56.,  72.],
         [104., 120.]],

        [[ 76., 100.],
         [148., 172.]],

        [[ 96., 128.],
         [192., 224.]]])

现在的输出包含3个通道,第一个通道的结果与先前输入张量X和多输入单输出通道的结果一致。

4.3. 1×1卷积层

1×1卷积,即kh=kw=1,看起来似乎没有多大意义。 毕竟,卷积的本质是有效提取相邻像素间的相关特征,而1×1卷积显然没有此作用。 尽管如此,1×1仍然十分流行,经常包含在复杂深层网络的设计中。

因为使用了最小窗口, 1 × 1 1\times 1 1×1卷积失去了卷积层的特有能力——在高度和宽度维度上,识别相邻元素间相互作用的能力。
其实 1 × 1 1\times 1 1×1卷积的唯一计算发生在通道上。

下图展示了使用 1 × 1 1\times 1 1×1卷积核与 3 3 3个输入通道和 2 2 2个输出通道的互相关计算。

在这里插入图片描述

这里输入和输出具有相同的高度和宽度,输出中的每个元素都是从输入图像中同一位置的元素的线性组合。

我们可以将 1 × 1 1\times 1 1×1卷积层看作在每个像素位置应用的全连接层,以 c i c_i ci个输入值转换为 c o c_o co个输出值。
因为这仍然是一个卷积层,所以跨像素的权重是一致的。
同时, 1 × 1 1\times 1 1×1卷积层需要的权重维度为 c o × c i c_o\times c_i co×ci,再额外加上一个偏置。

下面,我们使用全连接层实现 1 × 1 1 \times 1 1×1卷积。请注意,我们需要对输入和输出的数据形状进行调整。


# 1x1卷积层
def corr2d_multi_in_out_1x1(X,K):
    c_i,h, w = X.shape
    c_o = K.shape[0]
    X = X.reshape((c_i,h*w)) #将每个通道的空间维度展平为一个列向量
    K = K.reshape((c_o,c_i))
    #全连接层中的矩阵乘法
    y = torch.matmul(K,X)
    return y.reshape(c_o,h,w) #恢复输出矩阵的通道数和空间维度


#当执行1×1卷积运算时,上述函数相当于先前实现的互相关函数corr2d_multi_in_out。
X= torch.normal(0,1,(3,3,3))
K = torch.normal(0,1,(2,3,1,1))
y1 = corr2d_multi_in_out_1x1(X,K)
y2 = corr2d_multi_in_out(X,K)
print(y1);print(y2)
assert float(torch.abs(y1-y2).sum()) < 1e-6

#结果:
tensor([[[ 0.5941, -0.5362, -1.0132],
         [ 1.8299, -1.2045,  1.1347],
         [-0.4486, -2.2969, -0.8045]],

        [[ 0.3476,  1.7180,  1.9936],
         [ 1.3062,  0.8710,  2.2610],
         [ 1.6681, -1.8917, -0.0728]]])
tensor([[[ 0.5941, -0.5362, -1.0132],
         [ 1.8299, -1.2045,  1.1347],
         [-0.4486, -2.2969, -0.8045]],

        [[ 0.3476,  1.7180,  1.9936],
         [ 1.3062,  0.8710,  2.2610],
         [ 1.6681, -1.8917, -0.0728]]])

4.4. 小结

  1. 多输入多输出通道可以用来扩展卷积层的模型。
  2. 以每像素为基础应用时, 1 × 1 1\times 1 1×1卷积层相当于全连接层。
  3. 1 × 1 1\times 1 1×1卷积层通常用于调整网络层的通道数量和控制模型复杂性。

总结

本章学习了填充和步幅这两个调整数据维度的应用原理,再就是学习了多输入与多输出通道的扩展卷积层模型的概念,以及1×1卷积层在调整通道数量上的运用。

下士闻道,大笑之──不笑,不足以为道。

–2023-10-12 进阶篇

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

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

相关文章

《开箱元宇宙》:《福布斯》如何通过 Web3 改进讲故事的方式

你们是否想知道 The Sandbox 如何融入世界上最具标志性的品牌和名人的战略&#xff1f;在本期《开箱元宇宙》系列中&#xff0c;我们与《福布斯》一起探讨了他们为何决定在 The Sandbox 中尝试 Web3&#xff0c;以及他们如何改变讲故事的方式&#xff0c;以便在一次体验中吸引超…

C++QT---QT-day1

/*************************登陆窗口制作***************************/ #include "mywindow.h"MyWindow::MyWindow(QWidget *parent): QMainWindow(parent) {this->resize(500,350);this->setWindowTitle("登陆界面");this->setWindowIcon(QIcon(…

【特纳斯电子】基于单片机的火灾监测报警系统-实物设计

视频及资料链接&#xff1a;基于单片机的火灾监测报警系统-实物设计 - 电子校园网 (mcude.com) 编号&#xff1a; T0152203M-SW 设计简介&#xff1a; 本设计是基于单片机的火灾监测报警系统&#xff0c;主要实现以下功能&#xff1a; 1.通过OLED显示温度、烟雾、是否有火…

Leetcode—136.只出现一次的数字【简单】

2023每日刷题&#xff08;二&#xff09; Leetcode—136.只出现一次的数字 位运算法 实现代码 int singleNumber(int* nums, int numsSize){int i 0;int res 0;for(; i < numsSize; i) {res ^ nums[i];}return res; }运行结果 之后我会持续更新&#xff0c;如果喜欢我的…

【网络安全 --- win10系统安装】win10 系统详细安装过程(提供资源)

一&#xff0c;资源下载 百度网盘镜像下载地址链接&#xff1a; 百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固&#xff0c;支持教育网加速&#xff0c;支持手机端。注册使用百度网盘即可享受免费存储空间https://pan.ba…

笔试算法题ACM模式输入输出处理

1. Python input之后得到的全是string类型&#xff0c;数字需要用int(n)进行转换 读取单个数 n int(input()) 读取一串数组&#xff1a; nums [int(n) for n in input().split()] &#xff08;nums是个数组&#xff09; 读取字符串&#xff1a; stringinput().split(…

队列的运行算法

1.链队&#xff1a; 插入 删除 打印 取队顶 #include <stdio.h> #include <stdlib.h>typedef struct Qnode{int data;struct Qnode *next; }Qnode,*QuenePtr;typedef struct {QuenePtr front;QuenePtr rear; }LinkQueue; //初始化 void InitQueue(LinkQueue *q){(…

从头开始编写BP,不使用MATLAB工具箱,纯手写matlab代码,以BP分类为例,MATLAB代码免费获取...

本期文章教大家纯代码搭建BP神经网络&#xff0c;适合大家深入理解BP神经网络&#xff0c;非常适合新手学习&#xff01; 现在直接用手写BP代码的很少&#xff0c;一般都是用的MATLAB自带BP函数。然而如果你会自行编写BP神经网络&#xff0c;将会深入理解BP神经网络的结构与原理…

计讯物联水利RTU强力推进小型水库雨水情测报和安全监测系统应用

政策背景 小型水库是城市供水、农业灌溉和防洪排涝的重要基础设施&#xff0c;关系到人民群众的生产生活和社会经济的稳定发展。当前&#xff0c;小型水库监测设施薄弱是水库安全管理的突出短板&#xff0c;因此&#xff0c;水利部自2021年以来推进实施小型水库雨水情测报设施、…

语法分析出错,不是 GROUP BY 表达式

报错 ### Cause: dm.jdbc.driver.DMException: 第 9 行, 第 69 列[30]附近出现错误: 语法分析出错 ; bad SQL grammar []; nested exception is dm.jdbc.driver.DMException: 第 9 行, 第 69 列[30]附近出现错误: 语法分析出错at org.springframework.jdbc.support.SQLState…

java入门程序-HelloWorld

1.java程序开发的三个步骤 1.开发java程序&#xff0c;需要三个步骤&#xff1a;编写代码&#xff0c;编译代码(javac)&#xff0c;运行代码(java) 注意事项&#xff1a; 1.第一个java程序建议使用记事本书写。 2.建议代码文件名全英文&#xff0c;首字母大写&#xff0c;满…

院内导航系统厂商分析

随着医疗技术的不断发展和医院规模的不断扩大&#xff0c;院内导航系统成为了现代化医院不可或缺的一部分。患者就医时&#xff0c;一个高效便捷的导航系统可以帮助他们快速找到目标科室&#xff0c;同时也能提高医院的整体运营效率。本文将推荐五家在院内导航市场具有竞争力的…

【算法|前缀和系列No.4】leetcode238. 除自身以外数组的乘积

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【leetcode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

EL表达式与JSTL

1.EL表达式 1.EL表达式概述 EL(Expression Language)&#xff1a;表达式语言 在 JSP 2.0 规范中加入的内容&#xff0c;也是 Servlet 规范的一部分 作用&#xff1a;在 JSP 页面中获取数据。让我们的 JSP 脱离 java 代码块和 JSP 表达式 语法&#xff1a;${ 表达式内容 } …

群晖NAS drive的远程访问和电脑硬盘的内网穿透挂载设置方法

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

【弃坑xdm】docker容器作为开发环境,更加灵活可靠

关于我准备转行深度学习~~ 弃坑xdm 弃坑xdm 弃坑xdm 转发给你的同学&#xff0c;吓他们一跳~~ ps:其实我准备使用docker容器作为开发环境&#xff0c;vscode可以直接连接docker容器&#xff0c;更加灵活可靠。

企业常用的项目管理工具推荐,了解有哪些选择

项目管理软件是一种帮助项目经理和团队有效地计划、组织和管理项目的工具。它为协作、通信和任务管理提供了一个集中的平台。市场上有各种各样的项目管理软件&#xff0c;每个都有其独特的特性和功能。企业常用的项目管理工具有哪些&#xff1f; 1.Zoho Projects Zoho Projec…

基于tornado BELLE 搭建本地的web 服务

我的github 将BELLE 封装成web 后端服务&#xff0c;采用tornado 框架 import timeimport torch import torch.nn as nnfrom gptq import * from modelutils import * from quant import *from transformers import AutoTokenizer import sys import json #import lightgbm a…

2023年中国城市矿产行业产值及发展趋势分析[图]

城市矿产是指工业化和城镇化过程中产生和蕴藏于废旧机电设备、电线电缆、通讯工具、汽车、家电、电子产品、金属和塑料包装物以及废料中&#xff0c;可循环利用的钢铁、有色金属、贵金属、塑料、橡胶等资源。 开展“城市矿产”示范基地建设是缓解资源瓶颈约束&#xff0c;减轻环…

BAT027:删除当前目录指定文件夹以外的文件夹

引言&#xff1a;编写批处理程序&#xff0c;实现删除当前目录指定文件夹以外的文件夹。 一、新建Windows批处理文件 参考博客&#xff1a; CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件&#xff0c;点击【编辑】…