动手学深度学习—卷积神经网络(原理解释+代码详解)
目录
- 1. 从全连接层到卷积层
- 2. 图像卷积
- 2.1 互相关运算
- 2.2 卷积层
- 2.3 图像中目标的边缘检测
- 2.4 学习卷积核
- 2.5 特征映射和感受野
- 3. 填充和步幅
- 3.1 填充
- 3.2 步幅
- 4. 多输入多输出通道
- 4.1 多输入通道
- 4.2 多输出通道
- 4.3 1×1卷积核
- 5. 汇聚层
- 5.1 最大汇聚层和平均汇聚层
- 5.2 填充和步幅
- 5.3 多个通道
1. 从全连接层到卷积层
- 多层感知机对图像处理是百万维度,模型不可实现。
- 如果要在图片中找到某个物体,寻找方法应该和物体位置无关。
适合计算机视觉的神经网络架构:
- 平移不变性:不管检测对象出现在图像中的哪个位置,神经网络前几层应该对相同图像区域有相似的反应。
- 局部性:神经网络的前面几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系。
2. 图像卷积
2.1 互相关运算
严格来说,卷积层所表达的运算其实是互相关运算。
不同颜色所选的区域与同一个卷积核做互相关运算,最后得到输出。


同理,卷积核滑动进行互相关运算。最终得到高度为2,宽度为2的输出。

输出大小:
"""定义corr2d函数:1、该函数接受输入张量X和卷积核张量K,并返回输出张量Y2、输出大小 = 输入大小n(k)×n(w) - 卷积核大小k(h)×k(w)3、即:(n(k)-k(h)+1) × (n(w)-k(w)+1 )
"""
import torch
from torch import nn
from d2l import torch as d2ldef corr2d(X, K): #@save"""计算二维互相关运算"""# 卷积核的高度h和宽度w,K指卷积核Kernelh, w = K.shape# 设置输出Y的大小,用0进行填充Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))# 对局部区域做互相关运算for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i:i + h, j:j + w] * K).sum()return Y
对上图进行验证

2.2 卷积层
定义卷积层Conv2D:
- 卷积层对输入和卷积核权重进行互相关运算;
- 并在添加标量偏置之后产生输出。
"""定义卷积层Conv2D:1、卷积层对输入和卷积核权重进行互相关运算;2、并在添加标量偏置之后产生输出。
"""
class Conv2D(nn.Module):def __init__(self, kernel_size):super().__init__()# 设置权重self.weight = nn.Parameter(torch.rand(kernel_size))# 设置偏置self.bias = nn.Parameter(torch.zeros(1))# corr2d(X, K)def forward(self, x):return corr2d(x, self.weight) + self.bias
2.3 图像中目标的边缘检测
# 卷积层的一个简单应用:通过找到像素变化的位置,来检测图像中不同颜色的边缘。
# 1、构造一个6×8像素的黑白图像
X = torch.ones((6, 8))
X[:, 2:6] = 0
X

# 2、我们构造一个高度为1、宽度为2的卷积核K(水平相邻元素相同输出为0)
K = torch.tensor([[1.0, -1.0]])Y = corr2d(X, K)
Y

2.4 学习卷积核
"""由X生成Y的卷积核:1、构造一个卷积层,并将其卷积核初始化为随机张量;2、在每次迭代中,比较Y与卷积层输出的平方误差,然后计算梯度来更新卷积核;3、使用内置的二维卷积层,并忽略偏置。
"""
# 构造一个二维卷积层,它具有1个输出通道和形状为(1,2)的卷积核
conv2d = nn.Conv2d(1, 1, kernel_size=(1, 2), bias=False)# 这个二维卷积层使用四维输入和输出格式(批量大小、通道、高度、宽度),
# 其中批量大小和通道数都为1
X = X.reshape((1, 1, 6, 8))
Y = Y.reshape((1, 1, 6, 7))
lr = 3e-2 # 学习率# 进行训练,轮数为10。计算梯度并进行更新,输出loss
for i in range(10):# 定义损失函数:交叉熵损失Y_hat = conv2d(X)l = (Y_hat - Y) ** 2# 梯度置零conv2d.zero_grad()l.sum().backward()# 迭代卷积核# 梯度更新:w = w - lr * w'conv2d.weight.data[:] -= lr * conv2d.weight.grad# 每隔2轮输出一次if(i + 1) % 2 ==0:print(f'epoch{i+1}, loss{l.sum():.3f}')
这里可以看到学习的卷积核接近之前边缘检测的卷积核。

