神经网络与深度学习——笔记2
一、图像卷积
1.单通道卷积
将
N
h
×
N
w
{N_h} \times {N_w}
Nh×Nw的单通道图像
f
(
x
,
y
)
f(x,y)
f(x,y)与
K
h
×
K
w
{K_h} \times {K_w}
Kh×Kw卷积核
g
(
x
,
y
)
g(x,y)
g(x,y)进行卷积,即
f
∗
g
(
x
,
y
)
=
∑
n
=
0
K
w
−
1
∑
m
=
0
K
h
−
1
f
(
n
,
m
)
g
(
x
−
n
,
y
−
m
)
f*g(x,y) = \sum\limits_{n = 0}^{{K_w} - 1} {\sum\limits_{m = 0}^{{K_h} - 1} {f(n,m)} } g(x - n,y - m)
f∗g(x,y)=n=0∑Kw−1m=0∑Kh−1f(n,m)g(x−n,y−m)卷积后的图像大小为
(
N
h
−
K
h
+
1
)
×
(
N
w
−
K
w
+
1
)
\left( {{N_h} - {K_h} + 1} \right) \times \left( {{N_w} - {K_w} + 1} \right)
(Nh−Kh+1)×(Nw−Kw+1),具体的卷积示例如下图所示
2.多通道卷积
对于一个彩色RGB图像(
N
h
×
N
w
×
3
{N_h} \times {N_w}\times{3}
Nh×Nw×3)具有3个输入通道,此时需要对每个输入通道进行单通道卷积。
当为单通道输出时,卷积核大小为
K
h
×
K
w
×
3
{K_h} \times {K_w}\times{3}
Kh×Kw×3,卷积后的特征图像为
f
r
∗
g
r
+
f
g
∗
g
g
+
f
b
∗
g
b
{f_r}*{g_r} + {f_g}*{g_g} + {f_b}*{g_b}
fr∗gr+fg∗gg+fb∗gb
当为多通道输出时(有
C
o
C_o
Co个输出通道),卷积核大小为
C
0
×
K
h
×
K
w
×
3
{C_0}\times{K_h} \times {K_w}\times{3}
C0×Kh×Kw×3,卷积后的特征图像为
f
r
∗
g
r
i
+
f
g
∗
g
g
i
+
f
b
∗
g
b
i
(
i
=
1
⋯
C
o
)
{f_r}*{g_r^i} + {f_g}*{g_g^i} + {f_b}*{g_b^i}(i={1\cdots{C_o}} )
fr∗gri+fg∗ggi+fb∗gbi(i=1⋯Co)多输入多输出通道卷积示意图如下所示:
卷积完成后会对每个图像再加一个偏置
b
i
b_i
bi完成输出。
前向传播为
z
[
l
]
(
x
,
y
)
=
[
∑
n
=
0
K
w
−
1
∑
m
=
0
K
h
−
1
f
(
x
+
n
,
y
+
m
)
g
r
o
t
[
l
]
,
k
(
n
,
m
)
]
+
b
k
{{\rm{z}}^{[l]}}(x,y) = [\sum\limits_{n = 0}^{{K_w} - 1} {\sum\limits_{m = 0}^{{K_h} - 1} {f(x + n,y + m)} } {g^{[l],k}_{{\rm{rot}}}}(n,m)]+b_k
z[l](x,y)=[n=0∑Kw−1m=0∑Kh−1f(x+n,y+m)grot[l],k(n,m)]+bk
a
[
l
]
(
x
,
y
)
=
f
(
z
[
l
]
(
x
,
y
)
)
{a^{[l]}}(x,y) = f({\rm{z}^{[l]}}(x,y))
a[l](x,y)=f(z[l](x,y))其中
g
r
o
t
[
l
]
,
k
(
n
,
m
)
{g^{[l],k}_{{\rm{rot}}}}(n,m)
grot[l],k(n,m)表示将第
k
k
k个卷积核沿左右上下翻转后的1结果,
f
(
⋅
)
f({ \cdot })
f(⋅)为激活函数。
3.填充和步长
填充(Padding):在输入图像的边界填充元素,通常填0或者复制边界元素,常用来保持卷积后的图像大小不变。
步长(Stride):使卷积窗口每次滑动多个元素,默认步长为1,更改步长卷积后图像的大小也会相应的发生变化。
对于一个
N
h
×
N
w
{N_h} \times {N_w}
Nh×Nw的图像,若垂直填充为
P
h
P_h
Ph,垂直步长为
S
h
S_h
Sh,水平填充为
P
w
P_w
Pw,水平步长为
S
w
S_w
Sw,则卷积后的图像大小为:
⌊
(
N
h
−
K
h
+
1
+
P
h
)
/
S
h
⌋
×
⌊
(
N
w
−
K
w
+
1
+
P
w
)
/
S
w
⌋
\left\lfloor {\left( {{N_h} - {K_h} + 1 + {P_h}} \right)/{S_h}} \right\rfloor \times \left\lfloor {\left( {{N_w} - {K_w} + 1 + {P_w}} \right)/{S_w}} \right\rfloor
⌊(Nh−Kh+1+Ph)/Sh⌋×⌊(Nw−Kw+1+Pw)/Sw⌋其中
⌊
⌋
\left\lfloor {} \right\rfloor
⌊⌋为向下取整。在Pytorch的卷积常使用
import torch
from torch import nn
conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3),stride=2, padding=(2, 1),bias=False)
输入通道数为1,输出通道数为1,使用5 × \times × 3的卷积核,垂直和水平步长均为2,垂直方向上下各填充两个元素,水平方向左右各填充一个元素,卷积后无偏置。
二、池化(pooling)
使用一个固定大小的滑窗在输入上滑动,每次将滑窗内的元素聚合为一个值作为输出,即利用局部统计特性解决特征过多的问题。
1.最大池化(Max_pooling)
以窗口内的最大值作为当前区域的输出
2.平均池化(Average pooling)
以窗口内元素的平均值作为当前区域的输出
具体的使用示例如下
同样可以使用Pytorch中的池化函数
pool2d = nn.MaxPool2d(3, padding=1, stride=2)
窗口大小为3 × \times × 3,四周各填充一个元素,步长为2,默认情况下步长与窗口大小一致。
三、LeNet
1.LeNet网络结构
LeNet的网络结构如图所示
- C1层为卷积层,将原图像通过6个5 × \times × 5的卷积核进行卷积,得到6个大小为28 × \times × 28的特征图。共有 ( 5 × 5 + 1 ) × 6 \left( {5 \times 5 + 1} \right) \times 6 (5×5+1)×6个参数
- S2层为池化层,采用平均池化,窗口大小为2 × \times × 2,步长为2,得到6个14 × \times × 14的特征图。
- C3层仍然为卷积层,采用了6个 5 × 5 × 3 5 \times 5 \times 3 5×5×3的卷积核,9个 5 × 5 × 4 5 \times 5 \times 4 5×5×4和1个 5 × 5 × 6 5 \times 5 \times 6 5×5×6的卷积核对S2得到的特征图进行卷积,得到16个10 × \times × 10的特征图。共有 ( 5 × 5 × 3 + 1 ) × 6 + ( 5 × 5 × 4 + 1 ) × 9 + ( 5 × 5 × 6 + 1 ) × 1 = 1516 \left( {5 \times 5 \times 3{\rm{ + }}1} \right) \times 6{\rm{ + }}\left( {5 \times 5 \times 4{\rm{ + }}1} \right) \times 9{\rm{ + }}\left( {5 \times 5 \times 6{\rm{ + }}1} \right) \times 1 = 1516 (5×5×3+1)×6+(5×5×4+1)×9+(5×5×6+1)×1=1516个参数。
- S4层为池化层,采用平均池化,窗口大小为2 × \times × 2,步长为2,得到16个5 × \times × 5的特征图。
- C5层为卷积层,采用了120个5 × \times × 5的卷积核,因此得到特征图大小为 1 × 1 × 120 1 \times 1 \times 120 1×1×120,构成了与S4的全连接,具有120个神经元输出。共有 ( 5 × 5 × 16 + 1 ) × 120 = 48120 \left( {5 \times 5 \times 16{\rm{ + }}1} \right) \times 120 = 48120 (5×5×16+1)×120=48120个连接数。
- F6层为具有120维输入84个神经元输出的全连接层。
- 最后一层为84维输入10个神经元输出的全连接层,最终输出为softmax分类后结果。
2.LeNet程序实现
参考李沐《动手学深度学习(第二版)》第六章LeNet部分的程序实现。
1.搭建网络结构,由两个卷积层,两个池化层,三个全连接层构成。
import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(
nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2),
nn.Flatten(),
nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
nn.Linear(120, 84), nn.Sigmoid(),
nn.Linear(84, 10))
2.设置批量大小,加载数据集
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)
3.开始训练(train_ch6()为训练函数)
lr, num_epochs = 0.9, 10
train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
程序运行结果如下