ML&DL - TensorFlow2.1快速入门学习笔记05——卷积神经网络

ML&DL - TensorFlow2.1快速入门学习笔记05——卷积神经网络

  • 第五讲 卷积神经网络
    • 5.1 卷积计算过程
    • 5.2 感受野
    • 5.3 全零填充
    • 5.4 TensorFlow实现卷积计算层
    • 5.5 批标准化 (Batch Normalization, BN)
    • 5.6 池化
    • 5.7 舍弃 Dropout
    • 5.8 卷积神经网络
      • 卷积是什么?
    • 5.9 CIFAR10数据集
    • 5.10 卷积神经网络搭建示例
    • 5.11 LeNet、AlexNet、VGGNet、InceptionNet、ResNet
      • LeNet
      • AlexNet
      • VGGNet
      • InceptionNet
        • Inception结构块
        • 搭建一个精简的 InceptionNet
      • ResNet
        • 跳跃连接 与 ResNet 结构块
        • 跳跃连接的两种方式
        • 搭建 ResNet-18
    • 5.12 经典卷积神经网络小结
  • Reference



第五讲 卷积神经网络

前几讲,使用 “六步法” 搭建了全连接网络,实现了图像识别应用。实践证明,全连接网络对于识别和预测任务都有很好的效果。
卷积神经网络与全连接神经网络的唯一区别就在于神经网络中相邻两层的连接方式。

全连接网络参数个数: ∑ 层 数 [ ( 前 层 ∗ 后 层 ) w + ( 后 层 ) b ] \sum_{层数}[(前层*后层)_w+(后层)_b] [()w+()b]

在这里插入图片描述
针对MNIST数据集的分辨率仅为 28 ∗ 28 28*28 2828 的黑白图像 两层神经网络就包含了 101, 770 个参数。在实际应用中,图像的分辨率远高于此,且大多数是彩色图像,如下图所示。

在这里插入图片描述
虽然全连接网络一般被认为是分类预测的最佳网络,但待优化的参数过多,容易导致模型过拟合。 为了解决参数量过大而导致模型过拟合的问题,一般不会将原始图像直接输入,而是先对图像进行特征提取再将提取到的特征输入全连接网络。如下图所示,就是将汽车图片经过多次特征提取后再输入全连接网络。


5.1 卷积计算过程

卷积计算可认为是一种有效提取图像特征的方法。

  • 一般会用一个正方形的卷积核,按指定步长,在输入特征图上滑动,遍历输入特征图中的每个像素点。每一个步长,卷积核会与输入特征图出现重合区域,重合区域对应元素相乘、求和再加上偏置项得到输出特征的一个像素点。

    • 对于单通道图像(灰度图),使用 3 ∗ 3 ∗ 1 3*3*1 331 5 ∗ 5 ∗ 1 5*5*1 551 的卷积核;
    • 对于RGB三通道图像,使用 3 ∗ 3 ∗ 3 3*3*3 333 5 ∗ 5 ∗ 3 5*5*3 553 的卷积核;
    • 对于隐含层中深度为n的特征图,使用 3 ∗ 3 ∗ n 3*3*n 33n 5 ∗ 5 ∗ n 5*5*n 55n 的卷积核。
  • 卷积核的深度必须与输入层的通道数一致,所以输入特征图的深度(channel数)决定了当前层卷积核的深度 n n n
    每个卷积核在卷积计算后,会得到一层输出特征图,所以当前层卷积核的个数决定了当前层输出特征图的深度。
    所以一般只需要指定卷积核的尺寸 3 ∗ 3 3*3 33 5 ∗ 5 5*5 55卷积核的个数 (即输出层特征图的深度)。

  • 所以如果觉得某层模型的特征提取能力不足,可以适当增加该层的卷积核个数,以提高特征提取能力。

卷积核中的参数数量计算如下图所示:
这些参数的更新过程与全连接神经网络一致,同样使用梯度下降法进行参数更新。

在这里插入图片描述
单通道卷积核 3 ∗ 3 ∗ 1 3*3*1 331 的计算过程:

