概述
卷积神经网络Convolutional Neural Network,CNN。
卷积神经网络一般是由卷积层、池化层和全连接层交叉堆叠而成的前馈神经网络,全连接层一般在最顶层。
卷积神经网络有三个结构上的特性:局部连接、权重共享以及池化,这些特征使得卷积神经网络具有一定程度上的平移、缩放和旋转不变性。
卷积运算
滑动步长S:Stride,卷积核在滑动时的时间间隔
零填充P:Padding,在输入向量的两端进行补零
窄卷积:
宽卷积:
等宽卷积:
一幅图像在经过卷积操作后得到结果称为特征映射Feature Map
高斯核:平滑图像
均值滤波器:
斜对角边缘特征:
水平特征:
垂直特征:
import torch
from torch import nn
def corr2d(x, k):
"""
x: 输入,shape(h, w)
k: 卷积核,shape(k_h, k_w)
"""
h, w = x.shape
k_h, k_w = k.shape
# 初始化结果矩阵
y = torch.zeros(h - k_h + 1, w - k_w + 1)
for i in range(y.shape[0]):
for j in range(y.shape[1]):
y[i, j] = (x[i: i + k_h, j: j + k_w] * k).sum()
return y
x = torch.ones(5, 3)
k = torch.ones(2, 1)
corr2d(x, k)
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
def corr2d_multi_in(X, K):
# 输入X:维度(C_in, H, W)
# 卷积核K:维度(C_in, k_h, k_w)
res = corr2d(X[0, :, :], K[0, :, :])
for i in range(1, X.shape[0]):
# 按通道相加
res += corr2d(X[i, :, :], K[i, :, :])
return res
def corr2d_multi_in_out(X, K):
# 对 k 的第 e 维遍历,每次同输入 x 做互相关计算
# 所有结果使用 stack 函数合并在一起
return torch.stack([corr2d_multi_in(X, k) for k in K])
X = torch.arange(192, dtype=torch.float).view(3, 8, 8)
# 4 个卷积核,卷积核三通道
K = torch.arange(108, dtype=torch.float).view(4, 3, 3, 3)
print(X.shape, K.shape)
Y = corr2d_multi_in_out(X, K)
print(Y.shape)
torch.Size([3, 8, 8]) torch.Size([4, 3, 3, 3])
torch.Size([4, 6, 6])
def pool2d(X, pool_size, mode = 'max'):
X = X.float()
p_h, p_w = pool_size
Y = torch.zeros(X.shape[0] - p_h + 1, X.shape[1] - p_w + 1)
for i in range(Y.shape[0]):
for j in range(Y.shape[1]):
if mode == 'max':
Y[i, j] = X[i: i + p_h, j: j+ p_w].max()
elif mode == 'avg':
Y[i, j] = X[i: i + p_h, j: j+ p_w].mean()
return Y
H
2
=
(
H
1
−
K
+
2
P
)
/
S
+
1
H_2 = (H_1 - K + 2P\,)\,/ S + 1
H2=(H1−K+2P)/S+1
其中,
H
2
H_2
H2是卷积后的feature_map的宽度,
H
1
H_1
H1是卷积前图像的宽度,K是滤波器的宽度,P是零填充的数量,S是步长。
在机器学习和图像处理领域,卷积的主要功能是在一个图像(或某种特征)上滑动一个卷积核(即滤波器),通过卷积操作得到一组新的特征,在计算过程中,需要进行卷积核翻转。
互相关(Cross-Correlation)是一个衡量两个序列相关性的函数,通常是用滑动窗口的点积计算来实现,给定一个图像
X
∈
R
M
×
N
X \in R^{M \times N}
X∈RM×N和一个卷积核
W
∈
R
U
×
V
W \in R^{U \times V}
W∈RU×V,它们的互相关为:
y
i
j
=
∑
u
=
1
U
∑
v
=
1
V
w
u
v
x
i
+
u
−
1
,
j
+
v
−
1
y_{ij}=\sum_{u=1}^U\sum_{v=1}^Vw_{uv}\,x_{i+u-1,\,j+v-1}
yij=u=1∑Uv=1∑Vwuvxi+u−1,j+v−1
对比卷积:
y
i
j
=
∑
u
=
1
U
∑
v
=
1
V
w
u
v
x
i
−
u
+
1
,
j
−
v
+
1
y_{ij}=\sum_{u=1}^U\sum_{v=1}^Vw_{uv}\,x_{i-u+1,\,j-v+1}
yij=u=1∑Uv=1∑Vwuvxi−u+1,j−v+1
在神经网络中使用卷积是为了进行特征抽取,卷积核是否进行翻转和其特征抽取的能力无关,特别是当卷积核是可学习的参数时,我们用互相关来代替卷积核,事实上,很多深度学习工具中的卷积操作其实都是互相关操作。
稀疏交互:局部连接、局部感受野
权值共享:
共享卷积核参数——只提取了一种特征,作为参数的卷积核
w
(
l
)
w(l)
w(l)对于第
l
l
l层的所有神经元都是相同的,权重共享可以理解为一个卷积核只捕捉输入数据中的一种特定的局部特征,因此,如果需要提取多种特征,就需要使用多个不同的卷积核。
平移不变性:
由卷积和池化共同实现,平移不变性意味着系统产生完全相同的响应(输出),不管它的输入是如何平移的。
卷积:图像经过平移,相应的特征图上的表达也是平移的,即平移不变性。
池化:最大池化,返回感受野的最大值,如果最大值被移动了,但是仍然在感受野中,那么池化层将仍然输出相同的最大值。
上述两种操作共同提供了一些平移不变性,即使图像被平移,卷积保证仍然能够检测到它的特征,池化则尽可能地保持一致的表达。
池化
池化层(Pooling Layer),也叫子采样层(Subsampling Layer),其作用是进行特征选择,降低特征数量,从而减少参数数量。
卷积层虽然可以显著减少网络中连接的数量,但特征映射组中的神经元个数并没有显著减少,如果后面接一个分类器,分类器的输入维数依然很高,很容易出现过拟合,为了解决这个问题,可以在卷积层之后加上一个池化层,从而降低特征维数,避免过拟合。
池化(Pooling)是指对每个区域进行下采样(Down Sampling)得到一个值,作为这个区域的概括。能够抑制网络参数误差造成的估计均值偏移的现象,对纹理的提取较好。
更好地获取平移不变性,更高的计算效率(减少了神经元数量)
最大池化(Maximum Pooling,或Max Pooling):对于一个区域,选择该区域内所有神经元地最大活性值作为这个区域的表示。
平均池化(Mean Pooling):平均值,抑制差距,对输入的整体信息保存较好,比如图片背景。
在CNN出现之前,图像处理两大难点:
1、图像在数字化的过程中很难保留原有的特征,导致图像处理的准确率不高;
2、图像需要处理的数据量太大,导致成本很高,效率很低。
1、卷积层:提取特征
2、池化层:降维、防止过拟合
3、全连接层:输出结果
Convolution – Pooling – Convolution – Pooling – Fully-connnected
卷积核(Kernel)也叫滤波器(filter),代表图像的某种特征,所有神经元加起来相当于整张图的特征提取器集合。
图像特征图的“分布式特征表示”映射到样本标记空间,在整个卷积神经网络中起到“分类器”的作用。
卷积神经网络的应用
- 以(多维)数组形式出现的信号
- 局部相关性强的信号
- 特征可以出现在任何位置的信号
- 物体平移和变形不变的信号
- 一维卷积网络:循序信号、文本,(文本、音乐、音频、演讲、时间序列)
- 二维卷积网络:图像、时频表示(语音和音频),(目标检测、定位、识别)
- 三维卷积网络:视频、体积图像、断层扫描图像,(视频识别/理解、生物医学图像分析、高光谱图像分析)
参数学习
有监督的学习:前向传播 – 损失函数 – 反向传播 – 更新权重
超参的设计:网络的深度(隐藏层的层数)、卷积核(神经元)的数量、卷积核的大小
与全连接前馈网络相似,卷积网络也可以通过误差反向传播算法来进行参数学习,参数为卷积核中的权重以及偏置,在卷积神经网络中,主要有两种不同功能的神经层:卷积层和池化层,卷积核及偏置仅存在于卷积层,因此只需要计算卷积层中参数的梯度。
池化层是图像的压缩。
卷积层的前向传播时是通过卷积核做卷积运算得到feature map,其反向传播的目的是更新卷积核的参数。
误差传播
sensitive map
flipped filter
input
- 卷积层:计算损失函数,求梯度,更新卷积核权重参数
- 池化层:对于max pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项的值都为0
转置卷积:低维特征映射到高维
增加输出单元的感受野
- 增加卷积核的大小(参数增加)
- 增加层数(参数增加)
- 在卷积之前进行池化操作(信息损失)
- 空洞卷积dilated convolution(膨胀卷积,Atrous Concolution):在卷积核中间插零,不增加参数数量,不损失信息,同时增加输出单元的感受野,膨胀率 - 1 = 插入空洞数
空洞卷积
- 适用于图片size较大或者需要快速感受全局信息的情况
- 可以通过设置不同的dilation rate(膨胀率),捕获多尺度上下文信息,适用于需要捕获图片的多层次的情况,如语义分割等
- 空洞卷积存在网格效应
- 远距离的点之间的信息可能不相关
解决方案:HDC,Hybrid Dilated Convolution
- 叠加卷积的dilation rate不能有大于1的公约数
- 将dilation rate设计成锯齿状结构,同时捕获远近信息
LeNet,1998
基于LeNet-5的手写数字识别系统
- 卷积、池化、非线性层
- 卷积提取空间特征
- 使用映射到空间均值的下采样(subsampling)
- 双曲线(Tanh)或S型(Sigmoid)形式的非线性
- 多层神经网络(MLP)作为最后的分类器
LeNet提供了利用卷积层堆叠进行特征提取的框架
- 输入灰度图像3232,卷积核大小55,卷积层C1,28*28,6通道
- 下采样层S2,即池化层,加权平均池化,14*14,6通道
- 卷积层C3,10*10,16个卷积核。由S2到C3的16通道使用连接表来进行组合
- S4在C3上做下采样,5*5,16通道
- C5卷积,120个特征图,每个单元与S4层中的全部16个单元的5*5领域相连,即S4与C5构成全连接
- F6与C5全连接,F6层计算输入向量和权重向量之间的点积,再加上一个偏置,然后将其传递给sigmoid函数产生节点的输出
AlexNet,2012
- 首次使用ReLU函数(非线性激活函数),验证其在较深网络中效果优于sigmoid,解决sigmoid梯度弥散,提高网络训练速率
- 防止过拟合:Dropout,数据增强
- 大数据训练:百万级ImageNet图像数据
- 分Group实现双GPU并行,局部响应归一化(LRN)层
对局部神经元的活动状态创建竞争机制,响应大的神经元权重增大,抑制较小的神经元,增强模型的泛化能力
利用GPU强大的并行计算能力加速网络训练过程,并采用GPU分块训练的方式解决显存对网络规模的限制
利用随机裁剪和翻转镜像操作增加训练数据量,降低过拟合 - 5个卷积层,3个汇聚层和3个全连接层,使用重叠的最大池化(Max pooling),避免平均池化带来的模糊化效果,重叠技巧提升特征的丰富性
在ILSVR2012图像分类竞赛中将Top-5错误率下降至16.4%
Inception网络
GoogLeNet
- 多个Inception模块加少量汇聚层堆叠而成
- 减少网络参数,降低运算量
- 多尺度,多层次滤波:符合Hebbian原理
残差网络,ResNet
层数堆叠导致的问题:
- 梯度消失和爆炸
- 网络退化(Degradation):随着网络加深,准确率首先达到饱和,然后快速退化(训练集的错误率也上升,并非过拟合),反向传播路途长,训练效果差
Residual Network
- 残差映射 = 残差函数 + 恒等函数
- 没有带来额外的参数和计算开销
模型
- 输入层:batch_size, C_in, H, W
- 卷积 + 激活:Conv2D, BatchNorm, ReLU
- 池化层:Pooling
- 全连接层:FCN
- 输出层:batch_size, 10
class MyConv2D(nn.Module):
def __init__(self, in_channels, out_channels, kernel_size):
super(Conv2D, self).__init__()
# 初始化卷积层的2个参数:卷积核、偏差
if isinstance(kernel_size, int):
kernel_size = (kernel_size, kernel_size)
self.weight = nn.Parameter(torch.randn((out_channels, in_channels) + kernel_size))
self.bias = nn.Parameter(torch.randn(out_channels, 1, 1))
def forward(self, x):
# x: 输入图片,shape(batch_size, C_in, H, W)
return corr2d_multi_in_out(x, self.weight) + self.bias