学习了李沐——《动手学深度学习》的视频课程,在此对知识点进行整理以及记录动手实践中遇到的一些问题和想法。

首先,我们导入可能用到的包

import torch
from torch import nn

一.卷积层

关于卷积层的概念,笔者在此不再过多叙述,总之,卷积层的作用是提取输入图片中的信息,这些信息被称为图像特征,这些特征是由图像中的每个像素通过组合或者独立的方式所体现,比如图片的纹理特征,颜色特征。

1.卷积层运算

在神经网络中进行卷积操作可以看作是互相关运算,具体指的是输入张量与核张量之间进行互相关操作产生输出张量。在书中提到的卷积操作的理论描述中,可以总结为卷积核窗口按照设定好的步幅,对输入张量进行按元素做乘法后求和的操作。

上图中的操作,可以由下面的数学运算表示:

由于卷积核的宽度和高度都大于1,所以经过卷积操作的输出张量应该是小于(或者等于)输入张量的大小。我们分别将输出张量的高和宽由输入大小X,卷积核的高和宽记为X记为下式表示:

卷积运算的原理可有以下代码实现:

def corr2d(X, K):  """计算二维互相关运算"""h, w = K.shapeY = 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 = 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.]])

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))def forward(self, x):return corr2d(x, self.weight) + self.bias

上述代码中,笔者遇到的问题是nn.Paramater()这个方法。该方法是将一个固定的张量转变成一个可以训练的paramater,并且将这个参数绑定到模型中。笔者试过不用这个方法,直接用torch.full()和torch.zeros()初始化两个参数,最后并不能用state_dict()这个方法得到预设的参数。

3.图像中目标的边缘检测

书中讲述了一个检测黑白色垂直边缘的方法。在一张通道数为1的图片中,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变为0以及由0变为1的边界,并分别记为1和-1。

接下来,我们要构造一个1X2的卷积核,并通过这个卷积核检测出黑白边缘。至于这个卷积核为什么这样来创建,沐导说的是,这个核是通过学习所获得的。

K = torch.tensor([[1.0, -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.]])

4.学习卷积核

接下来,我们来实现如何学的上述边缘检测中的卷积核。这个过程的主要思想和神经网络的学习类似,在网络中进行训练,得到输出,之后计算模型输出与原数据的损失,再经过梯度下降更新参数,经过若干轮次的迭代,我们便可以求得参数weight(这里我们将偏置忽略掉)。

# 构造一个二维卷积层,它具有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  # 学习率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(f'epoch {i+1}, loss {l.sum():.3f}')
epoch 2, loss 6.567
epoch 4, loss 2.060
epoch 6, loss 0.738
epoch 8, loss 0.285
epoch 10, loss 0.114

在经过10次的迭代之后,误差便降到足够低,现在我们来看一看我们所学习到的权重张量。

conv2d.weight.data.reshape((1, 2))
tensor([[ 0.9571, -1.0261]])

5.突发奇想

上文中提到,现有的卷积核只能检测垂直边缘,笔者想将检测垂直边缘的卷积核学习出来。在这里,我们创建一个8X8的张量,将前两行和最后两行标记为白色1,其他位置置0。卷积核的大小设计为2X2。我们最后得到的输出应给是一个7X7的张量。

X = torch.ones((8,8))
X[2:6, :] = 0
Y = torch.zeros(7, 7)
Y[1, :] = 1
Y[-2, :] = -1
print(X)
print(Y)
tensor([[1., 1., 1., 1., 1., 1., 1., 1.],[1., 1., 1., 1., 1., 1., 1., 1.],[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., 1., 1., 1., 1., 1., 1.],[1., 1., 1., 1., 1., 1., 1., 1.]])
tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.],[ 1.,  1.,  1.,  1.,  1.,  1.,  1.],[ 0.,  0.,  0.,  0.,  0.,  0.,  0.],[ 0.,  0.,  0.,  0.,  0.,  0.,  0.],[ 0.,  0.,  0.,  0.,  0.,  0.,  0.],[-1., -1., -1., -1., -1., -1., -1.],[ 0.,  0.,  0.,  0.,  0.,  0.,  0.]])

