卷积神经网络是含有卷积层的神经网络
二维互相关运算
二维互相关(cross-correlation)运算的输入是一个二维输入数组和一个二维核(kernel)数组,输出也是一个二维数组,其中核数组通常称为卷积核或过滤器(filter)。卷积核的尺寸通常小于输入数组,卷积核在输入数组上滑动,在每个位置上,卷积核与该位置处的输入子数组按元素相乘并求和,得到输出数组中相应位置的元素。
实现的函数如下
def corr2d(X,K):
H,W = X.shape
h,w = K.shape
Y = torch.zeros(H-h+1,W-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
直接用*可以实现矩阵的点乘,或者用torch.mul(a, b)实现矩阵a和b对应位相乘,点乘再相加就是卷积。
二维卷积层
二维卷积层是对输入和卷积核做互相关运算,再加上一个偏差得到输出,因此二维卷积层得模型参数包括卷积核和偏差。
基于pytorch的自定义层的通常的步骤
(1)自定义一个继承自Module的类,类要实现两个基本的函数,第一是构造函数__init__,第二个是层的逻辑运算函数,即forward函数。
(2)构造函数_init__中实现层的参数定义
(3)构造函数_init__中实现层的参数定义
下面实现一个卷积的网络
class Conv2D(nn.Module):
def __init__(self,kernel_size):
super(Conv2D,self).__init__()
self.weight = nn.Parameter(torch.randn(kernel_size))
self.bias = nn.Parameter(torch.randn(1))
def forward(self, x):
return corr2d(x,self.weight) + self.bias
torch.randn(*sizes, out=None) → Tensor
返回一个张量,包含了从标准正态分布(均值为0,方差为1)中抽取的一组随机数。张量的形状由参数sizes定义。
特征图与感受野
⼆维卷积层输出的⼆维数组可以看作是输⼊在空间维度(宽和⾼)上某⼀级的表征,也叫特征图(feature map)。影响元素x的前向计算的所有可能输⼊区域(可能⼤于输⼊的实际尺⼨)叫做x的感受野(receptive field)
池化层
池化层的提出是为了缓解卷积层对位置的过度敏感性。
常见的池化操作有平均池化和最大池化。
池化层直接对窗口内的元素求最大值或平均值,并没有模型参数参与计算。
池化层夹在连续的卷积层中间,主要的作用有降维、去除冗余信息、对特征进行压缩、简化网络复杂度、减小过拟合、减少计算量、减少内存消耗等等。
如果输入是图像的话,那么池化层的最主要作用是压缩图像。
填充和步幅
填充:
在做卷积时,如果我们有一个n×n的图像,用f×f的过滤器做卷积,那么输出的维度就是
(
n
−
f
+
1
)
×
(
n
−
f
+
1
)
(n-f+1)×(n-f+1)
(n−f+1)×(n−f+1),输出的图像会变小了;同时那些在角落或者边缘区域的像素点在输出中采用较少,会丢掉了图像边缘位置的许多信息,为了解决这个问题,引入了填充(padding)。
填充(padding)是指在输⼊⾼和宽的两侧填充元素(通常是0元素)。
如果在⾼的两侧⼀共填充
p
h
p_h
ph⾏,在宽的两侧⼀共填充
p
w
p_w
pw列,那么输出形状将会是
(
n
−
f
+
p
h
+
1
)
×
(
n
−
f
+
p
w
+
1
)
(n-f + p_h + 1) × (n-f + p_w + 1)
(n−f+ph+1)×(n−f+pw+1)。
步幅:
卷积窗口每次滑动的⾏数和列数称为步幅(stride)。
如果用一个
f
×
f
f×f
f×f的过滤器卷积一个
n
×
n
n×n
n×n的图像,padding为p,步幅为s,一次移动s个步子,输出为
(
(
n
+
2
p
−
f
)
/
s
+
1
)
×
(
(
n
+
2
p
−
f
)
/
s
+
1
)
((n+2p-f)/s+1)×((n+2p-f)/s+1)
((n+2p−f)/s+1)×((n+2p−f)/s+1)