利用简单的全连接神经网络学习图像时,会损失掉图像像素之间的空间信息。而卷积神经网络可以很好地对图像进行深度学习,最主要的原因就是卷积层可以学习到图像的特征,最开始可能只是提取一些低级特征,随着网络的加深,一些高级特征也会被学习到。下面,我将设计一个实验,验证卷积层对图像特征的学习。
1.生成一个大小为(4,6),0,1,4,5列值全部为1;2,3列的值为0的矩阵,即生成了一个具有水平方向边缘的样本图像;
2.指定一个水平边缘检测的卷积核[-1,1]对样本图像进行边缘检测;
3.将第一步中生成的样本图像作为训练数据,第二步中边缘检测的结果作为标签,再指定一个大小跟第二步中卷积核形状一样的卷积核,开始训练卷积核。
4.将训练好的卷积核与第二步中指定的卷积核进行对比。
import torch
import torch.nn as nn
X=torch.ones((4,6))
X[:,2:4]=0
X=X.reshape((1,1,4,6))
kernel=torch.tensor([-1,1]).reshape((1,1,1,2)).float()
conv2d1=nn.Conv2d(1,1,kernel_size=(1,2),bias=False)#实例化一个卷积运算对象
conv2d1.weight.data=kernel#指定卷即核
Y=conv2d1(X)
print(f'X:{X}\n\nY:{Y}')
样本图像:
X:tensor([[[[1., 1., 0., 0., 1., 1.],
[1., 1., 0., 0., 1., 1.],
[1., 1., 0., 0., 1., 1.],
[1., 1., 0., 0., 1., 1.]]]])
边缘检测结果:
Y:tensor([[[[ 0., -1., 0., 1., 0.],
[ 0., -1., 0., 1., 0.],
[ 0., -1., 0., 1., 0.],
[ 0., -1., 0., 1., 0.]]]])
可以看到矩阵中边缘已经被指定的卷积核检测出来了。
将第一步中生成的样本图像作为训练数据,第二步中边缘检测的结果作为标签,再指定一个大小跟第二步中卷积核形状一样的卷积核,开始训练卷积核。
conv2d=nn.Conv2d(1,1,kernel_size=(1,2),bias=False)#卷积层
X=X.reshape((1,1,4,6))#特征值
Y=Y.reshape((1,1,4,5))#标签
lr=3e-2
for i in range(10):#迭代10次
Y_prediect=conv2d(X)
loss=(Y_prediect-Y)**2
conv2d.zero_grad()
loss.sum().backward(retain_graph=True)
conv2d.weight.data[:]-=lr*conv2d.weight.grad
print(f'epoch:{i},loss:{loss.sum():.3f}')
每次迭代的loss如下:
epoch:0,loss:5.003
epoch:1,loss:2.547
epoch:2,loss:1.458
epoch:3,loss:0.841
epoch:4,loss:0.486
epoch:5,loss:0.281
epoch:6,loss:0.162
epoch:7,loss:0.094
epoch:8,loss:0.054
epoch:9,loss:0.031
说明学习正常,此时看看学习好的权重:
tensor([[-0.9291, 0.9291]])
接近[-1,1]
卷积层通过学习得到的卷积核很接近开始指定的水平边缘检测卷积核,这说明卷积神经网络中的卷积层的确是根据指定的目标在学习图像的某些特征。