AlexNet 》 VGG 》 Inception 》 ResNet 》 Inception-ResNet 》 ResNeXt 》 DenseNet 》DPN ( Dual Path Network )
基础
什么是卷积?什么是全连接?答案在属性函数中。
2、什么是神经元、连接?
什么是神经元?
上图中一个圈就是一个神经元。
单个神经元模型:
神经元就是一个函数,这个函数完成了神经元的功能。神经元=隐层的激活函数(如sigmoid、Relu等)=输出层函数(如softmax等)。这里激活函数或输出层函数都用
H
(
x
)
H(x)
H(x)(Hypothesis function)来表示。也就是说神经元是
o
u
t
p
u
t
=
H
(
i
n
p
u
t
)
output=H(input)
output=H(input),其中
i
n
p
u
t
=
(
∑
i
=
0
n
w
i
∗
x
i
)
+
b
input=(\sum_{i=0}^nw_i*x_i)+b
input=(∑i=0nwi∗xi)+b(这是
n
n
n次连接)。
x
i
x_i
xi可以是输入层的输入,也可以是隐层的输出。每一个神经元都有激活函数,有的层我们没有指定激活函数并不是没有而是激活函数
H
(
x
)
=
x
H(x)=x
H(x)=x即输入等于输出。神经元的个数的本质就是进行多少次激活函数计算。
什么是连接?
直观来说图中一条带箭头的线就是一个连接,但这不是本质,连接的本质是一次计算
w
i
∗
x
i
w_i*x_i
wi∗xi(而不是
w
i
∗
x
i
+
b
w_i*x_i+b
wi∗xi+b)就是一次连接。
AlexNet各层分析
alexnet为了加快速度,采用两片GPU分别计算。
输入Input的图像规格:
224
∗
224
∗
3
224*224*3
224∗224∗3(RGB图像),实际上会经过预处理变为
227
∗
227
∗
3
227*227*3
227∗227∗3。其实,输入的是224还是227都没关系,因为第一层的padding=“VALID”。
为什么使用Sigmoid会梯度弥散,为什么Relu能解决Sigmoid的梯度弥散问题?
首先要明白什么是神经网络的一层?
神经网络的一层就是神经元那一层。
神经网络一层的要素有哪些?
输入、神经元功能(即激活函数)与输出。
神经网络层的命名?
我们对神经网络一层的命名往往是用其输入的属性函数命名,比如属性函数是卷积,那么对应的就是卷积层,卷积结果就是卷积层的输入!
Block-1:
卷积层:
input=(N,227,227,3) (即tf中参数data_format=NHWC)
kernal_shape=filter_shape=(11,11,3)
kernals=filters=96个
stride_shape=([4,4)
padding=“VALID”
激活函数=ReLu
pad=(0,0)
过程解释:
1、根据padding判断图片是否需要用0填充,这里padding="VALID"所以不需要,所以pad=(0,0);
为什么要进行padding操作?
在卷积层中,处于中间位置的数值容易被进行多次的提取,但是边界数值的特征提取次数相对较少,为了能更好的把边界数值也利用上,而进行padding操作。要么把边界去掉,要么把原始数据矩阵的四周都补上一层0。
2、将kernal按照stride滑过图片,将对应位置的元素相乘再求和;
3、特征图大小:
input_spatial_shape=[227,227];(input_spatial_shape是tf中的称呼)
(input_spatial_shape[i]-kernal_shape[i])/stride_shape[i]+1=(227-11)/4+1=55
所以单个特征图大小是
(
55
,
55
)
(55,55)
(55,55),一共有96个,为了计算的并行可以写成(55,55,96)
4、对特征图中的元素作用激活函数;
output=(N,55,55,96)
权重参数:
11
∗
11
∗
3
∗
96
=
34848
11*11*3*96=34848
11∗11∗3∗96=34848,偏置参数:96
输出神经元个数(即output units):
55
∗
55
∗
96
=
290400
55*55*96= 290400
55∗55∗96=290400,(由
227
∗
227
∗
3
=
154587
227*227*3=154587
227∗227∗3=154587变为290400)
连接个数:总共有权重参数34848个,每个filter滑过图片进行多少次计算呢?
(
55
∗
55
)
∗
11
∗
11
∗
3
(55*55)*11*11*3
(55∗55)∗11∗11∗3次,所以总共计算了
(
55
∗
55
)
∗
11
∗
11
∗
3
∗
96
=
105415200
(55*55)*11*11*3*96=105415200
(55∗55)∗11∗11∗3∗96=105415200次,所以总共有105415200个连接。
LRN层:
参考Local Response Normalization
MaxPooling层: 相当于降维操作
input=(N,55,55,96)
pool_shape=(3,3)
stride_shape=(2,2)
padding=‘VALID’
过程解释:
1、从一个3x3中选择最大的值
output=(N,27,27,96)
27是怎么计算的?
input_spatial_shape=[27,27];
(input_spatial_shape[i]-kernal_shape[i])/stride_shape[i]+1=(55-3)/2+1=27
权重参数:0,偏置参数:0
输出神经元个数(即output units):
27
∗
27
∗
96
=
69984
27*27*96= 69984
27∗27∗96=69984,(由290400变为69984)
连接个数:0
可以看出pool层减少了神经元数量,没有新增参数,也不涉及连接,所以佐证pool不是神经网络的一层!
Block-2:
卷积层:
input=(N,27,27,96)
kernal_shape=(5,5,96)
kernals=256个
stride=(1,1)
padding=“SAME”
pad=(2,2),(有的框架这个参数会自动计算)
激活函数=ReLu
过程解释:
1、因为padding=“SAME”,需要判断是否填充,以及填充多少
input_spatial_shape=[27,27]
output_spatial_shape[0] = ceil(input_spatial_shape[0] / strides[0])=ceil(27/1)=27
output_spatial_shape[1] = ceil(input_spatial_shape[1] / strides[1])=ceil(27/1)=27
output_spatial_shape=(27,27)
反推填充后的大小:
padded_size[0]=output_spatial_shape[0]+kernal_size[0]-1=27+5-1=31
padded_size[1]=output_spatial_shape[1]+kernal_size[1]-1=27+5-1=31
padded_size=[31,31]
也就是说:27+上面2行+下面2行=31,27+左面2列+右面2列=31,所以pad=(2,2),pad[0]=2表示上下各两行,pad[0]=2表示左右各两列
2、对(N,31,31,96)用256个kernal_shape=(5,5,96)滑过,产生256个(27,27)的特征图
3、对特征图中的元素作用激活函数;
output=(N,27,27,256)
权重参数:
5
∗
5
∗
96
∗
256
=
614400
5*5*96*256=614400
5∗5∗96∗256=614400,偏置参数:256
神经元个数:
27
∗
27
∗
256
=
186624
27*27*256= 186624
27∗27∗256=186624,(由69984变为186624)
连接个数:
(
27
∗
27
∗
614400
)
/
2
=
447897600
/
2
=
223948800
(27*27*614400)/2=447897600/2=223948800
(27∗27∗614400)/2=447897600/2=223948800
LRN层:
参考Local Response Normalization
MaxPooling层:
input=(N,27,27,256)
pool_shape=(3,3),
stride=(2,2),
padding=‘VALID’
过程解释:(27-3)/2+1=13
output=(N,13,13,256)
权重参数:0,偏置参数:0
输出神经元个数:
13
∗
13
∗
256
=
43264
13*13*256= 43264
13∗13∗256=43264,(由186624变为43264)
连接个数:0
Block-3:
卷积层:
input=(N,13,13,256)
kernal_shape=(3,3,256),
kernals=384个,
stride=(1,1),
padding=“SAME”,
pad=(1,1)
激活函数=ReLu
过程解释:
1、因为padding=“SAME”,需要判断是否填充,以及填充多少
input_spatial_shape=[13,13]
output_spatial_shape[0] = ceil(input_spatial_shape[0] / strides[0])=ceil(13/1)=13
output_spatial_shape[1] = ceil(input_spatial_shape[1] / strides[1])=ceil(13/1)=13
output_spatial_shape=(13,13)
反推填充后的大小:
padded_size[0]=output_spatial_shape[0]+kernal_size[0]-1=13+3-1=15
padded_size[1]=output_spatial_shape[1]+kernal_size[1]-1=13+3-1=15
padded_size=[15,15]
也就是说上下各1行,左右各1列,都用0填充
2、对(N,13,13,256)用384个shape=(3,3,256)的filter滑过,产生384个(13,13)的特征图
3、对特征图中的元素作用激活函数;
output=(N,13,13,384)
权重参数:
3
∗
3
∗
256
∗
384
=
884736
3*3*256*384=884736
3∗3∗256∗384=884736,偏置参数:384
神经元个数:
13
∗
13
∗
384
=
64896
13*13*384= 64896
13∗13∗384=64896,(由43264变为64896)
连接个数:
13
∗
13
∗
884736
=
149520384
13*13*884736=149520384
13∗13∗884736=149520384
Block-4:
卷积层:
input=(N,13,13,384)
kernal_shape=(3,3,384),
kernals=384个,
stride=(1,1),
padding=“SAME”,
pad=(1,1)
激活函数=ReLu
过程解释:
1、上下各1行,左右各1列,都用0填充
2、对(N,13,13,384)用384个shape=(3,3,384)的filter滑过,产生384个(13,13)的特征图
3、对特征图中的元素作用激活函数;
output=(N,13,13,384)
权重参数:
3
∗
3
∗
384
∗
384
=
1327104
3*3*384*384=1327104
3∗3∗384∗384=1327104,偏置参数=384
神经元个数:
13
∗
13
∗
384
=
64896
13*13*384= 64896
13∗13∗384=64896,(由64896变为64896)
连接个数:
(
13
∗
13
∗
1327104
)
/
2
=
224280576
/
2
=
112140288
(13*13*1327104)/2= 224280576/2=112140288
(13∗13∗1327104)/2=224280576/2=112140288
Block-5:
卷积层:
input=(N,13,13,384)
kernal_shape=(3,3,384),
kernals=256个,
stride=(1,1),
padding=“SAME”,
pad=(1,1)
激活函数=ReLu
过程解释:
1、上下各1行,左右各1列,都用0填充
2、对(N,13,13,384)用256个shape=(3,3,384)的filter滑过,产生256个(13,13)的特征图
3、对特征图中的元素作用激活函数;
output=(N,13,13,256)
权重参数:
3
∗
3
∗
384
∗
256
=
884736
3*3*384*256=884736
3∗3∗384∗256=884736,偏置参数=256
神经元个数:
13
∗
13
∗
256
=
43264
13*13*256= 43264
13∗13∗256=43264,(由64896变为43264)
连接个数:
(
13
∗
13
∗
884736
)
/
2
=
149520384
/
2
=
74760192
(13*13*884736)/2 =149520384/2=74760192
(13∗13∗884736)/2=149520384/2=74760192
MaxPooling层:
input=(N,13,13,256)
pool_size=(3,3],
stride=(2,2),
padding=‘VALID’
过程解释:(13-3)/2+1=6
output=(N,6,6,256)
权重参数:0,偏置参数:0
输出神经元个数:
6
∗
6
∗
256
=
9216
6*6*256= 9216
6∗6∗256=9216,(由
43264
变
为
9216
43264变为9216
43264变为9216)
连接个数:0
第2、4、5层求连接个数的时候要减半的原因(有待理解)
从第6层开始就有两个实现版本,一个是alexnet原论文版本叫v1版,另一个是改造后版本叫v2版
v1版:
Block-6:
全连接层:
进行flat操作input=(N,9216) (其中
9216
=
6
∗
6
∗
256
9216=6*6*256
9216=6∗6∗256)
kernal_shape=(9216,),
kernals=4096个,
stride=(1,1),
padding=“VALID”,
pad=(0,0)
激活函数=ReLu
过程解释:
1、对(N,9216)用4096个shape=(9216,)的filter滑过,产生4096个的特征值,此时就不再是特征图了,由最开始的输入(N,227,227,3)变成(N,4096),即一个图片变成4096个特征值。
2、对特征图中的元素作用激活函数;
output=(N,4096)
权重参数:
6
∗
6
∗
256
∗
4096
=
37748736
6*6*256*4096=37748736
6∗6∗256∗4096=37748736,偏置参数=4096
神经元个数:4096
连接个数=输入神经元数*输出神经元数=
(
6
∗
6
∗
256
)
∗
(
4096
)
(6*6*256)*(4096)
(6∗6∗256)∗(4096)=权重参数个数=37748736
可以看出全连接层是以一种特殊的卷积层,即卷积核shape=输入shape且padding=“VALID”。
Block-7:
全连接层:
input=(N,4096)
kernal_shape=(4096,),
kernals=4096个,
stride=(1,1),
padding=“VALID”,
pad=(0,0)
激活函数=ReLu
过程解释:
output=(N,4096)
权重参数:4096*4096=16777216,偏置参数=4096
神经元个数:4096
连接个数=16777216
Block-8(输出层):
全连接层:
input=(N,4096)
kernal_shape=(4096,),
kernals=1000个,
stride=(1,1),
padding=“VALID”,
pad=(0,0)
Softmax
过程解释:
1、这里的1000=总的分类数
2、Softmax就是激活函数
output=(N,4096)
权重参数:4096*1000=4096000个(这里没有偏置参数,如果有就是4096个)
神经元个数:1000
连接个数=4096000
Block | 层 | 信息 |
---|---|---|
1 | Convolution | 11x11x3x96; (Stride(4,4); Pad(0,0), ReLu, LRN=(k,α, β, n)=(2, 10^{−4}, 0.75,5) |
MaxPooling | 3x3 - Stride(2,2) | |
2 | Convolution | 5x5x96x256 - Stride(1,1) - Pad(2,2), ReLu, LRN=(k,α, β, n)=(2, 10^{−4}, 0.75,5) |
MaxPooling | 3x3 - Stride(2,2) | |
3 | Convolution | 3x3x256x384 - Stride(1,1) - Pad(1,1), ReLu |
4 | Convolution | 3x3x384x384 - Stride(1,2) - Pad(1,1), ReLu |
5 | Convolution | 3x3x384x256 - Stride(1,1) - Pad(1,1), ReLu |
MaxPooling | 3x3 - Stride(2,2) | |
6 | Fully connected | 9216x4096 - Stride(1,1) - Pad(0,0), ReLu |
7 | Fully connected | 9216x4096 - Stride(1,1) - Pad(0,0), ReLu |
8 | Fully connected | 4096x1000 - Stride(1,1) - Pad(0,0),Softmax |
这里的ReLU、Softmax都是假设函数,那么MaxPooling层没有假设函数吗?有的,其假设函数是线性的,即 H j = H ( A j ) = A j H_j=H(A_j)=A_j Hj=H(Aj)=Aj
v2版:
Block-6:
卷积层:
input=(N,6,6,256)
kernal_shape=(5,5,256),
kernals=4096个,
stride=(1,1),
padding=“VALID”,
pad=(0,0)
激活函数=ReLu
过程解释:
1、对(N,6,6,256)用4096个shape=(5,5,256)的filter滑过,产生4096个的特征值
2、对特征图中的元素作用激活函数;
output=(N,4096)
Block-7:
Dropout层:
input=(N,4096)
output=(N,4096)
Block-8(输出层):
卷积层:
input=(N,4096)
kernal_shape=(4096,),
kernals=1000个,
stride=(1,1),
padding=“VALID”,
pad=(0,0)
Softmax
过程解释:
1、这里的1000=总的分类数
2、Softmax
output=(N,4096)
v2版本的代码实现tf-slim的\research\slim\nets\alexnet.py
模型是什么?
比如线性回归中由
y
′
=
(
∑
i
=
0
n
w
i
∗
x
i
)
+
b
y'=(\sum_{i=0}^nw_i*x_i)+b
y′=(∑i=0nwi∗xi)+b,这里的
n
n
n个
w
i
w_i
wi和
b
b
b就是我们要训练的参数,也就是我们的模型。那么alexnet中要训练的参数是什么?
Block | 神经元数 | 权重参数个数 | 连接数 |
---|---|---|---|
1 | 290400 | 34848 | 105415200 |
2 | 186624 | 307200 | 223948800 |
3 | 64896 | 884736 | 149520384 |
4 | 64896 | 663552 | 112140288 |
5 | 43264 | 442368 | 74760192 |
6 | 4096 | 37748736 | 37748736 |
7 | 4096 | 16777216 | 16777216 |
8 | 1000 | 4096000 | 4096000 |
总计 | 659272 | 60954656 | 724406816 |
alexnet的模型参数是6千万数量级。
模型是怎么训练的?这个问题等同于参数是如何更新的?