其实,卷积网络我们已经见过并使用过了,在第1课介绍机器学习项目实战架构时,我特别给出了一个通过卷积网络识别MNIST图像的例子,一是因为想强调它作为常用深度网络的重要性,二是因为它的结构并不复杂。
复习一下该程序的完整代码,并通过model.summary方法显示网络的结构:
from keras import models # 导入Keras模型和各种神经网络的层
from keras.layers import Dense, Dropout, Flatten, Conv2D, Max Pooling2D
model = models.Sequential() # 序贯模型
model.add(Conv2D(filters=32, # 添加Conv2D层, 指定过滤器的个数, 即通道数
kernel_size=(3, 3), # 指定卷积核的大小
activation='relu', # 指定激活函数
input_shape=(28, 28, 1))) # 指定输入数据样本张量的类型
model.add(Max Pooling2D(pool_size=(2, 2))) # 添加Max Pooling2D层
model.add(Conv2D(64, (3, 3), activation='relu')) # 添加Conv2D层
model.add(Max Pooling2D(pool_size=(2, 2))) # 添加Max Pooling2D层
model.add(Dropout(0.25)) # 添加Dropout层
model.add(Flatten()) # 添加展平层
model.add(Dense(128, activation='relu')) # 添加全连接层
model.add(Dropout(0.5)) # 添加Dropout层
model.add(Dense(10, activation='softmax')) # Softmax分类激活, 输出10维分类码
model.compile(optimizer='rmsprop', # 指定优化器
loss='categorical_crossentropy', # 指定损失函数
metrics=['accuracy']) # 指定评估指标
model.summary() # 显示网络模型
运行代码,输出网络结构如下:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
max_pooling2d_1 (Max Pooling2 (None, 13, 13, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 11, 11, 64) 18496
_________________________________________________________________
max_pooling2d_2 (Max Pooling2 (None, 5, 5, 64) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 1600) 0
_________________________________________________________________
dense_1 (Dense) (None, 128) 204928
_________________________________________________________________
dense_2 (Dense) (None, 10) 1290
=================================================================
Total params: 225, 034
Trainable params: 225, 034
Non-trainable params: 0
还可以用下页图形的方式显示出这个有225 034个参数、用序贯方式生成的卷积网络的形状:
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
SVG(model_to_dot(ann, show_shapes = True ).create(prog='dot', format='svg'))
程序编译出来的卷积网络的结构信息
下图更直观地显示了卷积网络的典型架构。它实现了一个图像分类功能:输入的是图像,输出的是图像的类别标签。
卷积网络的典型架构
卷积网络也是多层的神经网络,但是层内和层间神经元的类型和连接方式与普通神经网络不同。卷积神经网络由输入层、一个或多个卷积层和输出层的全连接层组成。
(1)网络左边仍然是数据输入部分,对数据做一些初始处理,如标准化、图片压缩、降维等工作,最后输入数据集的形状为 (样本,图像高度,图像宽度,颜色深度)。
(2)中间是卷积层,这一层中,也有激活函数的存在,示例中用的是Re LU。
(3)一般卷积层之后接一个池化层,池化层包括区域平均池化或最大池化。
(4)通常卷积+池化的架构会重复几次,形成深度卷积网络。在这个过程中,图片特征张量的尺寸通常会逐渐减小,而深度将逐渐加深。如上一张图所示,特征图从一张扁扁的纸片形状变成了胖胖的矩形。
(5)之后是一个展平层,用于将网络展平。
(6)展平之后接一个普通的全连接层。
(7)最右边的输出层也是全连接层,用Softmax进行激活分类输出层,这与普通神经网络的做法一致。
(8)在编译网络时,使用了Adam优化器,以分类交叉熵作为损失函数,采用了准确率作为评估指标。
卷积网络的核心特点就是卷积+池化的架构,要注意到“卷积层”中的参数,其实是远少于全连接层的(本例中两个卷积层中的参数加起来不到2万个,而全连接层则贡献了其他20多万个参数)。这是因为,卷积网络中各层的神经元之间,包括输入层的特征和卷积层之间,不是彼此全部连接的,而是以卷积的方式有选择性的局部连接,如下图所示。这种结构除了能大大减少参数的数量之外,还有其他一些特殊优势。下面讲一讲这其中的道理。
全连接和局部连接的示意