深度学习-5.卷积网络
Deep Learning - Lecture 5 Convolutional Networks
- 卷积层
- 二维卷积
- 深度网络中的卷积
- 卷积层的超参数
- 池化层
- 一个深度卷积神经网络示例
- 示例:图像分类
- 高级卷积网络设计
- 深度卷积神经网络的演变
- 深度方向池化
- Inception - GoogLeNet架构
- 残差网络
- 使用 Keras 函数式方法构建的残差网络块
- 迁移学习
- 总结
- 引用
本节目标:
- 解释深度网络中的卷积层及其超参数。
- 解释池化层。
- 设计并实现深度卷积神经网络。
卷积层
卷积神经网络是目前最成功的也是最重要的神经网络之一。尤其是在计算机视觉的方面。
(还是这张老图,展示物体识别的。)
二维卷积
深度卷积神经网络(DCNNs)是最受欢迎的深度网络类型之一,适合处理类似网格的数据。因为卷积层在计算上比全连接层更高效,其参数要少得多。
卷积网络中使用滤波器(filter)作为传统意义上的权重。
基本的二维卷积操作,即使用具有权重 w m , n w_{m,n} wm,n的二维滤波器(或内核)对具有元素 x i , j x_{i,j} xi,j的二维输入(加上偏置 b b b)进行卷积。二维卷积的公式为 z i , j = ∑ m ∑ n w m , n x i + m , j + n + b z_{i,j}=\sum_{m}\sum_{n}w_{m,n}x_{i + m,j + n}+b zi,j=m∑n∑wm,nxi+m,j+n+b
深度网络中的卷积
公式:深度网络中第 l l l层单个卷积层输出的计算公式: z i , j , k ( l ) = ∑ c ∑ m ∑ n w m , n , c , k ( l ) x i + m , j + n , c ( l − 1 ) + b k ( l ) z_{i,j,k}^{(l)}=\sum_{c}\sum_{m}\sum_{n}w_{m,n,c,k}^{(l)}x_{i + m,j + n,c}^{(l - 1)}+b_{k}^{(l)} zi,j,k(l)=c∑m∑n∑wm,n,c,k(l)xi+m,j+n,c(l−1)+bk(l)其中, m m m和 n n n是卷积滤波器行和列的索引, c c c是输入特征深度/卷积滤波器深度的索引, k = 1 , … , N F k = 1, \ldots, N_F k=1,…,NF是卷积滤波器数量的索引。
下图是一个示例,:输入特征图尺寸为
7
×
7
×
3
7\times7\times3
7×7×3,卷积滤波器(convolution filters)的尺寸为
3
×
3
×
3
×
2
3\times3\times3\times2
3×3×3×2,(步长是221,图中没有给出,但是简单推算即可)得到的输出特征图的得到尺寸为
3
×
3
×
2
3\times3\times2
3×3×2
详细计算过程(外网网址):斯坦福大学CS231n课程
在上图可以看到:输入集的周围填充了一圈0,其主要作用是保证特征图的尺寸,和防止边缘信息丢失。
卷积层的超参数
卷积网络有许多不同超参数,需由用户调整。
1. Filter size(滤波器大小):表示为
F
S
×
F
S
F_S \times F_S
FS×FS,假设高度和宽度相同,即
W
F
=
H
F
=
F
S
W_F = H_F = F_S
WF=HF=FS 。
2. Number of filters(滤波器数量):用
N
F
N_F
NF表示,指每层中滤波器的数量。
3. Stride(步长):用
N
S
N_S
NS表示,是滤波器在输入上滑动时的离散跳跃数。
4. Padding(填充):用
N
P
N_P
NP表示,指在输入周围引入的零填充量。
上图展示了对于输入特征图的零填充,零填充操作可用于防止每层的输出缩小。
-
在卷积神经网络中,进行卷积操作时,如果不进行填充(padding),随着卷积核在输入特征图上滑动,输出特征图的尺寸会变小。
-
例如,对于一个大小为 W I × H I W_I \times H_I WI×HI(宽度×高度)的输入特征图,使用大小为 F S × F S F_S \times F_S FS×FS的卷积核,步长为 N S N_S NS,在不填充的情况下,输出特征图的宽度 W O W_O WO和高度 H O H_O HO的计算公式为 W O = ( W I − F S ) / N S + 1 H O = ( H I − F S ) / N S + 1 W_O=(W_I - F_S)/N_S + 1\\H_O=(H_I - F_S)/N_S + 1 WO=(WI−FS)/NS+1HO=(HI−FS)/NS+1(这里假设整除情况,若不能整除会涉及向下取整等操作)。可以看到,输出尺寸相对于输入尺寸是减小的。
-
而当引入零填充,即在输入特征图周围填充 N P N_P NP圈0后,输出特征图的宽度与高度变为 W O = ( W I − F S + 2 N P ) / N S + 1 H O = ( H I − F S + 2 N P ) / N S + 1 W_O = (W_I - F_S + 2N_P)/N_S + 1\\H_O = (H_I - F_S + 2N_P)/N_S + 1 WO=(WI−FS+2NP)/NS+1HO=(HI−FS+2NP)/NS+1 。通过合理设置 N P N_P NP的值,就可以使输出特征图的尺寸与输入特征图尺寸相同或为期望的尺寸,从而达到防止输出缩小的目的。
-
在DF = D1的前提下, D O = N F D_O = N_F DO=NF 。
是因为每个滤波器在卷积操作时,会对输入特征图进行处理,生成一个对应的特征图。也就是说,每一个滤波器都会产生一个输出通道(Output channel)。有多少个滤波器,最终就会有多少个输出通道,而输出特征图的深度本质上就是输出通道的数量。所以,输出特征图的深度 D O D_O DO 就等于滤波器的数量 N F N_F NF 。
池化层
- 池化会减小特征图的尺寸,从而降低计算复杂度,并使输出对输入中的小幅度平移更具鲁棒性。
- 池化操作是用附近输出的统计量来替换输出。
- 两种常见的池化操作,即最大池化(Max pooling)和平均池化(Average pooling)。
- 下图为示例,不过需要注意:池化操作会将 4×4 的输入特征图缩小为 2×2 的输出特征图。
一个深度卷积神经网络示例
深度卷积神经网络将卷积层与激活函数及其他层相结合
训练卷积网络
- 损失函数:通常为均方误差(squared error)或分类交叉熵(categorical cross - entropy)。
- 参数估计算法:采用随机梯度下降(stochastic gradient descent)或其变体(如Adam算法),参数更新公式为 θ ← θ − ϵ g \theta \leftarrow \theta - \epsilon g θ←θ−ϵg 。
- 损失函数梯度:通过自动微分获得, g ≈ ∇ θ J ( θ ) g \approx \nabla_{\theta}J(\theta) g≈∇θJ(θ) 。
简单的卷积网络结构示意图
- 图像输入层(Image input layer):输入图像 x x x 。
- 二维卷积层(Convolution 2D layer):计算公式为 z i , j , k ( l ) = ∑ c ∑ m ∑ n w m , n , c , k ( l ) x i + m , j + n , c ( l − 1 ) + b k ( l ) z_{i,j,k}^{(l)}=\sum_{c}\sum_{m}\sum_{n}w_{m,n,c,k}^{(l)}x_{i + m,j + n,c}^{(l - 1)}+b_{k}^{(l)} zi,j,k(l)=∑c∑m∑nwm,n,c,k(l)xi+m,j+n,c(l−1)+bk(l) 。
- 批量归一化层(Batch Normalisation):计算公式为 z ~ i , j , k ( l ) = γ z ~ i , j , k ( l ) + β \tilde{z}_{i,j,k}^{(l)}=\gamma\tilde{z}_{i,j,k}^{(l)}+\beta z~i,j,k(l)=γz~i,j,k(l)+β 。
- ReLU激活函数层(ReLU):计算公式为 x i , j , k ( l ) = h ( z i , j , k ( l ) ) = max ( z ~ i , j , k ( l ) , 0 ) x_{i,j,k}^{(l)}=h(z_{i,j,k}^{(l)})=\max(\tilde{z}_{i,j,k}^{(l)},0) xi,j,k(l)=h(zi,j,k(l))=max(z~i,j,k(l),0) 。
- 最大池化层(Max Pooling 2D) 。如上介绍的,最大或平均。
- 二维卷积层(Convolution 2D layer) 。同上。
- 批量归一化层(Batch Normalisation) 。同上。
- ReLU激活函数层(ReLU) 。同上。
- 全连接层(Fully Connected layer(5)):计算公式为 z j ( l ) = ∑ i = 1 N l w j i ( l ) x i ( l − 1 ) + b j ( l ) z_{j}^{(l)}=\sum_{i = 1}^{N_{l}}w_{ji}^{(l)}x_{i}^{(l - 1)}+b_{j}^{(l)} zj(l)=∑i=1Nlwji(l)xi(l−1)+bj(l) 。
- Softmax层(Softmax layer):计算公式为 y ^ j = exp ( z j ( l ) ) ∑ k = 1 K exp ( z j ( l ) ) \hat{y}_{j}=\frac{\exp(z_{j}^{(l)})}{\sum_{k = 1}^{K}\exp(z_{j}^{(l)})} y^j=∑k=1Kexp(zj(l))exp(zj(l)) 。
Matlab示例代码
filterSize = 3;
numFilters = 16;
%% define model layers
layers = [
imageInputLayer([28 28 1])
convolution2dLayer(filterSize,numFilters,'Padding','same')
batchNormalizationLayer
reluLayer
maxPooling2dLayer(2,'Stride',2)
convolution2dLayer(filterSize,numFilters,'Padding','same')
batchNormalizationLayer
reluLayer
fullyConnectedLayer(10)
softmaxLayer
classificationLayer];
Python示例代码(使用Keras - TensorFlow在Python中定义卷积网络层。)
numFilters = 16
# define model layers
model = tf.keras.Sequential()
model.add(tf.keras.Input(shape=(28,28,1)))
model.add(tf.keras.layers.Conv2D(numFilters, kernel_size =(3, 3), padding='same'))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size =(2, 2),
strides=(2, 2), padding= 'same'))
model.add(tf.keras.layers.Conv2D(numFilters, kernel_size =(3, 3), padding='same'))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(10))
model.add(tf.keras.layers.Softmax())
示例:图像分类
高级卷积网络设计
深度卷积神经网络的演变
卷积网络设计演变的关键步骤
- ZFNet和VGGNet中的小滤波器:例如使用3×3的滤波器而非11×11的滤波器。
- GoogleNet(Inception)中使用1×1卷积的并行滤波器和深度控制。
- ResNet中用于极深层网络的跳跃连接。
ILSVRC(ImageNet 大规模视觉识别挑战赛)的获胜者凸显了深度网络设计方面的改进,这些改进带来了显著的准确率提升。
不同网络对比表格
- AlexNet:2012年参赛,是第一个重要的深度卷积神经网络(DCNN),有8层,Top - 5准确率为84.69%,参数数量为6200万。
- ZFNet:2013年参赛,特点是使用了更小的滤波器,同样8层,Top - 5准确率提升到88.80%,参数数量为4300万。
- VGGNet:2014年获得第二名,使用固定大小的滤波器,有19层,Top - 5准确率达到92.68%,参数数量为1.38亿。
- GoogleNet:2014年获得第一名,特点是并行滤波器,有22层,Top - 5准确率为93.34%,参数数量相对较少,为680万。
- ResNet - 152:2015年参赛,具有跳跃连接,有152层,Top - 5准确率高达96.43%,参数数量为6030万。通过这些对比,展示了随着时间推移,卷积神经网络在结构设计和性能上的不断进步 。
深度方向池化
使用1×1卷积的深度方向池化,1×1滤波器用于控制输出激活图的深度,滤波器的数量决定了输出深度。
示意图
- 输入通道图:尺寸为224×224,深度为512 。
- 1×1滤波器:尺寸为1×1,数量为1×1×512×d(d是滤波器的数量也是输出深度),对输入通道图进行卷积操作。
- 输出激活图:尺寸同样为224×224,其深度d由1×1滤波器的数量控制。
- 深度控制用于控制计算复杂度,即通过调整1×1滤波器的数量来调节输出激活图的深度,进而控制卷积操作中的计算量 。
Inception - GoogLeNet架构
Inception架构支持使用不同大小的卷积滤波器进行并行处理,旨在处理不同尺寸的特征。
- 简单版本(计算复杂度高):从前一层(Previous Layer)出发,分别经过1×1卷积、3×3卷积、5×5卷积和3×3最大池化,然后将结果进行滤波器拼接(Filter Concatenation)。
- 改进计算效率版本(带有1×1深度控制):在前一层和3×3卷积、5×5卷积之间加入了1×1卷积,用于控制深度,降低计算复杂度,同样最后将各部分结果进行滤波器拼接。
残差网络
残差网络(Resnets),即通过跳跃连接进行残差学习。
跳跃连接(Skip connections)可以跨层传输值,这有助于防止梯度消失问题,并使得构建更深的网络成为可能。带有跳跃连接的层被称为残差层(residual layers)。
数学原理
假设要学习的函数为
y
=
F
(
x
)
+
x
y = F(x) + x
y=F(x)+x ,经过变换可得
F
(
x
)
=
y
−
x
F(x) = y - x
F(x)=y−x ,因此
F
(
x
)
F(x)
F(x) 是
y
y
y 和
x
x
x 之间的残差。权重层尝试学习残差
F
(
x
)
F(x)
F(x) 。还引用了观点“”。
(我们假设优化残差映射比优化原始的、无参考的映射更容易。)
结构示意图
输入
x
x
x 经过一个由二维卷积(Convolution 2D)、ReLU激活函数和另一个二维卷积组成的
F
(
x
)
F(x)
F(x) 路径.
同时
x
x
x 通过跳跃连接直接与
F
(
x
)
F(x)
F(x) 的输出相加,得到
y
=
F
(
x
)
+
x
y = F(x) + x
y=F(x)+x 。
使用 Keras 函数式方法构建的残差网络块
网络结构图
Python示例代码
import keras
from keras import layers
# define number of filters and kernel size
numfilters = 256
kernelsize = (3, 3)
# input
x = keras.Input(shape=(32,32,1))
# resnet block
fx = layers.Conv2D(numfilters, kernelsize, padding='same')(x)
fx = layers.BatchNormalization()(fx)
fx = keras.activations.relu(fx)
fx = layers.Conv2D(numfilters, kernelsize, padding='same')(fx)
x = layers.Add()([x,fx])
x = layers.ReLU()(x)
# output layer: dense -> softmax
x = keras.layers.Dense(32, activation="relu")(x)
yhat = keras.layers.Dense(5, activation="softmax")(x)
model = keras.Model(inputs=x, outputs=yhat)
model.summary()
迁移学习
迁移学习是指采用一个预训练的深度网络,如 VGG、GoogleNet、Mobilenet 等,并根据你的任务替换其最后几层。通常比从头开始训练一个网络更快,且所需数据更少。
迁移学习步骤
- 加载预训练网络:获取已经在大规模数据集上训练好的网络模型。
- 替换最后几层:将预训练网络的最后几层替换为适合特定任务的层。
- 重新训练层:
- 通常只需训练新的最后几层,保持预训练层固定。
- 也可以重新训练所有层,但这样速度较慢。
Matlab示例代码
% load a pretrained network - e.g. googlenet
net = googlenet;
lgraph = layerGraph(net); % convert to layer graph
% find fully connected output layer to replace
[learnableLayer,classLayer] = findLayersToReplace(lgraph);
% define new fully connected output layer
newLayer = fullyConnectedLayer(numClasses, 'Name','new_fc');
% replace fully connected output layer
lgraph = replaceLayer(lgraph,learnableLayer.Name,newLayer);
% replace the classification output layer
newClassLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,classLayer.Name,newClassLayer);
% optionally - freeze initial layers to prevent retraining them
layers = lgraph.Layers;
connections = lgraph.Connections;
layers(1:10) = freezeWeights(layers(1:10));
lgraph = createLgraphUsingConnections(layers,connections);
% now train the network as usual - pass in the layer graph
net = trainNetwork(imdsTrain,lgraph,options);
Python示例代码
首先,你要确认安装了Keras_cv。
!pip install --upgrade keras-cv tensorflow
!pip install --upgrade keras
之后,加载一个预训练的ResNet50模型,并将其定义为适用于2个类别的模型,为重新训练做好准备。
import keras
import keras_cv
# Pretrained Resnet50 model
model = keras_cv.models.ImageClassifier.from_preset(
"resnet50_v2_imagenet", num_classes=2
)
# compile the model
model.compile(
loss="categorical_crossentropy",
optimizer=keras.optimizers.SGD(learning_rate=0.01),
metrics=["accuracy"],
)
总结
- 应用场景:卷积网络用于处理具有网格状结构的数据,如时间序列、图像和视频。
- 卷积层优势:卷积层在计算效率上比全连接层高得多,具体体现在:
- 参数更少:相较于全连接层,卷积层所需的参数数量更少。
- 参数共享:卷积层中参数是共享的,这减少了计算量和模型的参数量。
- 卷积网络特性:卷积网络的先进特性使其在计算上更高效,并且能够构建得更深。这些特性帮助卷积网络在处理相关数据时表现出色,在诸多领域得到广泛应用 。
引用
- (斯坦福大学CS231n课程“Convolutional Neural Networks for Visual Recognition”)https://cs231n.github.io/convolutional - networks/
- (Inception - GoogLeNet架构)Szegedy, C., Liu, W., Jia, Y., Sermanet, P., Reed, S., Anguelov, D., … &
Rabinovich, A. (2015). Going deeper with convolutions. In Proceedings of the
IEEE conference on Computer Vision and Pattern Recognition (pp. 1-9). - (残差网络)He, Kaiming, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. “Deep residual learning for image recognition.” IEEE CVPR, pp. 770-778. 2016.
- (迁移学习)https://keras.io/api/keras_cv/models/tasks/image_classifier/