LeNet神经网络

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

1. LeNet神经网络介绍

LeNet神经网络由深度学习三巨头之一的Yan LeCun提出,他同时也是卷积神经网络 (CNN,Convolutional Neural Networks)之父。LeNet主要用来进行手写字符的识别与分类,并在美国的银行中投入了使用。LeNet的实现确立了CNN的结构,现在神经网络中的许多内容在LeNet的网络结构中都能看到,例如卷积层,Pooling层,ReLU层。虽然LeNet早在20世纪90年代就已经提出了,但由于当时缺乏大规模的训练数据,计算机硬件的性能也较低,因此LeNet神经网络在处理复杂问题时效果并不理想。虽然LeNet网络结构比较简单,但是刚好适合神经网络的入门学习。

2. LeNet神经网络结构

LeNet的神经网络结构图如下:

LeNet网络图

LeNet网络的执行流程图如下:

LeNet图像处理流程

2.1 LeNet第一层(卷积运算)

接下来我们来具体的一层层的分析LeNet的网络结构。首先要了解图像(输入数据)的表示。在LeNet网络中,输入图像是手写字符,图像的表示形式为二维数据矩阵,如下图所示:

图像的表示

LeNet网络除去输入输出层总共有六层网络。第一层是卷积层(C1层),卷积核的大小为5\*5,卷积核数量为6个,输入图像的大小为32*32,因此输入数据在进行第一层卷积之后,输出结果为大小为28*28,数量为6个的feature map。卷积操作如下面两幅图所示:

卷积演示

卷积演示

卷积操作的过程可描述为:卷积核在图像上滑动,滑动步长为1(即每次移动一格,水平方向从左到右,到最右边之后再从最左边开始,向下移动一格,重复从左到右滑动),当卷积核与图像的一个局部块重合时进行卷积运行,卷积计算方式为图像块对应位置的数与卷积核对应位置的数相乘,然后将所有相乘结果相加即为feature map的值,相乘累加之后的结果位于卷积核中心点的位置,因此如果是3\*3的卷积核,feature map比原图像在水平和垂直方向上分别减少两行(上下各一行)和两列(左右各一列),因此上面图像原图为5*5,卷积核为3\*3,卷积结果大小为3*3,即(5-2)*(5-2),如果卷积核为5*5,则卷积结果大小为(5-4)*(5-4)。上图中的卷积核为:
卷积核

由于神经网络层与层的结构是通过连接来实现的,因此输入层与第一个卷积层的连接数量应为(32-2-2)\*(32-2-2)\*(5\*5+1)\*6= 28\*28\*156 =122304

卷积的作用主要是:通过卷积运算,可以使原信号特征增强,并且降低噪音。在图像上卷积之后主要是减少图像噪声,提取图像的特征。例如sobel算子就是一种卷积运算,主要是提取图像的边缘特征。卷积网络能很好地适应图像的平移不变性:例如稍稍移动一幅猫的图像,它仍然是一幅猫的图像。卷积操作保留了图像块之间的空间信息,进行卷积操作的图像块之间的相对位置关系没有改变。图像在不同卷积核上进行卷积之后的效果图如下:

同一幅图像用不同卷积核处理的效果

2.2 LeNet第二层(pooling运算)

图像在LeNet网络上进行第一层卷积之后,结果为大小为28*28,数量为6个的feature map。LeNet网络的第二层为pooling层(S2层),也称为下采样。在图像处理中,下采样之后,图像的大小会变为原来的1/4,即水平方向和垂直方向上图像大小分别减半。Pooling有多种,这里主要介绍两种,max-pooling和average-pooling。max-pooling即为从四个元素中选取一个最大的来表示这四个元素,average-pooling则用四个元素的平均值来表示这四个元素。Pooling示意图如下:

Pooling示意图

Pooling示意图

在LeNet在进行第二层Pooling运算后,输出结果为14*146个feature map。其连接数为(2*2+1) * 14 * 14 *6 = 5880。Pooling层的主要作用就是减少数据,降低数据纬度的同时保留最重要的信息。在数据减少后,可以减少神经网络的纬度和计算量,可以防止参数太多过拟合。LeNet在这一层是将四个元素相加,然后乘以参数w再加上偏置b,然后计算sigmoid值。

2.3 LeNet第三层(卷积运算)

LeNet第三层(C3层)也是卷积层,卷积核大小仍为5*5,不过卷积核的数量变为16个。第三层的输入为14*146个feature map,卷积核大小为5*5,因此卷积之后输出的feature map大小为10*10,由于卷积核有16个,因此希望输出的feature map也为16个,但由于输入有6个feature map,因此需要进行额外的处理。输入的6个feature map与输出的16个feature map的关系图如下:

S2层与C3层的关系图

如上图所示,第一个卷积核处理前三幅输入的feature map,得出一个新的feature map。

2.4 LeNet第四层(Pooling运算)

上一层卷积运算之后,结果为大小为10*1016个feature map,因此在第四层(S4层)进行pooling运算之后,输出结果为16个大小为5*5的feature map。与S2层进行同样的操作。

2.5 LeNet第五层

LeNet第五层是卷积层(C5层),卷积核数目为120个,大小为5*5,由于第四层输出的feature map大小为5*5,因此第五层也可以看成全连接层,输出为120个大小为1*1的feature map。

2.6 LeNet第六层

LeNet第六层是全连接层(F6层),有84个神经元(84与输出层的设计有关),与C5层全连接。

2.7 LeNet各层的参数变化

  • C1
    输入大小:32*32
    核大小:5*5
    核数目:6
    输出大小:28*28*6
    训练参数数目:(5*5+1)*6=156
    连接数:(5*5+1)*6*(32-2-2)*(32-2-2)=122304

  • S2
    输入大小:28*28*6
    核大小:2*2
    核数目:1
    输出大小:14*14*6
    训练参数数目:2*6=12,2=(w,b)
    连接数:(2*2+1)*1*14*14*6 = 5880

  • C3
    输入大小:14*14*6
    核大小:5*5
    核数目:16
    输出大小:10*10*16
    训练参数数目:6*(3*5*5+1) + 6*(4*5*5+1) + 3*(4*5*5+1) + 1*(6*5*5+1)=1516
    连接数:(6*(3*5*5+1) + 6*(4*5*5+1) + 3*(4*5*5+1) + 1*(6*5*5+1))*10*10=151600

  • S4
    输入大小:10*10*16
    核大小:2*2
    核数目:1
    输出大小:5*5*16
    训练参数数目:2*16=32
    连接数:(2*2+1)*1*5*5*16=2000

  • C5
    输入大小:5*5*16
    核大小:5*5
    核数目:120
    输出大小:120*1*1
    训练参数数目:(5*5*16+1)*120*1*1=48120(因为是全连接)
    连接数:(5*5*16+1)*120*1*1=48120

  • F6
    输入大小:120
    输出大小:84
    训练参数数目:(120+1)*84=10164
    连接数:(120+1)*84=10164

3. LeNet在Caffe中的配置

LeNet神经网络结构在Caffe中的配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
name: "LeNet"
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_train_lmdb"
batch_size: 64
backend: LMDB
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "examples/mnist/mnist_test_lmdb"
batch_size: 100
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 50
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: MAX
kernel_size: 2
stride: 2
}
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool2"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "accuracy"
type: "Accuracy"
bottom: "ip2"
bottom: "label"
top: "accuracy"
include {
phase: TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
top: "loss"
}

参考资料:

1.https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/

如果有收获,可以请我喝杯咖啡!