NNDL 作业六 卷积基础知识

一、概念

1.卷积

卷积是指在滑动中提取特征的过程,我们先从一个小小的权重矩阵开始,让它逐步在二维输入数据上“扫描”。这个权重矩阵“滑动”的同时,计算权重矩阵和扫描所得的数据矩阵的乘积,然后把结果相加,卷积的过程可以参考下图:
在这里插入图片描述

注意
真正的卷积是将卷积核翻转180°再对位相乘相加,我们平常说的卷积其实是互相关。
但由于卷积核是否进行翻转与其特征抽取能力无关,卷积核是通过学习得到的,卷积和互相关再能力上等价,因此我们常用“卷积”来代替互相关。

2.卷积核

简单来说,卷积核就是一个二维矩阵,不同的卷积核对应不同的特征。卷积核定义了卷积的大小范围,在网络中代表感受野的大小,二维卷积核最常见的就是 3*3 的卷积核。一般情况下,卷积核越大,感受野越大,看到的图片信息越多,所获得的全局特征越好。但大的卷积核会导致计算量的暴增,计算性能也会降低。

【卷积核的大小一般为奇数*奇数】 1 ∗ 1 1*1 11 3 ∗ 3 3*3 33 5 ∗ 5 5*5 55 7 ∗ 7 7*7 77都是最常见的。这是为什么呢?为什么没有偶数*偶数?

(1)更容易padding
在卷积时,我们有时候需要卷积前后的尺寸不变。这时候我们就需要用到padding。假设图像的大小,也就是被卷积对象的大小为 n ∗ n n*n nn,卷积核大小为 k ∗ k k*k kk,padding的幅度设为 ( k − 1 ) / 2 (k-1)/2 (k1)/2时,卷积后的输出就为 ( n − k + 2 ∗ ( ( k − 1 ) / 2 ) ) / 1 + 1 = n (n-k+2*((k-1)/2))/1+1=n (nk+2((k1)/2))/1+1=n,即卷积输出为 n ∗ n n*n nn,保证了卷积前后尺寸不变。但是如果 k k k是偶数的话, ( k − 1 ) / 2 (k-1)/2 (k1)/2就不是整数了。

(2)更容易找到卷积锚点
在CNN中,进行卷积操作时一般会以卷积核模块的一个位置为基准进行滑动,这个基准通常就是卷积核模块的中心。若卷积核为奇数,卷积锚点很好找,自然就是卷积模块中心,但如果卷积核是偶数,这时候就没有办法确定了,让谁是锚点似乎都不怎么好。

卷积核到底是怎么提取特征的呢?用几个例子来感受一下:
(1)啥也不做
在这里插入图片描述
这个滤波器啥也没有做,得到的图像和原图是一样的。
因为只有中心点的值是1。邻域点的权值都是0,对滤波后的取值没有任何影响

(2)图像锐化
锐化滤波器实际上就是计算当前点和周围点的差别,然后将这个差别加到原来的位置上

在这里插入图片描述
如果核的中心值是负数,就是在强调边缘,在锐化边缘
注意,这里还属于锐化,不是边缘检测

(3)边缘检测

水平方向边缘
在这里插入图片描述

需要注意的是,这里矩阵的元素和是0,所以滤波后的图像会很暗,只有边缘的地方是有亮度的。

为什么这个滤波器可以寻找到水平边缘呢?
因为用这个滤波器卷积相当于求导的离散版本:你将当前的像素值减去前一个像素值,这样你就可以得到这个函数在这两个位置的差别或者斜率。

垂直方向边缘
在这里插入图片描述
45°边缘
在这里插入图片描述
所有方向边缘
在这里插入图片描述
(4)浮雕
浮雕滤波器可以给图像一种3D阴影的效果。
只要将中心一边的像素减去另一边的像素就可以了。这时候,像素值有可能是负数,我们将负数当成阴影,将正数当成光,然后我们对结果图像加上128的偏移。这时候,图像大部分就变成灰色了。

45度的浮雕滤波器

在这里插入图片描述
我们只要加大滤波器,就可以得到更加夸张的效果了

在这里插入图片描述

3.特征图

特征图是由一系列卷积核对输入图像进行卷积操作得到的结果。它可以看作是原始图像的抽象表示,其中每个像素点表示一些特定的特征。

卷积中的特征图大小计算方式:
w o u t = w i n + 2 × p a d d i n g − F s t r i d e + 1 w_{out}=\frac{w_{in}+2\times padding-F}{stride}+1 wout=stridewin+2×paddingF+1
其中, w o u t w_{out} wout为输出特征图的大小, w i n w_{in} win为输入特征图的大小, F F F为卷积核大小, s t r i d e stride stride为卷积步长。

