文章目录
本课程来自深度之眼deepshare.net,部分截图来自课程视频。
内容概要
学习网络模型中采用的神经网络层,包括卷积层,池化层,全连接层和激活函数层,学会如何区分二维卷积和三维卷积;
卷积层
1d/2d/3d卷积
卷积运算:卷积核在输入信号(图像)上滑动,相应位置上进行乘加
卷积核:又称为滤波器,过滤器,可认为是某种模式,某种特征。
卷积过程类似于用一个模版去图像上寻找与它相似的区域,与卷积核模式越相似,激活值越高,从而实现特征提取.
AlexNet卷积核可视化,发现卷积核学习到的是边缘,条纹,色彩这一些细节模式.
卷积维度:一般情况下,卷积核在几个维度上滑动,就是几维卷积。
一维卷积
二维卷积
三维卷积
卷积-nn.Conv2d()
nn.Conv2d功能:对多个二维信号进行二维卷积
主要参数:
·in_channels:输入通道数
·out_channels:输出通道数,等价于卷积核个数
·kernel_size:卷积核尺寸
·stride:步长
·padding:填充个数
·dilation:空洞卷积大小
·groups:分组卷积设置
·bias:偏置
下面的图中stride分别等于1和2.
下图是padding的例子,左边没有padding卷积后变小了,右边padding,卷积后大小不变。
空洞卷积主要用于目标检测,主要是扩大kernel的感受野。
分组卷积就类似AlexNet中将卷积分为两组,两组处理数据过程中不相互通讯,直到最后的FC才组合起来。
尺寸计算:
简化版(不带padding):
o
u
t
s
i
z
e
=
I
n
s
i
z
e
−
k
e
r
n
e
l
s
i
z
e
s
t
r
i
d
e
+
1
out_{size}=\cfrac{In_{size}-kernel_{size}}{stride}+1
outsize=strideInsize−kernelsize+1
例如上图就是(4-3)/1+1=2
完整版:
H
o
u
t
=
⌊
H
i
n
+
2
×
p
a
d
d
i
n
g
[
0
]
−
d
i
l
a
t
i
o
n
[
0
]
×
(
k
e
r
n
e
l
_
s
i
z
e
[
0
]
−
1
)
−
1
s
t
r
i
d
e
[
0
]
+
1
⌋
H_{out}=\left \lfloor \cfrac{H_{in}+2×padding[0]-dilation[0]×(kernel\_size[0]-1)-1}{stride[0]}+1 \right \rfloor
Hout=⌊stride[0]Hin+2×padding[0]−dilation[0]×(kernel_size[0]−1)−1+1⌋
问题:一个RGB的图片转化为三维的张量后做卷积为什么不是三维卷积而是二维卷积呢?
因为RGB三个通道每个通道都是单独的一个卷积核进行操作,每个卷积核在xy两个维度上滑动,所以是二维卷积。三个卷积核得到的结果相加然后加上bias,得到输出的一个结果。
转置卷积-nn.ConvTranspose
转置卷积又称为反卷积(这个名字一般不用,避免和信号处理里面的反卷积重复)(Deconvolution)和部分跨越卷积(Fractionally strided Convolution),用于对图像进行上采样(UpSample)
为什么称为转置卷积?先通过一个实例来看看正常卷积如何操作的:
假设图像尺寸为44,卷积核为33,padding=0,stride=1
正常卷积:
先把输入图像拉成一个一维的矩阵:
I
16
∗
1
I_{16*1}
I16∗1其中16代表图像的像素,1代表1张图片;
卷积核矩阵:
K
4
∗
16
K_{4*16}
K4∗16,其中16是卷积核3×3=9然后通过补0,补到16位得来的,4是输出图像的像素值的总个数。
输出图像矩阵:
O
4
∗
1
=
K
4
∗
16
∗
I
16
∗
1
O_{4*1}=K_{4*16}*I_{16*1}
O4∗1=K4∗16∗I16∗1,就是输入矩阵与卷积核矩阵进行相乘。
最后把输出图像矩阵
O
4
∗
1
O_{4*1}
O4∗1进行reshape得到输出图像。
转置卷积:
假设图像尺寸为2×2,卷积核为3×3,padding=0,stride=1
图像矩阵:
I
4
∗
1
I_{4*1}
I4∗1
卷积核矩阵:
K
16
∗
4
K_{16*4}
K16∗4,其中4卷积核3*3=9然后剔除,选出其中4个和输入图像计算,16是输出图像的像素值的总个数。
输出图像矩阵:
O
16
∗
1
=
K
16
∗
4
∗
I
4
∗
1
O_{16*1}=K_{16*4}*I_{4*1}
O16∗1=K16∗4∗I4∗1
因此可知:
转置卷积核与正常卷积核在形状上是转置的关系,但是二者的权值上不是转置关系,因此对图像做正常卷积后再做转置卷积是不会得到原图像的~! 以上也是为什么不把转置卷积称为逆卷积或反卷积的原因。
nn.ConvTranspose2d
功能:转置卷积实现上采样
主要参数:
·in_channels:输入通道数
·out_channels:输出通道数
·kernel_size:卷积核尺寸
·stride:步长
·padding:填充个数
·dilation:空洞卷积大小
·groups:分组卷积设置
·bias:偏置
尺寸计算:
简化版(不带padding):
o
u
t
s
i
z
e
=
(
i
n
s
i
z
e
−
1
)
∗
s
t
r
i
d
e
+
k
e
r
n
e
l
s
i
z
e
out_{size}=(in_{size}-1)*stride+kernel_{size}
outsize=(insize−1)∗stride+kernelsize
完整版:
H
o
u
t
=
(
H
i
n
−
1
)
×
s
t
r
i
d
e
[
0
]
−
2
×
p
a
d
d
i
n
g
[
0
]
+
d
i
d
l
a
t
i
o
n
[
0
]
×
(
k
e
r
n
e
l
s
i
z
e
[
0
]
−
1
)
+
o
u
t
p
u
t
p
a
d
d
i
n
g
[
0
]
+
1
H_{out}=(H_{in}-1)×stride[0]-2×padding[0]+didlation[0]×(kernel_size[0]-1)+output_padding[0]+1
Hout=(Hin−1)×stride[0]−2×padding[0]+didlation[0]×(kernelsize[0]−1)+outputpadding[0]+1
池化层—Pooling Layer
池化运算:对信号进行“收集”并“总结”,类似水池收集水资源,因而得名池化层
“收集”:多变少“总结”:最大值/平均值
nn.MaxPool2d
功能:对二维信号(图像)进行最大值池化
主要参数:
·kernel_size:池化核尺寸
·stride:步长(通常与kernel_size一样大,就是不重叠)
·padding:填充个数
·dilation:池化核间隔大小
·ceil_mode:尺寸向上取整
·return_indices:记录池化像素索引(通常是在最大值反池化上采样时使用,)
nn.AvgPool2d
功能:对二维信号(图像)进行平均值池化
主要参数:
·kernel_size:池化核尺寸
·stride:步长
·padding:填充个数
·ceil_mode:尺寸向上取整
·count_include_pad:填充值用于计算
·divisor override:除法因子(设置后不再除以池化核尺寸大小,而是除法因子)
nn.MaxUnpool2d
功能:对二维信号(图像)进行最大值池化上采样
主要参数:
·kernel_size:池化核尺寸
·stride:步长
·padding:填充个数
上采样要记录最大值的索引,所以在forward的时候需要传入index参数。
forward(self,input,indices,output_size=None)
线性层—Linear Layer
线性层又称全连接层,其每个神经元与上一层所有神经元相连实现对前一层的线性组合,线性变换。
输入:
I
n
p
u
t
=
[
1
,
2
,
3
]
Input=[1,2,3]
Input=[1,2,3],大小:
s
h
a
p
e
=
(
1
,
3
)
shape=(1,3)
shape=(1,3)
权值矩阵:
W
0
=
[
1
2
3
4
1
2
3
4
1
2
3
4
]
W_0=\begin{bmatrix} 1 & 2 &3 & 4\\ 1 & 2 & 3 &4 \\ 1 & 2 &3 & 4 \end{bmatrix}
W0=⎣⎡111222333444⎦⎤,大小:
s
h
a
p
e
=
(
3
,
4
)
shape=(3,4)
shape=(3,4)
隐藏层:
H
i
d
d
e
n
=
I
n
p
u
t
∗
W
0
=
[
6
,
12
,
18
,
24
]
Hidden=Input*W_0=[6,12,18,24]
Hidden=Input∗W0=[6,12,18,24],大小:
s
h
a
p
e
=
(
1
,
4
)
shape=(1,4)
shape=(1,4)
这里忽略了bias
nn.Linear
功能:对一维信号(向量)进行线性组合
主要参数:
·in features:输入结点数
·out features:输出结点数
·bias:是否需要偏置
计算公式:
y
=
x
W
T
+
b
i
a
s
y=xW^T+bias
y=xWT+bias
inputs=torch.tensor([[1.,2,3]])
1inear_layer=nn. Linear(3,4)
1inear_layer.weight.data=torch. tensor([[1.,1.,1.],
[2.,2.,2.], I[B.,3.,3.],[4.,4.,4.]])
1inear_layer.bias.data. fill_(0.)
output=linear_layer(inputs)
print(inputs, inputs. shape)
print(linear_layer.weight.data,1inear_layer.weight.data.shape)
print(output, output.shape)
激活函数层——Activation Layer
激活函数对特征进行非线性变换,赋予多层神经网络具有深度的意义。
如果是线性激活函数,上面的神经网络可以写为:
H
1
=
X
∗
W
1
H_1=X*W_1
H1=X∗W1
H
2
=
H
1
∗
W
2
H_2=H_1*W_2
H2=H1∗W2
o
u
t
p
u
t
=
H
2
∗
W
3
=
H
1
∗
W
2
∗
W
3
=
X
∗
(
W
1
∗
W
2
∗
W
3
)
=
X
∗
W
output=H_2*W_3=H_1*W_2*W_3=X*(W_1*W_2*W_3)=X*W
output=H2∗W3=H1∗W2∗W3=X∗(W1∗W2∗W3)=X∗W
也就是说,如果是线性激活函数,无论叠加多少层,都可以看做是一个线性函数而已。
但是如果激活函数是非线性的,那就不一样了。
nn.Sigmoid
计算公式:
y
=
1
/
(
1
+
e
−
x
)
y= 1/(1+e^{-x})
y=1/(1+e−x)
梯度公式:
y
′
=
y
∗
(
1
−
y
)
y'=y*(1-y)
y′=y∗(1−y)
特性:
·输出值在(0,1),符合概率
·导数范围是[0,0.25],易导致梯度消失
·输出为非0均值,破坏数据分布
nn.tanh
5=2+1
ex-e-x
计算公式:
y
=
s
i
n
x
c
o
s
x
=
e
x
−
e
−
x
e
x
+
e
−
x
=
2
1
+
e
−
2
x
+
1
y=\frac{sinx}{cosx}=\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{2}{1+e^{-2x}}+1
y=cosxsinx=ex+e−xex−e−x=1+e−2x2+1
梯度公式:y’=1-y2
特性:
·输出值在(-1, 1),数据符合0均值
·导数范围是(0, 1),易导致梯度消失
nn.ReLU
计算公式:
y
=
m
a
x
(
0
,
x
)
y=max(0,x)
y=max(0,x)
梯度公式:
y
′
=
{
1
,
x
>
0
u
n
d
e
f
i
n
e
d
,
x
=
0
0
,
x
<
0
y'=\left\{\begin{matrix} 1,x>0\\ undefined,x=0\\ 0,x<0\end{matrix}\right.
y′=⎩⎨⎧1,x>0undefined,x=00,x<0
特性:
·输出值均为正数,负半轴导致死神经元
·导数是1,缓解梯度消失,但易引发梯度爆炸
其他ReLU
nn.LeakyReLU
·negative_slope:负半轴斜率
nn.PReLU
·init:可学习斜率
nn.RReLU
·lower:均匀分布下限
·upper:均匀分布上限