CNN
从全连接层到卷积
无论哪种方法找到这个物体,都应该和物体的位置没有关系。使用一个物体检测器,该检测器将图像分割成多个区域,并为每个区域包含物体的可能性打分,卷积神经网络正是将空间不变性的这一个概念系统化,从而基于这个模型使用较少的参数来学习有用的表示。
设计适合计算机视觉的神经网络架构:
平移不变性:不管检测对象出现在图像的哪个位置,神经网络的前几层应该对相同的图像区域具有相似的反应。
局部性:神经网络的前几层应该只探索输入图像中的局部区域,而不过度在意图像中相隔较远区域的关系,最后可以聚合这些局部特征,以在整个图像级别进行预测。
X,H均为二维张量,但是为了使得每个神经元都能接收到每个输入像素的信息,将参数从权重据矩阵替换成四阶权重张量W,U中包含偏置参数可以将全连接层形式化为:
不是需要通过重新变形和重新索引变成卷积,而是卷积是一种特殊的全连接层。卷积神经网络是包含全基层的一类特殊的神经网络,V被称为是卷积核,也被称为卷积层的权重。在图像处理中,卷积层通常比全连接层需要更少的参数,但依旧获得高效用的模型。多个输入和输出通道使模型在每个空间位置可以获取图像的多方面特征。
损失抖动很厉害的原因是数据集很大
图像卷积
卷积层所表达的运算其实是互相关运算,输入张量和核张量通过互相关运算产生输出张量。
输出大小=输入大小-卷积核大小
输出的卷积层有时被称为特征映射,因为它可以被视为一个输入映射到下一层的空间维度的转换器,在卷积神经网络中,对于某一层的任意元素x,其感受野是指在前向传播期间可能影响x计算的所有元素(来自所有先前层),感受野可能大于输入的实际大小。
二维卷积的核心计算是二维互相关计算,最简单的计算是对二维输入数据和卷积核执行互相关操作,然后添加一个偏置。学习卷积核时,无论用严格卷积运算,或互相关运算,卷积层的输出不会受太大影响。当需要检测输入特征中更广的区域时,可以构建一个更深的卷积网络。
# 互相关运算
import torch
from torch import nn
from d2l import torch as d2l
# K 是核矩阵
def corr2d(X,K):
"""计算二维互相关运算"""
# 拿出K的行数和列数
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 = 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.]])
实现二维卷积层
# 实现二维卷积层
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
# 卷积层的简单应用:检测图像中不同颜色的边缘
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.]])
K = torch.tensor([[1.0,-1.0]])
# 输出的Y中代表的1从白色到黑色边缘,-1代表从黑色到白色边缘
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只可以检测到垂直边缘 将X转置之后就没有办法进行检测
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.]])
学习卷积核
# 学习由X生成Y的卷积核 输入是1通道输出是1通道
conv2d