【23-24 秋学期】NNDL 作业6 卷积

一、概念

1、卷积

在我看来,卷积就是利用一个给定的矩阵同目标矩阵中的每一个可以分解得到的和给定矩阵同大小的分解矩阵们相乘,并且每个相乘得到的值都在一个结果矩阵在对应的位置储存。当然这里只说了步长为1的情况,如果增加步长,那么分解矩阵时,就要按照步长走,而且这个分解不是严格的分解,下一个分解后的矩阵可能会用到上一个矩阵的一部分。

2、卷积核

卷积核就是我在1中所说的特定矩阵,根据卷积核的不同种类,卷积出来的结果也各有特色。

3、特征图

特征图就是,1中所说的那个结果矩阵。即目标矩阵同卷积核卷积之后的结果。

4、特征选择

我觉得,这个概念应该是对于不同卷积核有不同的特征选择效果的意思吧。例如说,我们可以使用相应的卷积核得到一些图中我们想要得到的信息,即特征提取。

5、步长

这个就很好理解了,步长就是卷积核与目标矩阵进行卷积时,分解时每一步走的有多远,这个在图里说才好解释,这个步长不止针对于每一列也会在每一行上生效,也可能会在列和行上有不同的步长定义。ppt中的滑动也很形象。

6、填充

填充就更容易理解了。填充就是在目标矩阵的周围,一般是用0来扩充它的列和行,来达到不丢失数据的目的吧。我觉得可能也有别的作用,但是暂时没想到。

7、感受野

感受野,就是针对我们在得到卷积结果时,对应的我们使用了目标矩阵的多大一部分,一般跟卷积核有关,我有一个公式:

感受野大小等于

所有卷积核行相加减去总卷积核个数减1乘

所有卷积核列相加减去总卷积核个数减1

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

1. 图1分别使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix}​,\begin{pmatrix} 1\\ -1\\ \end{pmatrix}输出特征图

2. 图2分别使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix}​,\begin{pmatrix} 1\\ -1\\ \end{pmatrix}输出特征图

3. 图3分别使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix}​,\begin{pmatrix} 1\\ -1\\ \end{pmatrix}​,\begin{pmatrix} 1 &-1 \\ -1&1 \end{pmatrix}​ ,输出特征图

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

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

就本次实验接触到的各种卷积核,我发现他们的都是各式各样的对称,就拿4题中这些,越简单的,对称的越简单,越复杂的,对称的越复杂。我甚至感觉自己挑一挑这些参数就可能可以让他更锐化或者更模糊,但是我没有实践。

不过这个确实模糊和锐化的效果差别不是很明显。

每个卷积核的名字基本上就是它的作用,所以我觉得没有必要展开说了,并且更深度的我也不能解释了。

这些卷积核大概都是计算出来的吧,通过数学方面的知识,越来越感觉到老师说的对于数学的学习很重要这句话的含金量了。

同时,卷积时二维是不能进行卷积的,所以我们需要拓展维度,然后按照顺序,一个维度一个维度的来。虽然在卷积时是四维,但是我们还是只用了二位相当于,因为有两个维度的值为1,对于卷积没啥意义。

1-3题代码如下:

import numpy as np
import torch
from torch import nn
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容

# 创建图像
p1 = [[0, 0, 0, 255, 255, 255],
      [0, 0, 0, 255, 255, 255],
      [0, 0, 0, 255, 255, 255]]
p2 = [[255, 255, 0, 0],
      [255, 255, 0, 0],
      [0, 0, 255, 255],
      [0, 0, 255, 255]]
p3 = [[0, 0, 0, 0, 0, 0, 0, 0, 0],
      [0, 255, 0, 0, 0, 0, 0, 255, 0],
      [0, 0, 255, 0, 0, 0, 255, 0, 0],
      [0, 0, 0, 255, 0, 255, 0, 0, 0],
      [0, 0, 0, 0, 255, 0, 0, 0, 0],
      [0, 0, 0, 255, 0, 255, 0, 0, 0],
      [0, 0, 255, 0, 0, 0, 255, 0, 0],
      [0, 255, 0, 0, 0, 0, 0, 255, 0],
      [0, 0, 0, 0, 0, 0, 0, 0, 0]]