在这里插入图片描述
多通道卷积核 3 ∗ 3 ∗ 3 3*3*3 333 3 ∗ 3 ∗ n 3*3*n 33n 的计算过程:

在这里插入图片描述
卷积核移动计算过程: 当卷积核遍历完成输入特征图后,就得到了一张输出特征图,完成了一个卷积核的卷积计算过程。当有n个卷积核时,就会有n张输入特征图依次叠加。
在这里插入图片描述


5.2 感受野

感受野(Receptive Field): 卷积神经网络各输出特征图中的每个像素点,在原始输入图片上映射区域的大小。

如下图所示,对于一幅 5 ∗ 5 5*5 55 的原始输入图像,经过两层 3 ∗ 3 3*3 33 卷积核作用,和经过一层 5 ∗ 5 5*5 55 的卷积核作用,都得到一个感受野是 5 5 5 的输出特征图。所以这两层 3 ∗ 3 3*3 33 卷积核和一层 5 ∗ 5 5*5 55 的卷积核的特征提取能力是一样的。

在这里插入图片描述
那么,是选择两层 3 ∗ 3 3*3 33 卷积核好?还是选择一层 5 ∗ 5 5*5 55 的卷积核好呢?这时就要考虑他们所承载的参数量和计算量了。

  • 例: 对于使用两个 3 ∗ 3 3*3 33 卷积核,在第一层网络中,卷积核需要移动 ( x − 2 ) 2 (x-2)^2 (x2)2 次,在第二层网络中,卷积核需要移动 ( x − 4 ) 2 (x-4)^2 (x4)2 次,即两个 3 ∗ 3 3*3 33 卷积核总共需要进行 ( x − 2 ) 2 + ( x − 4 ) 2 = 2 x 2 − 12 x + 20 (x-2)^2+(x-4)^2=2x^2-12x+20 (x2)2+(x4)2=2x212x+20 次卷积运算。每次卷积运算需要进行 3 ∗ 3 = 9 3*3=9 33=9 次乘加运算。所以使用两个 3 ∗ 3 3*3 33 卷积核共需要进行 18 x 2 − 108 x + 180 18x^2-108x+180 18x2108x+180 次乘加运算。

在这里插入图片描述


5.3 全零填充

在上一节中介绍时,使用尺寸为 n ∗ n n*n nn 的卷积核,输出特征图的尺寸相比输入特征图的尺寸,减小了 n − 1 n-1 n1 。但是有时候,我们希望卷积计算能够使得输入输出特征图的尺寸保持不变。这就需要用到全零填充
全零填充(padding): 为了保持输出图像尺寸与输入图像一致, 经常会在输入图像周围进行全零填充,如下图所示,在 5 × 5 5×5 5×5 的输入图像周围填 0,则输出特征尺寸同为 5 × 5 5×5 5×5

