TensorFlow 2.0 深度学习实战 —— 浅谈卷积神经网络 CNN

前言

上一章为大家介绍过深度学习的基础和多层感知机 MLP 的应用,本章开始将深入讲解卷积神经网络的实用场景。
卷积神经网络 CNN(Convolutional Neural Networks,ConvNet)是一种特殊的深度学习神经网络,近年来在物体识别、图像重绘、视频分析等多个层面得到了广泛的应用。
本文将以VGG16预训练模型为例子,从人脸识别、预训练模型、图片风格迁移、滤波分析、热力图等多过领域介绍 CNN 的应用。

目录

一、卷积神经网络的原理

二、构建第一个 CNN 对MNIST 数字进行分类

三、利用 CNN 进行人脸识别

四、使用 VGG16 框架预训练模型 

五、CNN 中间激活层输出图

六、CNN 滤波器的可视化输出

七、CNN 热力图


一、卷积神经网络的原理

卷积神经网络 CNN 是由多个块组成,每个块都具有两种层:卷积层 Conv 和池化层 Pooling,卷积层 Conv 通过卷积核(也称滤波器)进行卷积运算后,由激活函数输出到池化层,再通过池化运算,如此迭代多次后,由最后的一个块通过输出层全连接进行数据输出,完成卷积神经网络的整个过程(如下图)。
可能听起来可能有点复杂,其实可以把 “卷积层 ——> 激活层 ——> 池化层” 作为一个重复块看待,经过多层重复后再由全连接输出,下面将从卷积层和池化层两个方面分别介绍 CNN 流程。

1.1 卷积层

1.1.1 滤波器(卷积核)

假设在卷积层中,有一个 1*6*6 的图形作为输入数据,这里把它称为输入特征图,它经过一个 3*3 的滤波器(也被称为卷积核)进行卷积运算,即从 input 左上角 3*3 的受野区开始计算其张量积,每完成一次计算向右移动,步幅为1,完成此计算后,就会得出一个 1*4*4 的输出特征图(如下图)。

卷积核的形状必须大于等于 2 * 2 ,一般为 3*3 或者 5*5,其步幅可以自定义,一般为 1。如果卷积核步幅为 3,那么一个输入特征图为1*6*6经过步幅为3的3*3卷积核后,输出特征图就会变为 1*2*2, 如此类推。

1.1.2 偏置值

正如正常等式 f(x)=w*x+h 一样,卷积运算也有偏置值,偏置值的运算就是为每个值都加上此张量,如果下图

1.1.3 填充

经过卷积核运算后,输出特征图会比输入特征图维度少2,也就是一个1*3*3 的输入特征图与一个步幅为1的3*3卷积核运算后,会得出一个 1*1*1 的输出特征图。然而,这时候如果需要得出一个1*3*3 的输出特征图,只需要把 padding 参数设置为 same,系统就会自动把输入称征图变形状为 1*5*5,用 0 来填充再进行运行。 

1.1.4 三维数据卷积运算

上图所介绍的都是二维数据的卷积运算,如果遇到图像处理时,例如 RGB 图片,往往还需要处理一个数据就是通道 channel,一般 RGB 图片的 channel 数为 3(红、绿、蓝),而 monochrome 图片的 channel 数为 1,根据格式不同略有差别。因此卷积核有三维数据的运算,当输入特征图为三维数据时,其卷积核也会变为三维,并将每个维度的结果相加得出输出特征输出图。

我们可以把这个三维的输入特征图看成是一幅 n 个 channel 的图片输入操作,如果图片为 n 个 channel 大小为 width*height 的输入特征图,卷积核的形状是 n*3*3,最后输出特征图将是 1*owitdh * oheight 。

此时,若用到 w 个卷积核,然后再加入 w 个偏置值,那 n 个 channel 大小为 height * width 的输入特征图将会输出 w 层大小为 oheight * owidth 的输出特征图

1.1.5 TensorFlow 中的 卷积类 ConvNet

在 TensorFlow 1.x 中需要添加一个卷积层,可使用 tf.nn.conv2d 函数