im1 = np.array(p1)
im2 = np.array(p2)
im3 = np.array(p3)

# plt.figure(num='原图')
# plt.subplot(1, 3, 1)
# plt.imshow(im1.astype('uint8'), cmap='gray')
# plt.title('1')
# plt.subplot(1, 3, 2)
# plt.imshow(im2.astype('uint8'), cmap='gray')
# plt.title('2')
# plt.subplot(1, 3, 3)
# plt.imshow(im3.astype('uint8'), cmap='gray')
# plt.title('3')
# plt.show()

# 唯独提升外加变为张量 
im1 = torch.from_numpy(im1.reshape((1, 1, im1.shape[0], im1.shape[1]))).to(torch.float32)
im2 = torch.from_numpy(im2.reshape((1, 1, im2.shape[0], im2.shape[1]))).to(torch.float32)
im3 = torch.from_numpy(im3.reshape((1, 1, im3.shape[0], im3.shape[1]))).to(torch.float32)

# 建立模型
conv1 = nn.Conv2d(1, 1, (2, 1), bias=False)
conv2 = nn.Conv2d(1, 1, (1, 2), bias=False)
conv3 = nn.Conv2d(1, 1, (2, 1), bias=False)
conv4 = nn.Conv2d(1, 1, (1, 2), bias=False)
conv5 = nn.Conv2d(1, 1, (2, 1), bias=False)
conv6 = nn.Conv2d(1, 1, (1, 2), bias=False)
conv7 = nn.Conv2d(1, 1, 2, bias=False)

# 卷积核的定义
sk1 = np.array([[1, -1]], dtype=float)
sk2 = sk1
sk3 = np.array([[1, -1], [-1, 1]], dtype=float)
sk1 = torch.from_numpy(sk1.reshape(1, 1, sk1.shape[0], sk1.shape[1])).to(torch.float32)
sk2 = torch.from_numpy(sk2.reshape(1, 1, sk2.shape[1], sk2.shape[0])).to(torch.float32)
sk3 = torch.from_numpy(sk3.reshape(1, 1, sk3.shape[0], sk3.shape[1])).to(torch.float32)

# 卷积核导入模型
conv1.weight.data = sk1
conv2.weight.data = sk2
conv3.weight.data = sk1
conv4.weight.data = sk2
conv5.weight.data = sk1
conv6.weight.data = sk2
conv7.weight.data = sk3

# 进行模型计算
img1 = conv1(im1)
img2 = conv2(im1)
img3 = conv3(im2)
img4 = conv4(im2)
img5 = conv5(im3)
img6 = conv6(im3)
img7 = conv7(im3)

# 转化为numpy并且去掉维度为1的不需要的多于维度 便于显示图像
x1 = img1.data.squeeze().numpy()
x2 = img2.data.squeeze().numpy()
x3 = img3.data.squeeze().numpy()
x4 = img4.data.squeeze().numpy()
x5 = img5.data.squeeze().numpy()
x6 = img6.data.squeeze().numpy()
x7 = img7.data.squeeze().numpy()

im1 = im1.data.squeeze().numpy()
im2 = im2.data.squeeze().numpy()
im3 = im3.data.squeeze().numpy()

# 输出图片
plt.figure(num='卷积后')
plt.subplot(3, 4, 1)
plt.imshow(im1, cmap='gray')
plt.title('1')
plt.subplot(3, 4, 2)
plt.imshow(x1, cmap='gray')
plt.title('1-1')
plt.subplot(3, 4, 3)
plt.imshow(x2, cmap='gray')
plt.title('1-2')
plt.subplot(3, 4, 5)
plt.imshow(im2, cmap='gray')
plt.title('2')
plt.subplot(3, 4, 6)
plt.imshow(x3, cmap='gray')
plt.title('2-1')
plt.subplot(3, 4, 7)
plt.imshow(x4, cmap='gray')
plt.title('2-2')
plt.subplot(3, 4, 9)
plt.imshow(im3, cmap='gray')
plt.title('3')
plt.subplot(3, 4, 10)
plt.imshow(x5, cmap='gray')
plt.title('3-1')
plt.subplot(3, 4, 11)
plt.imshow(x6, cmap='gray')
plt.title('3-2')
plt.subplot(3, 4, 12)
plt.imshow(x7, cmap='gray')
plt.title('3-3')
plt.show()