图像特征主要有图像的颜色特征、纹理特征、形状特征等。
那到底这些特征图对应的图像是什么样的呢?接着往下看:
颜色特征
RGB图片有3个通道,可以说有3个颜色特征,分别为红色,绿色和蓝色。
在这里插入图片描述
纹理特征
在这里插入图片描述

形状特征
在这里插入图片描述
随着神经网络深度的不断加深,卷积提取到的特征逐渐清晰起来。由浅层次的纹理特征,逐步到深层次的形状特征.

4.特征选择

在卷积神经网络(CNN)中,特征选择是指通过卷积操作从输入数据中提取出具有代表性重要性的特征。在卷积层中,卷积核通过滑动窗口的方式与输入数据进行卷积操作,得到一系列的特征图。

特征选择的目的是通过卷积核的学习,选择出对于分类或回归任务有意义的特征。通过学习,卷积核可以自动地从输入数据中提取出与任务相关的特征,例如边缘、纹理、形状等。

在卷积过程中,每个卷积核都会学习不同的特征,因此可以通过增加卷积核的数量来增加网络的表达能力。特征选择也可以通过调整卷积核的大小、步长、填充等参数来控制特征提取的精细程度。

特征选择是卷积神经网络的核心部分,它能够帮助网络自动地从原始数据中学习到有用的特征,提高网络的性能和泛化能力。

5.步长

卷积的步长(stride)是指卷积核在进行滑动窗口操作时每次移动的距离。步长的大小会影响卷积操作的输出尺寸和特征提取的精度。

如下图:

在这里插入图片描述在这里插入图片描述

根据具体的任务和数据特点来选择合适的步长。一般来说,如果目标是提取更精细的特征,可以选择较小的步长;如果目标是减少计算量和模型复杂度,可以选择较大的步长。同时,步长也可以和其他参数(如填充、卷积核大小)一起调整,以获得更好的性能。

6.填充

填充是指再输入矩阵周围填充一圈数值(一般是0),如图。
在这里插入图片描述

如果不填充会怎么样呢?
(1) 输入图片通过层层 filter 不断缩小,最后只有一点点。
(2) 输入图片的边缘信息可能会丢失。

7.感受野

感受野指的是输出图像中的一个像素与对应的输入图像中的像素。
换句话说,它表示一个输出像素“看到”的输入图像中区域的大小,注意是从输出来看的。如果你将卷积操作比作窗户,那么感受野就是一个输出像素透过这个窗户可以看到的输入图片的范围。

一定要注意:感受野指的是输入图像中的区域

在这里插入图片描述
上图中,第一个输出左上角的像素点12.0,透过3x3的矩阵看到的是输入图像左上角的3x3的像素矩阵;最后一个输出14.0,透过3x3的矩阵看到的是输入图像右下角的3x3的像素矩阵,这个3x3的像素矩阵就是这个卷积的感受野。

感受野的作用
可以说,感受野影响了神经网络对于图像的理解和图像特征的提取。
一个大的感受野使得神经网络可以看到输入图像上更大的像素范围,从而更好地理解图像的全局信息,从而提取全局特征,如物体的形状和轮廓。
而较小的感受野只能捕捉到图像的局部特征,如边缘或纹理。
因此,在很多神经网络中,往往会出现不同大小的卷积核,就是为了提取不同尺度范围内的特征,让神经网络既可以学到图像的细节、又可以看到图像的轮廓。

二、探究不同卷积核的作用

在这里插入图片描述
卷积神经网络工作原理的直观理解_superdont的博客-CSDN博客

1.图1分别使用卷积核 ( − 1 , 1 ) \left( -1,1 \right) (1,1) (   1 − 1 ) \left( \begin{array}{l} \ 1\\ -1\\ \end{array} \right) ( 11) 输出特征图

卷积结果

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

代码

import torch
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

def Conv2d(X, K):  # X是输入,K是核矩阵
    '''计算二维互相关运算'''
    h, w = K.shape  # 核的行数和列数

    # 输出的行数=输入的行数-核的行数+1,列数同理
    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

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
#读入图像
im = Image.open('图1.png').convert('L')  # 读入一张灰度图的图片
X = np.array(im, dtype='float32')  # 将其转换为一个矩阵
X=torch.from_numpy(X)
#显示原图
plt.subplot(1,3,1).set_title('原图')
plt.imshow(X, cmap='gray')  # 可视化图片
#卷积
K1 = torch.tensor([[1.0, -1.0]])
Y1=Conv2d(X,K1)
print(Y1)
plt.subplot(1,3,2).set_title('使用[1,-1]卷积')
plt.imshow(Y1, cmap='gray')  # 可视化图片
#卷积
K2=torch.tensor([[1.0],[-1.0]])
Y2=Conv2d(X,K2)
print(Y2)
plt.subplot(1,3,3).set_title('使用[1,-1]的转置卷积')
plt.imshow(Y2, cmap='gray')  # 可视化图片
plt.show()