1 def conv2d_v2(input,  filters,   strides,  padding,
2               data_format="NHWC", dilations=None,
3               name=None):
  • input:  类型为 `float32`, `float64`,`int32`, `uint8`, `int16`, `int8`, `int64`, `bfloat16`, `uint16`, `half`, `uint32`, `uint64`其中一种的张量,形状为 [batch, in_height, in_width, depth],代表输入的批量数据
  • filters: 类型为 float32、float64、halt 的张量,输入类型与 input 相同,代表卷积核格式,例如 [1,3,3,1]
  • strides:int 类型列表,长度为4,用于控制卷积核的移动步幅,与上述参数相同,也是四维的,[1,1,1,1],其中第一个1和最后一个1是固定值,中间的两个数代表在x轴和y轴的移动步长。
  • padding:str 类型 [ SAME','VALID'] 之一,用于选择填充的算法,SAME 是填充边界,VALID 是当不足以移动时直接舍弃。
  • data_formate:str类型 [‘NHWC’、'NCHW' ] 之一,默认值为 NHWC,指定输入和输出数据的格式。NHWC 时数据格式为 [batch, in_height, in_width, in_channels],NCHW时数据格式为 [batch,in_channels,in_heihgt,in_width] 
  • dilations:int类型列表,格式必须为 [1, rate_height, rate_width, 1],指定填充边界时的步幅。当边界无需填充时,其默认值为 None,当需要填充边界时,其默认值为 [1,1,1,1]
  • name: str 类型,名称

在 TensorFlow 2.x 中可以直接使用 Conv2D 类,其常用参数与 TensorFlow 1.x 类似,注意数据输入格式略有不同。

1 class Conv2D(Conv):
2   def __init__(self,filters,kernel_size,strides=(1, 1),padding='valid',
3           data_format=None,dilation_rate=(1, 1),groups=1,activation=None,
4           use_bias=True,kernel_initializer='glorot_uniform',bias_initializer='zeros',
5           kernel_regularizer=None,bias_regularizer=None,activity_regularizer=None,
6           kernel_constraint=None, bias_constraint=None,
7           **kwargs):
  • filters:int 类型,代表卷积核的数量
  • kernel_size:int 类型列表,形状 [int,int],代表卷积核的形状
  • strides:int 类型列表,默认值为 (1 , 1 ) 与 tf.nn.conv2d 不同,其形状为 [int , int ] 二维数组,用于控制卷积核的移动步幅。
  • padding:"valid" 或 "same" (大小写敏感),用于选择填充的算法,same 是填充边界,valid 是当不足以移动时直接舍弃。
  • data_formate:str类型 [ channels_last , channels_first ] 之一,默认值为 channels_last,指定输入和输出数据的格式。channels_first 时数据格式为 [batch, channels, height, width],channels_last 时数据格式为 [batch,heihgt,width, in_channels] 
  • dilations:int类型列表,格式必须为 [ rate_height, rate_width ],默认值为 [1 , 1 ],指定填充边界时的步幅。
  • group: int 类型,默认为1,指定输入数据中,沿 channel 轴分割的组的数量
  • activation: str 类型,默认为 None,要使用的激活函数。 如果你不指定,则不使用激活函数 (即线性激活: a(x) = x)。
  • use_bias: bool 类型,默认为 True,指该层是否使用偏置向量。
  • kernel_initializer: str 类型,默认为 glorot_uniflorm, kernel 权值矩阵的初始化器 (详见 keras.initializers)。
  • bias_initializer: str 类型,默认为 zeros ,偏置向量的初始化器 (详见 keras.initializers) 。
  • kernel_regularizer: str 类型,默认为 None,运用到 kernel 权值矩阵的正则化函数 (详见 keras.regularizers)。
  • bias_regularizer: 运用到偏置向量的正则化函数 (详见 keras.regularizers)。
  • activity_regularizer: 运用到层输出(它的激活值)的正则化函数 (详见 keras.regularizers)。
  • kernel_constraint: 运用到 kernel 权值矩阵的约束函数 (详见 keras.constraints)。
  • bias_constraint: 运用到偏置向量的约束函数 (详见 keras.constraints)。
     

 1.2 最大池化层

池化层分为最大池化层 MaxPool 与均值池化层 AvgPool,其实就是缩小width和height的运算,比如按步幅 2 进行 2*2 MaxPool,相当于在 2*2 的区域中获取最大值运算,取出最大的值。其池化大小往往也步幅相同,即 2 * 2 的池化步幅为2 ,3 * 3 的池化步幅为3,如此类推。

在 TensorFlow 1.x 中需要添加最大池化层,可使用 tf.nn.max_pool 函数

1 def max_pool(value, ksize, strides, padding,
2        data_format="NHWC", name=None, input=None): 
  • input:  类型为 `float32` 的 4维张量,形状为 [batch, in_height, in_width, depth],代表输入的批量数据
  • ksize: 类型为 int 的整数列表,代表池化区域的格式,例如 [1 , 2 , 2 , 1]
  • strides:int 类型列表,长度为4,用于控制池化的移动步数,与上述参数相同,也是四维的,例如[1,1,1,1],其中第一个1和最后一个1是固定值,中间的两个数代表在x轴和y轴的移动步长。
  • padding:str 类型 [ SAME','VALID'] 之一,用于选择填充的算法,SAME 是填充边界,VALID 是当不足以移动时直接舍弃。
  • data_formate:str类型 [‘NHWC’、'NCHW' ] 之一,默认值为 NHWC,指定输入和输出数据的格式。NHWC 时数据格式为 [batch, in_height, in_width, in_channels],NCHW时数据格式为 [batch,in_channels,in_heihgt,in_width] 
  • name: str 类型,名称

 在 TensorFlow 2.x 中可通过 MaxPooling2D 类生成最大池化层

1 class MaxPooling2D(Pooling2D):
2   def __init__(self, pool_size=(2, 2), strides=None,
3          padding='valid', data_format=None,  **kwargs):
  • pool_size:int 类型的整数列表,长为2,默认为(2,2),代表池化层在两个方向(竖直,水平)采样范围。
  • strides:int 类型列表,步长为2的整数列表,默认为 None,用于控制池化的移动步数。当使用 None 时,默认 与pool_size 相同。
  • padding:"valid" 或 "same" (大小写敏感),用于选择填充的算法,same 是填充边界,valid 是当不足以移动时直接舍弃。
  • data_format:字符串,“channels_first”或“channels_last”之一,代表图像的通道维的位置。默认值为 channels_last,指定输入和输出数据的格式。channels_first 时数据格式为 [batch, channels, height, width],channels_last 时数据格式为 [batch,heihgt,width, channels] 
     

1.3 卷积神经网络 CNN 的优势

对比起多层感知机,卷积神经网络有其天生的优势。由于多层感知机使用的是全转接层,因此当输入图形数据例如 RGB 图形为三维形状时,需要先对图像进行变形。例如常用的 MNIST 28*28*1 的数字,输入前会先将其转化为 784 的数据形式。如此一来相当于把所有的神经元看作同一维度处理,这样会把原有的三维数据间所隐藏的关联标志,相距像素等重要信息丢弃。
而从上面的例子可以看到,使用卷积神经网络会以三维数据的形式接收输入数据,同时以三维的形式输出到下一层。因此使用 CNN 可以最大程度保存图形原来的特征,这也是近年来 CNN 被广泛应用于图像、视频、人脸识别等领域的原因。

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值