2.5 特征映射和感受野
- 输出的卷积层有时被称为特征映射。
- 在卷积神经网络中,对于某一层的任意元素x,其感受野是指在前向传播期间可能影响x计算的所有元素。
3. 填充和步幅
- 问题一:应用了连续卷积,最终得到的输出远小于输入大小,使得原始图像的边界丢失了许多有用信息,我们希望输入大小和输出大小相同?
解决:填充:在输入图像的边界填充元素(通常填充元素是0)- 问题二:有时原始的输入分辨率十分冗余,我们可能希望大幅降低图像的宽度和高度?
解决:步幅:设置卷积核滑动的步幅来减少采样次数- 问题三:卷积核为什么一般选择奇数?
解决:保持空间维度的同时,我们可以在顶部和底部填充相同数量的行,在左侧和右侧填充相同数量的列。
3.1 填充
填充(padding):在输入图像的边界填充元素(通常填充元素是0)


"""填充:1、输入给定8×8,输出要求8×82、卷积核的大小为3×3,所有侧边填充1个像素
"""
import torch
from torch import nn# 为了方便起见,我们定义了一个计算卷积层的函数。
# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数
def comp_conv2d(conv2d, X):# 这里的(1,1)表示批量大小和通道数都是1X = X.reshape((1, 1) + X.shape)Y = conv2d(X)# 省略前两个维度:批量大小和通道(1, 1, 8, 8)return Y.reshape(Y.shape[2:])conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1)
X = torch.rand(size=(8, 8))
print(X)
print(conv2d)
print(comp_conv2d(conv2d, X))
comp_conv2d(conv2d, X).shape

# 卷积核为5×3时,为了使输入和输出相同,高度填充2,宽度填充1
conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3), padding=(2, 1))
comp_conv2d(conv2d, X).shape

3.2 步幅
步幅(stride):每次滑动元素的数量

"""步幅:1、每次滑动元素的数量;2、为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素。
"""
# 将高度和宽度的步幅设置为2,从而将输入的高度和宽度减半
# (8 + 2 - 3) / 2 = 4
conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)
comp_conv2d(conv2d, X).shape

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

import torch
from d2l import torch as d2ldef corr2d_multi_in(X, K):# 先遍历“X”和“K”的第0个维度(通道维度),再把它们加在一起return sum(d2l.corr2d(x, k) for x, k in zip(X, K))# 构造输入张量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]]])corr2d_muti_in(X, K)

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与K+1(K中每个元素加1)和K+2连接起来,构造了一个具有3个输出通道的卷积核。
K = torch.stack((K, K + 1, K + 2), 0)# (输出通道数,输入通道数,高度,宽度)
K.shape

4.3 1×1卷积核
- 1×1卷积核被经常用来改变通道,相当于全连接层
- 可以对输入和输出的形状进行调整
# 使用全连接层实现1×1卷积
def corr2d_multi_in_out_1x1(X, K):c_i, h, w = X.shape# K:(输出通道,输入通道,高度,宽度)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))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)
assert float(torch.abs(Y1 - Y2).sum()) < 1e-6
print(Y1)
print(Y2)

5. 汇聚层
通过逐渐聚合信息,生成越来越粗糙的映射,最终实现学习全局表示的目标,同时将卷积图层的所有优势保留在中间层。
汇聚(pooling)层(也叫做池化层):
- 降低卷积层对位置的敏感性
- 降低对空间降采样表示的敏感性
5.1 最大汇聚层和平均汇聚层
汇聚层与卷积层的原理大体相似,只不过把互相关运算换成求最大值或者求平均值