2.图2分别使用卷积核 ( − 1 , 1 ) \left( -1,1 \right) (1,1) (   1 − 1 ) \left( \begin{array}{l} \ 1\\ -1\\ \end{array} \right) ( 11) 输出特征图

卷积结果
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

3.图3分别使用卷积核 ( − 1 , 1 ) \left( -1,1 \right) (1,1) (   1 − 1 ) \left( \begin{array}{l} \ 1\\ -1\\ \end{array} \right) ( 11) ( 1 − 1 − 1 1 ) \left( \begin{matrix} 1& -1\\ -1& 1\\ \end{matrix} \right) (1111) 输出特征图

卷积结果
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

代码

import torch
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

def Conv2d(X, K):  # X是输入,K是核矩阵
    '''计算二维互相关运算'''
    # 从K的shape中拿出h(height)--行数和w(wide)--列数
    h, w = K.shape  # 核的行数和列数

    # 输出的行数=输入的行数-核的行数+1,列数同理
    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


plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
'''
#读入图像
im = Image.open('图3.png').convert('L')  # 读入一张灰度图的图片
X = np.array(im, dtype='float32')  # 将其转换为一个矩阵
X=torch.from_numpy(X)
'''
X=torch.zeros((9,9))
for i in range(9):
    for j in range(9):
        if (i==j or i+j==8) and (i!=0 and j!=0):
            X[i,j]=255
#显示原图
plt.subplot(1,4,1).set_title('原图')
plt.imshow(X, cmap='gray')  # 可视化图片
#卷积
K1 = torch.tensor([[1.0, -1.0]])
Y1=Conv2d(X,K1)
print(Y1)
plt.subplot(1,4,2).set_title('使用[1,-1]卷积')
plt.imshow(Y1, cmap='gray')  # 可视化图片
#卷积
K2=torch.tensor([[1.0],[-1.0]])
Y2=Conv2d(X,K2)
print(Y2)
plt.subplot(1,4,3).set_title('使用[1,-1]的转置卷积')
plt.imshow(Y2, cmap='gray')  # 可视化图片
#卷积
K3=torch.tensor([[-1,1],[1,-1]])
Y3=Conv2d(X,K3)
print(Y3)
plt.subplot(1,4,4).set_title('使用[[-1,1],[1,-1]]卷积')
plt.imshow(Y3,cmap='gray')
plt.show()

4. 实现灰度图的边缘检测、锐化、模糊。

在这里插入图片描述

(1)边缘检测

在这里插入图片描述

部分代码

#基于第一个代码,修改卷积核就可以

#显示原图
print(X)
plt.title('原图')
plt.imshow(X, cmap='gray')  # 可视化图片
plt.show()
#左边缘检测
K1=torch.tensor([[1,0,-1],[2,0,-2],[1,0,-1]])
Y1=Conv2d(X,K1)
print(Y1)
plt.subplot(1,4,1).set_title('左边缘检测')
plt.imshow(Y1,cmap='gray')
#右边缘检测
K2=torch.tensor([[-1,0,1],[-2,0,2],[-1,0,1]])
Y2=Conv2d(X,K2)
print(Y2)
plt.subplot(1,4,2).set_title('右边缘检测')
plt.imshow(Y2,cmap='gray')
#上边缘检测
K3=torch.tensor([[1,2,1],[0,0,0],[-1,-2,-1]])
Y3=Conv2d(X,K3)
print(Y3)
plt.subplot(1,4,3).set_title('上边缘检测')
plt.imshow(Y3,cmap='gray')
#下边缘检测
K4=torch.tensor([[-1,-2,-1],[0,0,0],[1,2,1]])
Y4=Conv2d(X,K4)
print(Y4)
plt.subplot(1,4,4).set_title('下边缘检测')
plt.imshow(Y4,cmap='gray')
plt.show()

(2)锐化
在这里插入图片描述
部分代码

#锐化
plt.subplot(1,2,1).set_title('原图')
plt.imshow(X, cmap='gray')  # 可视化图片
#锐化
K5=torch.tensor([[0,-1,0],[-1,5,-1],[0,-1,0]])
Y5=Conv2d(X,K5)
plt.subplot(1,2,2).set_title('锐化')
plt.imshow(Y5,cmap='gray')
plt.show()

图像锐化后,为什么“蒙上了一层灰色”?