在这里插入图片描述
卷积输出特征图维度计算: p a d d i n g = { S A M E ( 使 用 全 0 填 充 ) 输 入 特 征 图 边 长 步 长 ( 向 上 取 整 ) V A L I D ( 不 使 用 全 0 填 充 ) 输 入 特 征 图 边 长 − ( 卷 积 核 边 长 − 1 ) 步 长 ( 向 上 取 整 ) padding=\begin{cases} SAME (使用全0填充) & \frac{输入特征图边长}{步长} & (向上取整) \\ \\ VALID (不使用全0填充) & \frac{输入特征图边长-(卷积核边长-1)}{步长} & (向上取整) \end{cases} padding=SAME(使0)VALID(使0)(1)()()

在这里插入图片描述
TensorFlow描述全零填充: 用参数padding = ‘SAME’ 或 padding = ‘VALID’表示。


5.4 TensorFlow实现卷积计算层

Tensorflow给出了计算卷积的函数:

	tf.keras.layers.Conv2D (filters = 卷积核个数,  # 即卷积层输出特征图深度
							kernel_size = 卷积核尺寸,  # 正方形写核长整数,或(核高h,核宽w)
							strides = 滑动步长,  # 横纵向相同写步长整数,或(纵向步长h,横向步长w),默认1
							padding = “same” or “valid”, # 使用全零填充是“same”, 不使用是“valid”(默认“valid”)
							activation = “ relu ” or “ sigmoid ” or “ tanh ” or “ softmax”等,  # 如果在该层之后使用了BN,则此处不使用激活函数
							input_shape = (,, 通道数) #输入特征图维度,可省略
							)

举个栗子:

	model = tf.keras.models.Sequential([
			Conv2D(6, 5, padding='valid', activation='sigmoid'),
			MaxPool2D(2, 2),
			Conv2D(6, (5, 5), padding='valid', activation='sigmoid'),
			MaxPool2D(2, (2, 2)),
			Conv2D(filters=6, kernel_size=(5, 5),padding='valid', activation='sigmoid'),
			MaxPool2D(pool_size=(2, 2), strides=2),
			Flatten(),
			Dense(10, activation='softmax')
			])

5.5 批标准化 (Batch Normalization, BN)

神经网络对0附近的数据更敏感。但是随着网络层数的增加,特征数据会出现偏离0均值的情况。

  • 标准化 (Normalization):可以使数据符合以0为均值,1为标准差的标准正态分布。将偏移的特征数据重新拉回到0附近。
  • 批标准化 (Batch Normalization, BN):对一小批数据(batch),做标准化处理 。常用在卷积操作和激活操作之间。

批标准化后,第 k k k 个卷积核的输出特征图(feature map)中第 i i i 个像素点的值: H i ′ k = H i k − μ b a t c h k σ b a t c h k H_i'^k=\frac{H_i^k-\mu_{batch}^k}{\sigma_{batch}^k} Hik=σbatchkHikμbatchk其中, H i k H_i^k Hik表示批标准化前,第 k 个卷积核,输出特征图中第 i i i 个像素点的值; μ b a t c h k = 1 m ∑ i = 1 m H i k \mu_{batch}^k=\frac{1}{m}\sum_{i=1}^mH_i^k μbatchk=m1i=1mHik表示批标准化前,第k个卷积核, batch张输出特征图中所有像素点平均值; σ b a t c h k = δ + 1 m ∑ i = 1 m ( H i k − μ b a t c h k ) \sigma_{batch}^k=\sqrt{\delta+\frac{1}{m}\sum_{i=1}^m(H_i^k-\mu_{batch}^k)} σbatchk=δ+m1i=1m(Hikμbatchk) 表示批标准化前,第k个卷积核, batch张输出特征图中所有像素点标准差。

在这里插入图片描述
一共包含 n n n 个卷积核, b a t c h = 32 batch=32 batch=32,每个卷积核对一个 b a t c h = 32 batch=32 batch=32 的输入特征图进行一次卷积计算输出 32 32 32 张特征图。 μ b a t c h k \mu_{batch}^k μbatchk 即对这 32 张特征图的所有像素值求平均; σ b a t c h k \sigma_{batch}^k σbatchk 即对这 32 张特征图的所有像素值求标准差。

在这里插入图片描述
如上图所示,BN操作将原本偏移的数据重新拉回标准正态分布,然后再进入激活函数,使进入激活函数的数据分布在激活函数线性区。 使得输入数据的微小变化,更明显的提现到激活函数的输出,提升了激活函数对输入数据的区分力。

但是,这种标准化方法使得特征数据完全满足标准正态分布,集中在激活函数中心的线性区域,使激活函数丧失了非线性特性,因此在BN操作中为每个卷积核引入可训练参数:缩放因子 γ \gamma γ 和偏移因子 β \beta β,调整批归一化的力度。 X i k = γ k H i ′ k + β k X_i^k=\gamma_kH_i'^k+\beta_k Xik=γkHik+βk 在反向传播时,缩放因子 γ \gamma γ 和偏移因子 β \beta β,会与其他可训练参数一同被优化。 使标准正态分布后的特征数据通过缩放因子和偏移因子优化了特征数据分布的宽窄和偏移量,保证了网络的非线性表达力。

在这里插入图片描述
BN层位于卷积层之后,激活层之前。

在这里插入图片描述
TensorFlow API: tf.keras.layers.BatchNormalization()

	model = tf.keras.models.Sequential([
			Conv2D(filters=6, kernel_size=(5, 5), padding='same'), # 卷积层
			BatchNormalization(), # BN层
			Activation('relu'), # 激活层
			MaxPool2D(pool_size=(2, 2), strides=2, padding='same'), # 池化层
			Dropout(0.2), # dropout层
			])
  • 注意:在调用此函数时,需要注意的一个参数是 training,此参数只在调用时指定,在模型进行前向推理时产生作用。
    • training = True 时,BN 操作采用当前 batch 的均值和标准差
    • training = False 时,BN 操作采用滑动平均(running)的均值和标准差
  • 在 Tensorflow 中,通常会指定 training = False,可以更好地反映模型在测试集上的真实效果。
  • 滑动平均(running):滑动平均,即通过一个个历史 batch 的叠加,最终趋向数据集整体分布的过程,在测试集上进行推理时,滑动平均的参数也就是最终保存的参数。
  • 此外,Tensorflow 中的 BN 函数其实还有很多参数,其中比较常用的是 momentum,即动量参数,与 sgd 优化器中的动量参数含义类似但略有区别,具体作用为滑动平均 r u n n i n = m o m e n t u m ∗ r u n n i n g + ( 1 – m o m e n t u m ) ∗ b a t c h runnin=momentum * running + (1 – momentum) * batch runnin=momentumrunning+(1momentum)batch,一般设置一个比较大的值,在 Tensorflow 框架中默认为 0.99。

5.6 池化

池化(pooling): 池化操作用于减少卷积神经网络中的特征参数量。

在这里插入图片描述

池化的主要方法有 最大池化均值池化最大池化可以提取图片纹理均值池化可以保留背景特征,如果使用 2 ∗ 2 2*2 22 的池化核对输入图片以步长 2 进行池化,输出图片将变为输入图片的 1/4 大小。

在这里插入图片描述
TensorFlow API:

	tf.keras.layers.MaxPool2D(pool_size=池化核尺寸,  # 正方形写核长整数,或(核高h,核宽w)
							  strides=池化步长,  # 步长整数, 或(纵向步长h,横向步长w),默认为pool_size
							  padding=‘valid’or‘same’)  # 使用全零填充是“same”, 不使用是“valid”(默认)

	tf.keras.layers.AveragePooling2D(pool_size=池化核尺寸,  # 正方形写核长整数,或(核高h,核宽w)
									 strides=池化步长,  # 步长整数, 或(纵向步长h,横向步长w),默认为pool_size
									 padding=‘valid’or‘same’)  # 使用全零填充是“same”, 不使用是“valid”(默认)

举个栗子:

	model = tf.keras.models.Sequential([
			Conv2D(filters=6, kernel_size=(5, 5), padding='same'), # 卷积层
			BatchNormalization(), # BN层
			Activation('relu'), # 激活层
			MaxPool2D(pool_size=(2, 2), strides=2, padding='same'), # 池化层
			Dropout(0.2), # dropout层
			])

5.7 舍弃 Dropout

舍弃(Dropout): 在神经网络的训练过程中, 将隐含层的部分神经元按照一定概率从神经网络中暂时舍弃,使用时被舍弃的神经元恢复链接。

在这里插入图片描述
TensorFlow API: tf.keras.layers.Dropout(舍弃的概率)

举个栗子:

	model = tf.keras.models.Sequential([
			Conv2D(filters=6, kernel_size=(5, 5), padding='same'), # 卷积层
			BatchNormalization(), # BN层
			Activation('relu'), # 激活层
			MaxPool2D(pool_size=(2, 2), strides=2, padding='same'), # 池化层
			Dropout(0.2), # dropout层随机舍弃20%的神经元
			])

5.8 卷积神经网络

卷积神经网络:通过卷积层借助卷积核提取特征后,送入全连接网络,进行识别预测任务。

卷积神经网络主要模块:
卷积层→BN层→激活层→池化层→Dropout层→FC层

在这里插入图片描述

卷积是什么?

卷积层的实际作用就是一个特征提取器,就是CBAPD。
卷积特征提取借助卷积核实现参数空间共享,借助卷积计算层提取空间特征后,送入全连接网络。

在这里插入图片描述


5.9 CIFAR10数据集

提供 5 万张 32 ∗ 32 32*32 3232 像素点的十分类彩色图片和标签,用于训练。
提供 1 万张 32 ∗ 32 32*32 3232 像素点的十分类彩色图片和标签,用于测试。

在这里插入图片描述
导入cifar10数据集:

	cifar10 = tf.keras.datasets.cifar10
	(x_train, y_train), (x_test, y_test) = cifar10.load_data()

观察CIFAR10数据集:

在这里插入图片描述


5.10 卷积神经网络搭建示例

搭建一个一层卷积、两层全连接的网络。

在这里插入图片描述
卷积层搭建示例:
在这里插入图片描述
“六步法“搭建卷积神经网络示例:

在这里插入图片描述
运行结果:

在这里插入图片描述


5.11 LeNet、AlexNet、VGGNet、InceptionNet、ResNet

接下来,将使用“六步法”实现LeNet、AlexNet、VGGNet、InceptionNet、ResNet卷积神经网络。

在这里插入图片描述

LeNet

LeNet 1 由Yann LeCun于1998年提出,卷积网络开篇之作。卷积网络通过共享卷积核,减少了网络的参数。

在统计神经网络层数时,一般只统计卷积计算层和全连接计算层,其余操作可以认为是卷积计算层的附属操作。
LeNet一共有五层网络,包含两层卷积层和三层全连接层。LeNet提出时,还没有BN操作和Dropout操作,该时代的主流激活函数为sigmoid激活函数。

在这里插入图片描述在这里插入图片描述
写出对应网络代码:

在这里插入图片描述
运行结果:

在这里插入图片描述

AlexNet

AlexNet 2 络诞生于2012年,是Hinton的代表作之一,当年ImageNet竞赛的冠军, Top5错误率为16.4%。AlexNet 使用了Relu激活函数,提升了训练速度,使用Dropout缓解了过拟合

AlexNet共有8层,包含5层卷积层和3层全连接层。

在这里插入图片描述
注:原文使用LRN(local response normalization) 局部响应标准化,本课程使用BN(Batch Normalization)替代。 近年来,LRN用的很少,其功能与BN相似。

写出对应网络代码:
在这里插入图片描述
运行结果:

在这里插入图片描述

VGGNet

VGGNet 3 诞生于2014年,当年ImageNet竞赛的亚军, Top5错误率减小到7.3%。

VGGNet使用小尺寸卷积核,在减少参数的同时,提高了识别准确率。VGGNet的网络结构规整,非常适合硬件加速。

以16层VGGNet网络为例: 包含13层卷积层和3层FC层。各层卷积核个数从64逐渐增加至512,越靠后,特征图尺寸越小,通过增加卷积核的个数,增加了特征图深度,保持了信息的承载能力。

在这里插入图片描述
写出对应网络代码:

在这里插入图片描述
运行结果:
在这里插入图片描述

InceptionNet

InceptionNet 4 诞生于2014年,当年ImageNet竞赛冠军, Top5错误率为6.67%。

InceptionNet引入了Inception结构块,在同一层网络内使用不同尺寸的卷积核,提升了模型感知力,使用了BN,缓解了梯度消失。

Inception结构块

InceptionNet的核心是他的基本单元Inception结构块。 无论是 GooGLeNet——Inception v1 ,还是InceptionNet的后续版本(v2,v3,v4)都是基于Inception结构块搭建的网络。

Inception结构块在同一层网络中使用了多个尺寸的卷积核,可以提取不同尺度的特征。

  • 通过 1 ∗ 1 1*1 11 卷积核作用到输入特征图的每个像素点,通过设定少于输入特征图深度的 1 ∗ 1 1*1 11 卷积核个数,减少了输出特征图深度,起到了降维的作用。 减少了参数量和计算量。

下图为一个Inception结构块的示意图:

在这里插入图片描述
Inception结构块共包含4个分支,分别为:

  • 经过 1 ∗ 1 1*1 11 卷积核输出到卷积连接器;
  • 经过 1 ∗ 1 1*1 11 卷积核配合 3 ∗ 3 3*3 33 卷积核输出到卷积连接器;
  • 经过 1 ∗ 1 1*1 11 卷积核配合 5 ∗ 5 5*5 55 卷积核输出到卷积连接器;
  • 经过 3 ∗ 3 3*3 33 最大池化核配合 1 ∗ 1 1*1 11 卷积核输出到卷积连接器。

送到卷积连接器的特征数据尺寸相同。 卷积连接器会将收到的这四路特征数据按深度方向拼接,生成Inception结构块的输出。

编写代码实现Inception结构块:
因为Inception结构块中的所有卷积均为CBA无PD结构,使用编写 class ConvBNRelu(Model): 来减小代码长度。

在这里插入图片描述
class ConvBNRelu(Model): 基础上使用 class 实现Inception结构块:
下图中,x = tf.concat([x1, x2_2, x3_3, x4_2], axis=3) 指按照 axis=3 深度方向拼接四路输出特征。
在这里插入图片描述

搭建一个精简的 InceptionNet

有了Inception结构块后,就可以搭建一个精简的InceptionNet了。网络共包含10层,分别为:

  • 第一层采用16个 3 ∗ 3 3*3 33卷积核,步长为1,全零填充,采用BN操作,Relu激活;
  • 随后是4个Inception结构块顺序相连,每两个Inception结构块组成一个block;
    • 第一个Inception结构块卷积步长为2,第二个Inception结构块卷积步长为1;
      这一操作使得第一个Inception结构块输出特征图尺寸减半,因此需要把输出特征图深度加深为2倍 self.out_channels *= 2
    • block_0设置的输出通道数为16,经过了4个分支,输出的深度为 4 ∗ 16 = 64 4*16=64 416=64
    • 因为使用 self.out_channels *= 2 将通道数加倍,所以block_1通道数为block_0的两倍,即block_1的通道数为32,经过了4个分支,输出的深度为 4 ∗ 32 = 128 4*32=128 432=128.
  • 128个通道的输出数据会被送入平均池化,再送人10分类全连接网络。

在这里插入图片描述

编写代码实现:
定义类Inception10时,设定了默认 init_ch=16 ,即默认输出深度为16,定义 class ConvBNRelu(Model): 时,定义了默认卷积核边长为3,步长为1,全零填充。
在这里插入图片描述


ResNet

ResNet 5 诞生于2015年,当年ImageNet竞赛冠军, Top5错误率为3.57%。

ResNet 提出了层间残差跳连,引入了前方信息,缓解了梯度消失,使得更深的神经网络的实现成为可能。前几小节介绍的LeNet、AlexNet、VGGNet和InceptionNet的层数:

在这里插入图片描述
可见,在探索卷积实现特征提取的道路上,通过加深网络层数,取得了越来越好的效果。而ResNet的作者何凯明在CIFAR10数据集上的实验发现56层卷积网络错误率高于与20层卷积网络。

在这里插入图片描述

跳跃连接 与 ResNet 结构块

作者认为,单纯堆叠网络层数,会使神经网络模型发生 退化现象 ,以至于后面的特征丢失了前面特征的原本模样。所以,作者引入了 跳跃连接 将前面的特征直接接到了后面。使得输出结果 H ( x ) H(x) H(x)包含了堆叠卷积的非线性输出 F ( x ) F(x) F(x) 和跳过这两层堆叠卷积层,直接连接的恒等映射 x x x ,即 H ( x ) = F ( x ) + x H(x)=F(x)+x H(x)=F(x)+x。这一操作有效缓解了深层神经网络层数过多所导致的 退化现象 。使得神经网络可以向着更深层发展。

注: ResNet中的特征图相加与InceptionNet中的特征图相加方式不同:

  • ResNet块中的“+”是特征图对应元素值相加(矩阵值相加),所以 F ( x ) F(x) F(x) x x x 特征图的维度应该完全相同。
  • Inception块中的“+”是沿深度方向叠加(千层蛋糕层数叠加)。

在这里插入图片描述

跳跃连接的两种方式

ResNet 结构块中的跳跃连接有两种情况:

  • 一种情况是下图中的实线连接,这种情况是指两层堆叠卷积没有改变特征图的维度,可以直接将特征图 F ( x ) F(x) F(x) 与特征图 x x x 相加;
  • 另一种情况是下图中的虚线连接,这种情况下,两层堆叠卷积改变了特征图的维度,需要借助 1 ∗ 1 1*1 11 卷积来调整 x x x 的维度(主要指特征图深度),使 特征图 F ( x ) F(x) F(x) 与特征图 x x x 维度一致。

在这里插入图片描述
对应这两种不同的ResNet结构块,写出代码:

在这里插入图片描述

搭建 ResNet-18

下图为ResNet-18的网络结构:
第一层为一个卷积,然后为8个ResNet结构块共16层卷积层,每两个ResNet结构块构成一个ResNet block,接着通过全局平均池化层,最后进入十分类全连接层。

在这里插入图片描述
根据ResNet结构块和ResNet-18网络结构编写出相应代码:

	class ResNet18(Model):
	    def __init__(self, block_list, initial_filters=64):  # block_list表示每个block有几个卷积层
	        super(ResNet18, self).__init__()
	        self.num_blocks = len(block_list)  # 共有几个block
	        self.block_list = block_list
	        self.out_filters = initial_filters
	        self.c1 = Conv2D(self.out_filters, (3, 3), strides=1, padding='same', use_bias=False)
	        self.b1 = BatchNormalization()
	        self.a1 = Activation('relu')
	        self.blocks = tf.keras.models.Sequential()
	        # 构建ResNet网络结构
	        for block_id in range(len(block_list)):  # 第几个resnet block
	            for layer_id in range(block_list[block_id]):  # 第几个卷积层
	
	                if block_id != 0 and layer_id == 0:  # 对除第一个block以外的每个block的输入进行下采样
	                    block = ResnetBlock(self.out_filters, strides=2, residual_path=True)
	                else:
	                    block = ResnetBlock(self.out_filters, residual_path=False)
	                self.blocks.add(block)  # 将构建好的block加入resnet
	            self.out_filters *= 2  # 下一个block的卷积核数是上一个block的2倍
	        self.p1 = tf.keras.layers.GlobalAveragePooling2D()
	        self.f1 = tf.keras.layers.Dense(10, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
	
	    def call(self, inputs):
	        x = self.c1(inputs)
	        x = self.b1(x)
	        x = self.a1(x)
	        x = self.blocks(x)
	        x = self.p1(x)
	        y = self.f1(x)
	        return y

5.12 经典卷积神经网络小结

当网络框架搭建好后,还需要尝试更改学习率等超参数,微调网络结构,通过一些优化策略,提升CIFAR10测试集的准确率。当模型在CIFAR10测试集的准确率达到90%以上时,则模型效果较好。

在这里插入图片描述



本文仅为笔者 TensorFlow 学习笔记,部分图文来源于网络,若有侵权,联系即删。

Reference


  1. Yann Lecun, Leon Bottou, Y. Bengio, Patrick Haffner. Gradient-Based Learning Applied to Document Recognition. Proceedings of the IEEE, 1998. ↩︎

  2. Alex Krizhevsky, Ilya Sutskever, Geoffrey E. Hinton. ImageNet Classification with Deep Convolutional Neural Networks. In NIPS, 2012. ↩︎

  3. K. Simonyan, A. Zisserman. Very Deep Convolutional Networks for Large-Scale Image Recognition. In ICLR, 2015. ↩︎

  4. Szegedy C, Liu W, Jia Y, et al. Going Deeper with Convolutions. In CVPR, 2015. ↩︎

  5. Kaiming He, Xiangyu Zhang, Shaoqing Ren. Deep Residual Learning for Image Recognition. In CPVR, 2016. ↩︎

你可能感兴趣的:(#,TensorFlow2.1)