怎么做自己的彩票网站,无锡微网站制作,怎样做竞价推广,深圳网站制作哪家便宜以下内容为结合李沐老师的课程和教材补充的学习笔记#xff0c;以及对课后练习的一些思考#xff0c;自留回顾#xff0c;也供同学之人交流参考。
本节课程地址#xff1a;卷积层_哔哩哔哩_bilibili 代码_哔哩哔哩_bilibili
本节教材地址#xff1a;6.2. 图像卷积 — 动…以下内容为结合李沐老师的课程和教材补充的学习笔记以及对课后练习的一些思考自留回顾也供同学之人交流参考。
本节课程地址卷积层_哔哩哔哩_bilibili 代码_哔哩哔哩_bilibili
本节教材地址6.2. 图像卷积 — 动手学深度学习 2.0.0 documentation (d2l.ai)
本节开源代码...d2l-zhpytorchchapter_multilayer-perceptronsconv-layer.ipynb 图像卷积
上节我们解析了卷积层的原理现在我们看看它的实际应用。由于卷积神经网络的设计是用于探索图像数据本节我们将以图像为例。
互相关运算
严格来说卷积层是个错误的叫法因为它所表达的运算其实是互相关运算cross-correlation而不是卷积运算。 根据 6.1节 中的描述在卷积层中输入张量和核张量通过(互相关运算)产生输出张量。
首先我们暂时忽略通道第三维这一情况看看如何处理二维图像数据和隐藏表示。在 下图 中输入是高度为3、宽度为3的二维张量即形状为3 × 3。卷积核的高度和宽度都是2而卷积核窗口或卷积窗口的形状由内核的高度和宽度决定即2 × 2。 在二维互相关运算中卷积窗口从输入张量的左上角开始从左到右、从上到下滑动。 当卷积窗口滑动到新一个位置时包含在该窗口中的部分张量与卷积核张量进行按元素相乘得到的张量再求和得到一个单一的标量值由此我们得出了这一位置的输出张量值。 在如上例子中输出张量的四个元素由二维互相关运算得到这个输出高度为2、宽度为2如下所示
0×01×13×24×319,1×02×14×25×325,3×04×16×27×337,4×05×17×28×343.
注意输出大小略小于输入大小。这是因为卷积核的宽度和高度大于1 而卷积核只与图像中每个大小完全适合的位置进行互相关运算。 所以输出大小等于输入大小 减去卷积核大小 即 这是因为我们需要足够的空间在图像上“移动”卷积核。稍后我们将看到如何通过在图像边界周围填充零来保证有足够的空间移动卷积核从而保持输出大小不变。 接下来我们在corr2d函数中实现如上过程该函数接受输入张量X和卷积核张量K并返回输出张量Y。
二维卷积层
输入 核 偏差 输出 c 和 是可学习的参数
import torch
from torch import nn
from d2l import torch as d2l
def corr2d(X, K): #save计算二维互相关运算h, w K.shape #获取卷积核的长宽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
通过 上图 的输入张量X和卷积核张量K我们来[验证上述二维互相关运算的输出]。
X torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K torch.tensor([[0.0, 1.0], [2.0, 3.0]])
corr2d(X, K)
输出结果
tensor([[19., 25.], [37., 43.]])
卷积层
卷积层对输入和卷积核权重进行互相关运算并在添加标量偏置之后产生输出。 所以卷积层中的两个被训练的参数是卷积核权重和标量偏置。 就像我们之前随机初始化全连接层一样在训练基于卷积层的模型时我们也随机初始化卷积核权重。
基于上面定义的corr2d函数[实现二维卷积层]。在__init__构造函数中将weight和bias声明为两个模型参数。前向传播函数调用corr2d函数并添加偏置。
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))def forward(self, x):return corr2d(x, self.weight) self.bias
高度和宽度分别为 和 的卷积核可以被称为 卷积或 卷积核。 我们也将带有 卷积核的卷积层称为 卷积层。
图像中目标的边缘检测
如下是[卷积层的一个简单应用]通过找到像素变化的位置来(检测图像中不同颜色的边缘)。 首先我们构造一个 6 × 8像素的黑白图像。中间四列为黑色0其余像素为白色1。
X torch.ones((6, 8))
X[:, 2:6] 0
X
输出结果 tensor([[1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.], [1., 1., 0., 0., 0., 0., 1., 1.]])
接下来我们构造一个高度为1、宽度为2的卷积核K。当进行互相关运算时如果水平相邻的两元素相同则输出为零否则输出为非零。
K torch.tensor([[1.0, -1.0]])
现在我们对参数X输入和K卷积核执行互相关运算。 如下所示[输出Y中的1代表从白色到黑色的边缘-1代表从黑色到白色的边缘]其他情况的输出为0。
Y corr2d(X, K)
Y
输出结果 tensor([[ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.], [ 0., 1., 0., 0., 0., -1., 0.]])
现在我们将输入的二维图像转置再进行如上的互相关运算。 其输出如下之前检测到的垂直边缘消失了。 不出所料这个[卷积核K只可以检测垂直边缘]无法检测水平边缘。
corr2d(X.t(), K)
输出结果
tensor([[0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.]])
补充 学习卷积核
如果我们只需寻找黑白边缘那么以上[1, -1]的边缘检测器足以。然而当有了更复杂数值的卷积核或者连续的卷积层时我们不可能手动设计滤波器。那么我们是否可以[学习由X生成Y的卷积核]呢
现在让我们看看是否可以通过仅查看“输入-输出”对来学习由X生成Y的卷积核。 我们先构造一个卷积层并将其卷积核初始化为随机张量。接下来在每次迭代中我们比较Y与卷积层输出的平方误差然后计算梯度来更新卷积核。为了简单起见我们在此使用内置的二维卷积层并忽略偏置。
# 构造一个二维卷积层它具有1个输出通道和形状为12的卷积核
conv2d nn.Conv2d(1,1, kernel_size(1, 2), biasFalse)# 这个二维卷积层使用四维输入和输出格式批量大小、通道、高度、宽度
# 其中批量大小和通道数都为1
X X.reshape((1, 1, 6, 8))
Y Y.reshape((1, 1, 6, 7))
lr 3e-2 # 学习率for i in range(10):Y_hat conv2d(X)l (Y_hat - Y) ** 2conv2d.zero_grad()l.sum().backward()# 迭代卷积核conv2d.weight.data[:] - lr * conv2d.weight.gradif (i 1) % 2 0:print(fepoch {i1}, loss {l.sum():.3f})
输出结果 epoch 2, loss 4.114 epoch 4, loss 0.798 epoch 6, loss 0.178 epoch 8, loss 0.048 epoch 10, loss 0.016
在10 次迭代之后误差已经降到足够低。现在我们来看看我们[所学的卷积核的权重张量]。
conv2d.weight.data.reshape((1, 2))
输出结果 tensor([[ 1.0016, -0.9785]])
细心的读者一定会发现我们学习到的卷积核权重非常接近我们之前定义的卷积核K。
互相关和卷积
回想一下我们在 6.1节 中观察到的互相关和卷积运算之间的对应关系。 为了得到正式的卷积运算输出我们需要执行 6.1.6中定义的严格卷积运算而不是互相关运算。 幸运的是它们差别不大我们只需水平和垂直翻转二维卷积核张量然后对输入张量执行互相关运算。
值得注意的是由于卷积核是从数据中学习到的因此无论这些层执行严格的卷积运算还是互相关运算卷积层的输出都不会受到影响。 为了说明这一点假设卷积层执行互相关运算并学习 上图 中的卷积核该卷积核在这里由矩阵 表示。 假设其他条件不变当这个层执行严格的卷积时学习的卷积核 在水平和垂直翻转之后将与 相同。 也就是说当卷积层对 上图 中的输入和 执行严格卷积运算时将得到与互相关运算 上图中相同的输出。
为了与深度学习文献中的标准术语保持一致我们将继续把“互相关运算”称为卷积运算尽管严格地说它们略有不同。 此外对于卷积核张量上的权重我们称其为元素。
补充
二维互相关 二维卷积 由于对称性在实际使用中没有区别
一维和三维互相关
一维文本、语言、时序序列音频 三维视频、医学图像、气象地图 特征映射和感受野
如在 6.1.4.1节 中所述 上图 中输出的卷积层有时被称为特征映射feature map因为它可以被视为一个输入映射到下一层的空间维度的转换器。 在卷积神经网络中对于某一层的任意元素 其感受野receptive field是指在前向传播期间可能影响 计算的所有元素来自所有先前层。
请注意感受野可能大于输入的实际大小。让我们用 上图 为例来解释感受野 给定 2×2 卷积核阴影输出元素值19的感受野是输入阴影部分的四个元素。 假设之前输出为 其大小为 2×2现在我们在其后附加一个卷积层该卷积层以 为输入输出单个元素 。 在这种情况下 上的 的感受野包括 的所有四个元素而输入的感受野包括最初所有九个输入元素。 因此当一个特征图中的任意元素需要检测更广区域的输入特征时我们可以构建一个更深的网络。
小结
二维卷积层的核心计算是二维互相关运算。最简单的形式是对二维输入数据和卷积核执行互相关操作然后添加一个偏置。我们可以设计一个卷积核来检测图像的边缘。我们可以从数据中学习卷积核的参数。学习卷积核时无论用严格卷积运算或互相关运算卷积层的输出不会受太大影响。当需要检测输入特征中更广区域时我们可以构建一个更深的卷积网络。
练习
1. 构建一个具有对角线边缘的图像X。
1如果将本节中举例的卷积核K应用于X会发生什么情况
2如果转置X会发生什么
3如果转置K会发生什么
解 代码如下
X torch.ones((5, 5))
for i in range(X.shape[0]):for j in range(X.shape[1]):if i j:X[i,j] 0
X
输出结果 tensor([[0., 1., 1., 1., 1.], [1., 0., 1., 1., 1.], [1., 1., 0., 1., 1.], [1., 1., 1., 0., 1.], [1., 1., 1., 1., 0.]])
K torch.tensor([[1.0, -1.0]])
corr2d(X, K)
# 输出形状为54检测对角线边缘对角线上为-1下为1
输出结果 tensor([[-1., 0., 0., 0.], [ 1., -1., 0., 0.], [ 0., 1., -1., 0.], [ 0., 0., 1., -1.], [ 0., 0., 0., 1.]])
corr2d(X.t(), K)
# X转置后结果不变
输出结果 tensor([[-1., 0., 0., 0.], [ 1., -1., 0., 0.], [ 0., 1., -1., 0.], [ 0., 0., 1., -1.], [ 0., 0., 0., 1.]])
corr2d(X, K.t())
# 输出形状变成45检测对角线边缘对角线上为1下为-1
输出结果 tensor([[-1., 1., 0., 0., 0.], [ 0., -1., 1., 0., 0.], [ 0., 0., -1., 1., 0.], [ 0., 0., 0., -1., 1.]])
2. 在我们创建的Conv2D自动求导时有什么错误消息
解 报错维度不匹配。因为输入和输出格式是四维的包括批量大小、通道、高和宽但自定义的Conv2D仅包含二维信息即高和宽。 将输入和输出的批量大小和通道去掉或者创建卷积层时增加批量大小和通道均可解决该问题。
conv2d Conv2D((1,2))
Y_hat conv2d(X)
l (Y_hat - Y) ** 2
conv2d.zero_grad()
l.sum().backward()
conv2d.weight.data[:] - lr * conv2d.weight.grad
输出结果
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Cell In[24], line 3 1 conv2d Conv2D((1,2)) 2 Y_hat conv2d(X) ---- 3 l (Y_hat - Y) ** 2 4 conv2d.zero_grad() 5 l.sum().backward() RuntimeError: The size of tensor a (4) must match the size of tensor b (7) at non-singleton dimension 3
3. 如何通过改变输入张量和卷积核张量将互相关运算表示为矩阵乘法
解 核心思想是将输入张量中每个与卷积核做互相关运算的元素展成一行
比如将本节举例的X转变为 [0134124534674578]
再与reshape成列向量的卷积核K做矩阵乘法 [0134124534674578][0123][19253743]
再将结果reshape成输出Y的尺寸即可。
def corr2d_matmul(X, K): h, w K.shape# 将输入X中每次与卷积核做互相关运算的元素展平成一行# X_reshaped的每一行元素均为与卷积核做互相关的元素X_reshaped torch.zeros((X.shape[0] - h 1)*(X.shape[1] - w 1), h*w)k 0for i in range(X.shape[0] - h 1):for j in range(X.shape[1] - w 1):X_reshaped[k,:] X[i:i h, j:j w].reshape(1,-1)k 1# 将卷积核K转为列向量并与X_reshaped做矩阵乘法再reshape成输出尺寸即可Y X_reshapedK.view(-1)return Y.reshape(X.shape[0] - h 1, X.shape[1] - w 1)
X torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])
K torch.tensor([[0.0, 1.0], [2.0, 3.0]])
Y corr2d_matmul(X, K)
Y
输出结果 tensor([[19., 25.], [37., 43.]])
4.手工设计一些卷积核。
1二阶导数的核的形式是什么
2积分的核的形式是什么
3得到 次导数的最小核的大小是多少
解
1
对于一阶导数:
对应的一阶导数卷积核为
扩展至二维对应的一阶导数水平卷积核为 或者
对应的一阶导数垂直卷积核为 或者
进一步地对于二阶导数:
对应的二阶导数卷积核为
扩展至二维
对应的二阶导数水平卷积核为 或者
二阶导数垂直卷积核为 或者
二阶导数叠加卷积核为
2
一维积分核--平均滤波器: 其中 是 中的元素数量。二维积分核: 积分核可以是平均滤波器也称为均值滤波器其形式如下 二维平均滤波器 (也称为盒式滤波器或均质滤波器): 其中 和 分别是 的高度和宽度。
高斯积分核: 在空间域具有高斯形状用于实现平滑效果如下 其中 是高斯分布的标准差 是滤波器中每个元素的坐标。
双边滤波器核:结合了空间域的高斯权重和强度域的高斯权重用于在保持边缘的同时实现平滑如下
其中 是归一化因子确保核的总权重为 1 是空间域的标准差 是强度域的标准差 (,) 是图像在点 的强度 是中心像素的强度。
3结合第一小问的解答
对于一阶导数最小核的大小是3一个3点中心差分近似。对于二阶导数在一维情况下最小核的大小是3一个3点中心差分近似。在二维情况下一个简单的近似可能是一个3×3的核。对于更高阶的导数核的大小至少应与导数的阶数d相匹配但这通常不足以提供良好的近似。实际使用的核会更大以确保足够的平滑性和减少误差。