具体训练过程如下所示:

c_net = nn.Conv2d(1, 1, kernel_size=2, bias=False)
X = X.reshape((1, 1, 8, 8))
Y = Y.reshape((1, 1, 7, 7))lr = 0.01
for i in range(10):Y_hat = c_net(X)l = (Y_hat - Y) ** 2c_net.zero_grad()l.sum().backward()c_net.weight.data[:] -= lr * c_net.weight.gradif (i + 1) % 2 == 0:print(f'epoch {i+1}, loss {l.sum():.3f}')print(c_net.weight.data)
epoch 2, loss 3.257
epoch 4, loss 0.770
epoch 6, loss 0.204
epoch 8, loss 0.055
epoch 10, loss 0.015
tensor([[[[ 0.8568,  0.1198],[-0.2884, -0.6882]]]])

可以看到,在经过十轮的训练之后,loss已经非常低,而且我们成功学习到了卷积核中的参数weight。我们用这个卷积核中的数据,放到本文最开始我们创建的卷积层中去进行验证。

K = c_net.weight.data.reshape(2,2)
y_hat = corr2d((X.reshape(8, 8), K)
print(y_hat.data)
tensor([[-4.1306e-05, -4.1306e-05, -4.1306e-05, -4.1306e-05, -4.1306e-05,-4.1306e-05, -4.1306e-05],[ 9.7663e-01,  9.7663e-01,  9.7663e-01,  9.7663e-01,  9.7663e-01,9.7663e-01,  9.7663e-01],[ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,0.0000e+00,  0.0000e+00],[ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,0.0000e+00,  0.0000e+00],[ 0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,0.0000e+00,  0.0000e+00],[-9.7667e-01, -9.7667e-01, -9.7667e-01, -9.7667e-01, -9.7667e-01,-9.7667e-01, -9.7667e-01],[-4.1306e-05, -4.1306e-05, -4.1306e-05, -4.1306e-05, -4.1306e-05,-4.1306e-05, -4.1306e-05]])

可以看到,虽然我们没有真正得到一个只有1、0、-1三个数据组成的张量,但第一行和最后一行的数据太小,我们可以近似看成0,第二行和倒数第二行也可以近似看成1和-1。由此,我们成功学习到了我们所要求的卷积核。

6.填充

在使用多层卷积时,我们经常丢失边缘像素。由于我们通常使用小卷积核,因此对于任何单个卷积,我们可能只会丢失几个像素。 但随着我们应用许多连续卷积层,累积丢失的像素数就多了。 解决这个问题的简单方法即为填充(padding):在输入图像的边界填充元素(通常填充元素是0)。

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

在许多情况下,我们需要设置,这样,我们就能让输入张量和输出张量具有相同的高度和宽度,以便我们可以更好的去预测每个图层的输出形状。假设是奇数,我们将在高度的两侧填充行。 如果是偶数,则一种可能性是在输入顶部填充⌈

神经网络卷积层与池化层相关推荐

  1. 深度学习之卷积神经网络(7)池化层

    深度学习之卷积神经网络(7)池化层 在卷积层中,可以通过调节步长参数s实现特征图的高宽成倍缩小,从而降低了网络的参数量.实际上,处理通过设置步长,还有一种专门的网络层可以实现尺寸缩减功能,它就是这里要 ...

  2. 转:卷积神经网络_(1)卷积层和池化层学习

    博主总结的很好,学习中.转载:http://www.cnblogs.com/zf-blog/p/6075286.htm 卷积神经网络_(1)卷积层和池化层学习 卷积神经网络(CNN)由输入层.卷积层. ...

  3. 深入学习卷积神经网络中卷积层和池化层的意义(转)

    为什么要使用卷积呢? 在传统的神经网络中,比如多层感知机(MLP),其输入通常是一个特征向量:需要人工设计特征,然后将这些特征计算的值组成特征向量,在过去几十年的经验来看,人工找到的特征并不是怎么好用 ...

  4. 【卷积神经网络】卷积层,池化层,全连接层

    转于:<入门PyTorch> 卷积层是卷积神经网络的核心, 大多数计算都是在卷积层中进行的. 1 卷积层 1.1 概述 首先介绍卷积神经网络的参数. 这些参数是由一些可学习的滤波器集合构成 ...

  5. 卷积神经网络中卷积层、池化层、全连接层的作用

    1. 卷积层的作用 卷积层的作用是提取输入图片中的信息,这些信息被称为图像特征,这些特征是由图像中的每个像素通过组合或者独立的方式所体现,比如图片的纹理特征,颜色特征. 比如下面这张图片,蓝色框框住的 ...

  6. 深入学习卷积神经网络中卷积层和池化层的意义

    为什么要使用卷积呢? 在传统的神经网络中,比如多层感知机(MLP),其输入通常是一个特征向量:需要人工设计特征,然后将这些特征计算的值组成特征向量,在过去几十年的经验来看,人工找到的特征并不是怎么好用 ...

  7. 理解CNN卷积层与池化层计算

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 概述 深度学习中CNN网络是核心,对CNN网络来说卷积层与池化层的 ...

  8. (pytorch-深度学习系列)pytorch卷积层与池化层输出的尺寸的计算公式详解

    pytorch卷积层与池化层输出的尺寸的计算公式详解 要设计卷积神经网络的结构,必须匹配层与层之间的输入与输出的尺寸,这就需要较好的计算输出尺寸 先列出公式: 卷积后,池化后尺寸计算公式: (图像尺寸 ...

  9. 深度学习入门 (九):卷积层和池化层的实现

    目录 卷积神经网络 CNN 整体结构 卷积层 全连接层存在的问题 卷积运算 乘积累加运算 偏置 填充 (padding) 步幅 (stride) 小结:卷积层的输出特征图的大小 3 维数据的卷积运算 ...

  10. pytorch 入门:GPU加速,卷积层,池化层

    GPU 加速 深度学习设计很多向量和多矩阵运算,比如BP , CNN 等深层模型都可以写成矩阵运算的格式,不用写成循环运算.但是CPU 上矩阵的运算会被展成循环的形式,CPU 是串行执行的.而GPU ...

最新文章

  1. 7.0、Android Studio命令行工具
  2. dba mysql命令_Mysql常用DBA命令
  3. uva1471 二叉搜索树
  4. 技术分享-bounds的深入认识
  5. VS2015 + CUDA 8.0 配置GTX1070的OpenCL 开发环境
  6. 为什么现在老师这么难,值得大家深思
  7. eclipse中添加插件的方法
  8. 使用Weka进行数据挖掘
  9. js函数提示 vscode_VSCode + JSDoc 完美实现(almost)JavaScript代码提示
  10. SqlMapConfig.xml 的配置
  11. 生活随笔与读书笔记20140302
  12. sja1000 CAN驱动学习、调试记录(基于PeliCan Mode)
  13. DataView 构造
  14. c语言多文件编译 实例霓虹灯,单片机51c语言编程20种不同霓虹灯亮法
  15. 300万+企业财税服务平台微企宝,将于8月8日全球首发QB生态通证
  16. 排障集锦:九九八十一难之第十三难!-------------史上最全MySQL 单实例故障排查
  17. Oh My Zsh和Oh My Posh
  18. 使用bat命令【创建】【修改】【删除】文件
  19. Chrome浏览器时代就要拉开大幕
  20. 人群密度向:CMTL

热门文章

  1. linux,windows,mac最强Android模拟器
  2. 3D引擎渲染管理系统概览
  3. Ubuntu中shell命令-(1)-shell是什么?-Linux内核有哪些东西?-shell命令解释器包含哪几个种类?
  4. reshape功能介绍_Pandas中的数据重塑(reshape)功能
  5. CSS篇之波浪形文字
  6. 计算机办公软件应用中级,计算机办公软件应用中级证
  7. kubernetes理论概念详情(K8S)
  8. 亚马逊全球开店运营不能触碰的红线
  9. 科研人必备,Zotero神器安装使用全过程!
  10. windows下使用vnc viewer远程连接redhat Linux桌面