ps:打错字了,某一行的注释中’唯独‘是‘维度’

4题代码如下:

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

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = 'mlh.png'
im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
im = np.array(im, dtype='float32')  # 将其转换为一个矩阵

im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(1, 1, 3, bias=False)  # 定义卷积
conv2 = nn.Conv2d(1, 1, 3, bias=False)  # 定义卷积
conv3 = nn.Conv2d(1, 1, 3, bias=False)  # 定义卷积

sobel_kernel = np.array([[-1, -1, -1],
                         [-1, 8, -1],
                         [-1, -1, -1]], dtype='float32')  # 定义轮廓检测算子

sharpening_kernel = np.array([[0, -1, 0],
                              [-1, 5, -1],
                              [0, -1, 0]], dtype='float32')  # 定义锐化算子
blurred_kernel = np.array([[1 / 16, 1 / 8, 1 / 16],
                           [1 / 8, 1 / 4, 1 / 8],
                           [1 / 16, 1 / 8, 1 / 16]], dtype='float32')  # 定义模糊算子

sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
sharpening_kernel = sharpening_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
blurred_kernel = blurred_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出

conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值
conv2.weight.data = torch.from_numpy(sharpening_kernel)  # 给卷积的 kernel 赋值
conv3.weight.data = torch.from_numpy(blurred_kernel)  # 给卷积的 kernel 赋值

edge1 = conv1(Variable(im))  # 作用在图片上
edge2 = conv2(Variable(im))  # 作用在图片上
edge3 = conv3(Variable(im))  # 作用在图片上

x1 = edge1.data.squeeze().numpy()
x2 = edge2.data.squeeze().numpy()
x3 = edge3.data.squeeze().numpy()
im = im.data.squeeze().numpy()
plt.figure()
plt.subplot(2, 2, 1)
plt.imshow(im, cmap='gray')
plt.title("原图")
plt.subplot(2, 2, 2)
plt.imshow(x1, cmap='gray')
plt.title("边缘检测")
plt.subplot(2, 2, 3)
plt.imshow(x2, cmap='gray')
plt.title("锐化")
plt.subplot(2, 2, 4)
plt.imshow(x3, cmap='gray')
plt.title("模糊")
plt.show()

总结:

总结,本次实验又又又加深了我对pytorch以及python的理解,熟练了我对pycharm的使用,对于ctrl+d的使用,本次实验节省了我很多时间。

对于卷积能够提取特征的原理,在我看来,就是通过滤波器(卷积核)对图片进行线性的搜索,然后通过滤波器输出的特征图可以找到我们需要的图像的特征,从而达到提取特征的目的。但是对于卷积核为什么就是那个矩阵,我还没有想法,应该是和数学上相关吧。

函数参数:

plt.imshow()

plt.figure()

np.array.reshape()的含义

torch中squeeze()的具体含义、nn.Conv2D中每一个参数的含义和使用方法以及Tensor与np.array的互相转换。

等等以上的这些,虽然再次遇到可能还需要再次搜索各种参数是什么然后如何使用。

对于老师给出的一些网址,我也进入并体验了以下,但是那个预测数字的第一个就给我判断错了,我写的是6,输出是8,可惜并没有进行记录。

但是对于第二部分的1、2、3题,我感觉这个卷积出来的和我手算出来的结果差点意思,但是我也没有找到改进的方法,希望高人指点。

引用:

https://blog.csdn.net/qq_38975453/article/details/134176736?spm=1001.2014.3001.5502

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值