(3)模糊
在这里插入图片描述
部分代码

#模糊
K6=torch.tensor([[0.0625,0.0125,0.0625],[0.125,0.25,0.125],[0.0625,0.125,0.0625]])
Y6=Conv2d(X,K6)
plt.subplot(1,2,2).set_title('模糊')
plt.imshow(Y6,cmap='gray')
plt.show()

5.总结不同卷积核的特征和作用

卷积核特征作用
上边缘检测 \mathbf{上边缘检测} 上边缘检测 [ 1 2 1 0 0 0 − 1 − 2 − 1 ] \left[ \begin{matrix} 1& 2& 1\\ 0& 0& 0\\ -1& -2& -1\\ \end{matrix} \right] 101202101 一侧的权重为正,另一侧的权重为负具体来说,卷积核中的第一行表示在当前像素点的上方,对应的像素点的权重为1、2、1。而第三行表示在当前像素点的下方,对应的像素点的权重为-1、-2、-1。第二行没有权重,是为了使卷积核的中心点不影响检测的结果。
锐化 \mathbf{锐化} 锐化 [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] \left[ \begin{matrix} 0& -1& 0\\ -1& 5& -1\\ 0& -1& 0\\ \end{matrix} \right] 010151010 中心点权重较大强调边缘:锐化卷积核中的中心点权重比周围的点都要大,这样就可以突出图像中的边缘。中心点的权重越大,突出边缘的效果就越好。增强细节:锐化卷积核可以增强图像中的细节,使得图像更加清晰。锐化卷积核中的负权重可以减少周围像素的影响,而中心点的正权重则可以突出图像中的强度差异。
模糊 \mathbf{模糊} 模糊 [ 0.0625 0.125 0.0625 0.125 0.25 0.125 0.0625 0.125 0.0625 ] \left[ \begin{matrix} 0.0625& 0.125& 0.0625\\ 0.125& 0.25& 0.125\\ 0.0625& 0.125& 0.0625\\ \end{matrix} \right] 0.06250.1250.06250.1250.250.1250.06250.1250.0625 每个元素都几乎相等当我们应用模糊卷积核时,卷积核会将周围像素值的加权平均值赋值给中心像素。由于卷积核的权重分布比较均匀,它们能够有效地减少图像中像素值之间的变化率,从而 平滑图像减少噪声和细节
浮雕 \mathbf{浮雕} 浮雕 [ − 2 − 1 0 − 1 1 1 0 1 2 ] \left[ \begin{matrix} -2& -1& 0\\ -1& 1& 1\\ 0& 1& 2\\ \end{matrix} \right] 210111012 左上角和右下角权重代数和为零,中心为1;左上为负,右下为正具体来说,浮雕卷积核通过改变像素值之间的差异,使得较亮的像素变得更亮,较暗的像素变得更暗。这样,图像中的边缘和细节会受到强调,从而产生视觉上的立体效果。如果像素值之间的差异较大,则对应的区域会看起来凸出;如果像素值之间的差异较小,则对应的区域会看起来凹陷。
识别 \mathbf{识别} 识别 [ 0 0 0 0 1 0 0 0 0 ] \left[ \begin{matrix} 0& 0& 0\\ 0& 1& 0\\ 0& 0& 0\\ \end{matrix} \right] 000010000 正方形矩阵,中心像素值为1,其他像素值为0通常被用作卷积神经网络中的第一步,对输入图像进行初始处理,使得后续的卷积层可以捕捉到更高级的特征。此外,该卷积核也可用于对特征图进行降采样和上采样操作,从而实现图像分辨率的调整。

具体可进入:https://setosa.io/ev/image-kernels/

心得体会

通过这次试验我知道了图像是由像素点所构成的,而其最终的成像效果是由背后像素的颜色数值所决定的,如果针对图像要提取出我们想要的特征,那么我们就需要对其中的数值进行变化。那我们怎么改变这些数值呢?这就涉及到了“卷积核”,“卷积核”其实规定了周围像素点是如何对当前像素点产生影响的(如平滑卷积)以及找出像素值差异大的地方(如边缘检测)……。当不想考虑某个位置时,可以把这个位置的数值设为0,想重点考虑某个位置时,可以把这个位置的值设置得比较高。“卷积”通过对位相乘再相加(可以理解为加权求和)操作,用一个新的像素值来代替原来的像素值,然后让卷积核在这张图片上一步一步滑动,最终得到了一张新的图像。通过设置合适的卷积核,就可以得到我们想要的特征。

参考:
不同卷积核的效果
你真的理解“感受野”了吗?
常用图像卷积核类型小结
卷积与几种常见的卷积核

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值