CNN
区别于全连接的浅层网络,卷积网络称为CNN。LeNet-5论文提出卷积网络具有三大设计思想:局部感受野、权值共享、下采样。
1. 卷积
卷积是CNN中的基本操作,这里介绍几种常用的卷积。下面的例子都是假设卷积层 l a y e r layer layer的输入通道是 C i n C_{in} Cin,输出通道是 C o u t C_{out} Cout,卷积核尺寸是 w × h w \times h w×h。以Pytorch为例,layer是这样的:
layer = torch.nn.Conv2d(in_channels=C_in, out_channels=C_out, kernel_size=(w, h), stride=1, bias=True)
1.1 常规卷积
常规卷积是用 C o u t C_{out} Cout个维度为 ( w , h , C i n ) (w,h,C_{in}) (w,h,Cin)的立体卷积核卷积输入特征。卷积层layer的:
- 卷积核个数是: C o u t C_{out} Cout。
- 每个卷积核的宽、高、通道是: w w w、 h h h、 C i n C_{in} Cin
- 一个卷积核的参数(包含偏置)是: w ⋅ h ⋅ C i n + 1 w \cdot h \cdot C_{in} +1 w⋅h⋅Cin+1。
- 参数总数(包括偏置)是: P a r a m s = C o u t ⋅ ( w ⋅ h ⋅ C i n + 1 ) Params = C_{out} \cdot (w \cdot h \cdot C_{in} +1) Params=Cout⋅(w⋅h⋅Cin+1)。
下图是一个卷积核卷积的示意图。卷积核的通道数等于输入特征图的通道数;卷积核的个数等于输出特征图的通道数。
1.2 空洞卷积
定义:卷积核内填充0的卷积。卷积核上相邻有效像素(不是填充的0)间的距离称为空洞率。下图是卷积核尺寸
k
e
r
n
e
l
_
s
i
z
e
=
3
kernel\_size = 3
kernel_size=3、空洞率
d
i
l
a
t
i
o
n
=
2
dilation=2
dilation=2的空洞卷积。普通卷积是空洞率为1的空洞卷积。
作用:无需改变特征图尺寸就可以提取不同尺度的特征。如下图,卷积核尺寸
k
e
r
n
e
l
_
s
i
z
e
=
3
kernel\_size = 3
kernel_size=3、空洞率
d
i
l
a
t
i
o
n
=
2
dilation=2
dilation=2的空洞卷积相当于卷积核尺寸
k
e
r
n
e
l
_
s
i
z
e
=
5
kernel\_size = 5
kernel_size=5的常规卷积,它们的感受野尺寸都是
5
×
5
5 \times 5
5×5。
空洞卷积的参数计算方式和常规卷积一样。
1.3 分组卷积
分组卷积出自AlexNet,就是把输入特征按通道维度分组,不同的卷积核卷积不同的组。假设组数为G,则每组的输入通道数为
C
i
n
G
\frac{C_{in}}{G}
GCin,每组的卷积核个数为
C
o
u
t
G
\frac{C_{out}}{G}
GCout。如下图:
上面的左图是常规卷积,每个卷积核卷积输入特征图的所有通道。右图是分组卷积,输入特征按通道维度分为
G
G
G组,卷积核也分为
G
G
G组,第
i
i
i 组输入特征被第
i
i
i 组卷积核卷积。参数总数(包括偏置)是:
P
a
r
a
m
s
=
G
⋅
C
o
u
t
G
⋅
(
w
⋅
h
⋅
C
i
n
G
+
1
)
Params = G \cdot \frac{C_{out}}{G} \cdot (w \cdot h \cdot \frac{C_{in}}{G} +1)
Params=G⋅GCout⋅(w⋅h⋅GCin+1)。如果不考虑偏置,分组卷积的参数是常规卷积的
1
G
\frac{1}{G}
G1。
在Pytorch中,分组卷积使用参数
g
r
o
u
p
s
groups
groups指定组数:
torch.nn.Conv2d(..., groups)
1.4 点卷积
点卷积就是卷积核大小为1的常规卷积,用于改变特征图的通道数。
torch.nn.Conv2d(..., kernel_size=1)
1.5 深度可分离卷积
深度可分离卷积的目的是减少参数量,包括两步:1.分组卷积,组数 G = C i n G=C_{in} G=Cin;2.点卷积:
- 先用 C i n C_{in} Cin个维度为 ( w , h , 1 ) (w,h,1) (w,h,1)的平面卷积核卷积输入特征的 C i n C_{in} Cin个通道(一个平面卷积核卷积一个通道),得到维度为 ( w ′ , h ′ , C i n ) (w',h',C_{in}) (w′,h′,Cin)的特征图,如下图 ( a ) (a) (a)。参数个数是: C i n ⋅ ( w ⋅ h ⋅ 1 + 1 ) C_{in} \cdot (w \cdot h \cdot 1 + 1) Cin⋅(w⋅h⋅1+1)。
- 再用 C o u t C_{out} Cout个维度为 ( 1 , 1 , C i n ) (1,1,C_{in}) (1,1,Cin)的立体卷积核卷积第一步得到的特征图,如下图 ( b ) (b) (b)。参数个数是: C o u t ⋅ ( 1 ⋅ 1 ⋅ C i n + 1 ) C_{out} \cdot (1 \cdot 1 \cdot C_{in} +1) Cout⋅(1⋅1⋅Cin+1)。
参数总数(包括偏置)是: P a r a m s = C i n ⋅ ( w ⋅ h ⋅ 1 + 1 ) + C o u t × ( 1 ⋅ 1 ⋅ C i n + 1 ) Params = C_{in} \cdot (w \cdot h \cdot 1 + 1)+ C_{out} \times (1 \cdot 1 \cdot C_{in} +1) Params=Cin⋅(w⋅h⋅1+1)+Cout×(1⋅1⋅Cin+1)。
1.6 空洞深度可分离卷积
空洞深度可分离卷积和深度可分离卷积一样分为两步。不同的是空洞深度可分离卷积的第一步使用的是空洞卷积,如上图 ( c ) (c) (c)。
2. 查看网络信息
Pytorch有torchvision和torchsummary,tensorflow有tensorboard。利用这些工具可以查看网络信息。下面以pytorch的VGG-16为例,演示查看网络信息的方法。
2.1 查看网络定义
from torchvision import models
if __name__ == '__main__':
net = models.vgg16()
print(net)
2.2 查看特征图尺寸和参数量
import torch
from torchvision import models
from torchsummary import summary
if __name__ == '__main__':
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = models.vgg16().to(device)
summary(net, (3, 224, 224))
2.3 查看参数名和参数值
使用model.state_dict()或model.named_parameters()查看参数名和参数值:
from torchvision import models
if __name__ == '__main__':
net = models.vgg16()
for k, v in net.named_parameters():
print(k)