# 最大汇聚层和平均汇聚层
"""定义汇聚层:1、设置汇聚层与输出的大小2、设置模式:大汇聚层和平均汇聚层
"""
import torch
from torch import nn
from d2l import torch as d2l# 默认为最大汇聚层
def pool2d(X, pool_size, mode='max'):# 获取汇聚层的高度和宽度p_h, p_w = pool_size# 设置输出层Y的高度和宽度Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))# 进行遍历,相当于对矩阵的局部区域[i:i+p_h, j:j+p_w]求最大值/平均值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()if mode == 'avg':Y[i, j] = X[i: i + p_h, j: j + p_w].mean()return Y# 构建输入张量X,验证二维最大汇聚层输出
X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
print(X)
print('最大汇聚层:\n', pool2d(X, (2, 2)))
print('平均汇聚层:\n', pool2d(X, (2, 2), 'avg'))
# print(f'最大汇聚层:{'\n'+pool2d(X, (2, 2))}')
# print(f'平均汇聚层:{pool2d(X, (2, 2), 'avg')}')

5.2 填充和步幅
与卷积层一样,汇聚层也可以改变输出形状
# 构造了一个输入张量X,它有四个维度,其中样本数和通道数都是1
X = torch.arange(16, dtype=torch.float32).reshape((1, 1, 4, 4))
X

5.3 多个通道
多个通道:
- 在处理多通道输入数据时,汇聚层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总
- 汇聚层的输出通道数与输入通道数相同。
"""多个通道:1、在处理多通道输入数据时,汇聚层在每个输入通道上单独运算,而不是像卷积层一样在通道上对输入进行汇总。2、汇聚层的输出通道数与输入通道数相同。
"""
X = torch.cat((X, X + 1), 1)
X
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
pool2d(X)

相关文章:
动手学深度学习—卷积神经网络(原理解释+代码详解)
目录 1. 从全连接层到卷积层2. 图像卷积2.1 互相关运算2.2 卷积层2.3 图像中目标的边缘检测2.4 学习卷积核2.5 特征映射和感受野 3. 填充和步幅3.1 填充3.2 步幅 4. 多输入多输出通道4.1 多输入通道4.2 多输出通道4.3 11卷积核 5. 汇聚层5.1 最大汇聚层和平均汇聚层5.2 填充和步…...
环球数科、BUFFALO面试(部分)
环球数科 系统复杂且需求迭代频繁,如何维护微服务之间的接口调用关系? API接口在设计的时候需要大量的需求文档,而且文档也需要不断维护。如何高效维护API文档就很重要了。以下是一些常见的API管理工具:Swagger:Swag…...
RabbitMQ快速入门
文章目录 1、RabbitMQ的概述1.1、什么是消息队列?1.2、为什么要使用消息队列?1.3、RabbitMQ的特点: 2、RabbitMQ的安装2.1 下载与安装2.2 常用命令 3、RabbitMQ消息发送和接受3.1 消息发送和接受机制3.2 AMQP的消息路由3.3 Exchange(交换机)的…...
使用Git在GitHub上部署静态页面
在GitHub中,我们可以将自己的静态页面部署到GitHub中,它会给我们提供一个地址使得我们的页面变成一个真正的网站,可以供用户访问。 一、在GitHub下创建仓库 二、将项目部署到GitHub上 1. 初始化Git仓库 2. 提交代码 3. 关联远程仓库 在Gi…...
SQL-每日一题【1084. 销售分析III】
题目 Table: Product Table: Sales 编写一个SQL查询,报告2019年春季才售出的产品。即仅在2019-01-01至2019-03-31(含)之间出售的商品。 以 任意顺序 返回结果表。 查询结果格式如下所示。 示例 1: 解题思路 前置知识 between and between…...
Redis 软件包,在 CentOS 7 中安装 Redis
Download | Redis 1. 解压 Redis 软件包。假设你的 Redis 软件包名为 redis.tar.gz,进入redis.tar.gz所在目录下 ,可以使用以下命令进行解压: tar xzf redis.tar.gz 2. 切换到 Redis 软件包的解压目录。假设解压后的目录名为 redis…...
01.Redis实现发送验证码保存功能
学习目标: 提示:学习如何利用Redis来实现发送验证码功能 学习产出: 1. 准备pom环境 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><…...
C++STL——deque容器详解
纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 💬文章目录 一.deque容器的基本概念二.deque容器常用操作①deque构造函数②deque元素操作③deque赋值操作④deque交换操作⑤deque大小操作⑥deque插入和删除…...
docker 哨兵模式和集群模式安装Redis7.0.12
docker 哨兵模式和集群模式安装Redis7.0.12 1.下载镜像 1.1 配置阿里云加速源 墙外能访问https://hub.docker.com/_/redis 的可跳过 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 登录后选择左侧的镜像工具>镜像加速器,获取加速器地址&#…...
go nil 与零值
go nil 与零值 区别描述: 在Go语言中,nil和零值是两个不同的概念,它们在处理空值或未初始化值时有不同的应用场景。 nil: 在Go语言中,nil表示指针类型的零值或者interface、function、map、slice、channel、error类…...
puppeteer监听response并封装为express服务调用
const express require(express); const puppeteer require(puppeteer); const app express(); let browser; // 声明一个全局变量来存储浏览器实例app.get(/getInfo, async (req, res) > {try {const page_param req.query.page; // 获取名为"page"的查询参数…...
kubernetes之Ingress
一、背景 Ingress是k8s中实现7层负载的实现方式,是公开集群外部流量到集群内服务的HTTP和HTTPS路由 二、Ingress基础 通常Ingress实现由Ingress 控制器和Ingress组成,Ingress控制器负责具体实现反向代理及负载均衡,Ingress负责定义匹配规则和…...
前端实现打印1 - 使用 iframe 实现 并 分页打印
目录 打印代码对话框预览打印预览 打印代码 <!-- 打印 --> <template><el-dialogtitle"打印":visible.sync"dialogVisible"width"50%"top"7vh"append-to-bodyclose"handleClose"><div ref"print…...
MIAOYUN获评“2023年度一云多芯稳定安全运行优秀案例”
2023年7月25日至26日,由中国信息通信研究院(简称“中国信通院”)、中国通信标准化协会主办的以“云领创新,算启新篇”为主题的“2023可信云大会”在北京成功举办。会上公布了多项前瞻领域的评估结果和2023年度最佳实践案例&#x…...
论文代码学习—HiFi-GAN(4)——模型训练函数train文件具体解析
文章目录 引言正文模型训练代码整体训练过程具体训练细节具体运行流程 多GPU编程main函数(通用代码)完整代码 总结引用 引言 这里翻译了HiFi-GAN这篇论文的具体内容,具体链接。这篇文章还是学到了很多东西,从整体上说,…...
安防视频综合管理合平台EasyCVR可支持的视频播放协议有哪些?
EasyDarwin开源流媒体视频EasyCVR安防监控平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、智能分析等能力。 视频监控综合管理平台EasyCVR具备视频融合能力,平台基于云边端一体化架构,具有强大的…...
一张表格讲明白white-space属性。html如何识别\n\r,让这些特殊换行符换行。
大多数标签在展示文本内容的时候都会默认把文本中的空白和换行符去掉,这的确大大的使得文本的排版更加美观了,也怎加了区域的利用率,可是就有一些需求是需要原原本本的展示出原汁原味的文本格式。那该如何展示出文本的内在格式呢?…...
【Linux】编写shell脚本将项目前一天打印的日志进行提取,并且单独保存
业务场景:又到了熟悉的业务场景环节,其实应用上有很多,我们为了方便提取日志中部分关键的内容,对接给其他人也好,方便自己统计也罢,都会比每次我们都去服务器上及时查看,或者下载全部日志再筛选…...
快速搭建单机RocketMQ服务(开发环境)
一、什么是RocketMQ RocketMQ是阿里巴巴开源的一个消息中间件,在阿里内部历经了双十一等很多高并发场景的考验,能够处理亿万级别的消息。2016年开源后捐赠给Apache,现在是Apache的一个顶级项目。 早期阿里使用ActiveMQ,…...
Centos7搭建Apache Storm 集群运行环境
文章目录 1. 安装 Java2. 下载并解压 Storm3. 配置环境变量4. 配置 ZooKeeper5. 配置 Stormstorm.yaml自定义 storm.yamlstorm-env.shlogback/cluster.xml 6. 启动 Storm 集群7. 验证 1. 安装 Java Storm 运行在 Java 平台上,因此需要先安装 Java。你可以使用以下命…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

