学习《TensorFlow实战Google深度学习框架》(八) 卷积神经网络简介

版权声明:本文由洛北辰南原创,转载请注明原创地址,谢谢。 https://blog.csdn.net/qq_18941713/article/details/88682365

第六章 图像识别与卷积神经网络

通过MNIST数据集验证了第四章介绍的神经网络设计与优化的方法的实验结果可以看出,神经网络的结构会对神经网络的准确率产生巨大的影响。
本章介绍一个非常常用的神经网络结构——卷积神经网络(Convolutional Neural Network,CNN)。

6.1 图像识别问题简介及经典数据集

在这里插入图片描述
CIFAR数据集就是一个影响力很大的图像分类数据集。CIFAR数据集分为了CIFAR-10和CIFAR-100两个问题,它们都是图像词典项目(Visual Dictionary)中800万张图片的一个子集。
CIFAR-10问题收集了来自10个不同种类的60000张图片。如图为示例图片及分类,像素为32×32
在这里插入图片描述
CIFAR官网提供了不同格式的CIFAR数据集下载。

相比真实环境下的图像识别问题,有两个最大的问题。第一,现实生活中的图像分辨率要远高于32×32,而且图像分辨率不会固定。第二,现实生活中的物理类别很多,而且一张图片中也不会只出现一个种类的物体。

由斯坦福大学的李飞飞教授带头整理的ImageNet很大程度上解决了这两个问题。
ImageNet是一个机遇WordNet的大型图像数据库。在ImageNet中,将近1500万图片被关联到了WordNet的大约20000个名词同义词集上。目前每一个与ImageNet相关的WordNet同义词集都代表了现实世界中的一个实体,可以被认为是分类问题中的一个类别。ImageNet中的图片都是从互联网上爬取下来的,并且通过亚马逊的人工标注服务,将图片分类到WordNet 的同义词集上。在ImageNet的图片中,一张图片中可能出现多个同义词集所代表的实体。
在这里插入图片描述
上图为,物体识别任务,用矩形框(bounding box)框出实体,以用于更加精确的图像识别。
ImageNet的官网中列出了历届ILSVRC竞赛的题目和数据集。
在这里插入图片描述
如图,可以看出,基于卷积神经网络的图像识别算法可以远超人类表现。

6.2 卷积神经网络简介

首先展示一下,全连接网络与卷积神经网络的结构上的区别。
在这里插入图片描述
在全连接神经网络中,每相邻两层之间的节点都有边相连,于是一般会将每一层全连接层的节点组织成一列。
而对于卷积神经网络,相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,一般会将每一层卷积层的节点组织成一个三维矩阵。

使用全连接网络处理图像的最大问题在于参数过多。对于MNIST数据集,每一张图片大小事28×28×1,28×28为图像分辨率,1为色彩通道数。假设一层隐藏层节点数为500个,那么一个全连接层的神经网络参数有28×28×1×500+500=392500个。若是CIFAR数据集,32×32×32×500+500≈150万个参数。参数过多不仅导致计算效率低,也容易导致过拟合问题。所以需要一个更加合理网络结构来有效减少网络参数个数。

下图给出了一个更加具体的卷积神经网络架构图。
在这里插入图片描述
一个卷积神经网络主要由以下5中结构组成:

  • 1.输入层。输入一张图像的像素矩阵,三维矩阵的长和宽代表图像的像素大小,矩阵的深度代表图像的色彩通道,灰度图片只有一个通道,彩色图片有三个通道。
  • 2.卷积层。通过与过滤器进行卷积计算,提取某些图像特征,得到抽象程度更高的特征,经过卷积层处理的节点矩阵会变得更深。
  • 3.池化层。池化层不会改变三维矩阵的深度,但会改变矩阵的长宽。赤化操作可以认为是将一张分辨率较高的图片转化为分辨率较低的图片。
  • 4.全连接层。经过多轮卷积层和池化层处理之后,一般会由1到2个全连接层来给出最后的分类结果。经过几轮卷积层和池化层处理之后,可以认为图像中的信息已经被抽象成了信息含量更高的特征。可以把卷积、池化的过程看做自动图像特征提取的过程,仍需要全连接层来完成分类任务。
  • 5.Softmax层。Softmax层主要用于分类问题。通过Softmax层,可以得到当前样例属于不同种类的概率分布情况,在实际应用中,也就是图像分类得到的置信度。

6.3 卷积神经网络常用结构

6.3.1 卷积层

TensorFlow文档中将图中结构称为过滤器(filter),我更习惯称之为卷积核(kernel)。
过滤器可以将当前层神经网络上的一个子节点矩阵转化为下层神经网络上的一个单位节点矩阵。单位节点矩阵指的是长和宽都为1,但深度不限的节点矩阵。
在这里插入图片描述
过滤器的长度和宽都是人工指定的,这个节点矩阵的尺寸也被称之为过滤器的尺寸,常用的过滤器尺寸有3×3或5×5。因为过滤器的矩阵深度和当前层神经网络矩阵的深度是一致的,所以无需指定过滤器矩阵的深度。
另外一个需要指定的参数是处理得到的单位节点矩阵的深度,也就是过滤器的个数。由于一次卷积计算得到的是一个数值,所以过滤器的个数,决定了处理后的矩阵深度。

TensorFlow对卷积网络的解释太复杂了…我还是写的通俗一点。
在这里插入图片描述
请忽略g(0)的意义,左上为输入的图像矩阵的第一个要进行卷积计算的子矩阵,a[::0]、a[::1]、a[::2]为三个颜色通道上的子矩阵。对应的卷积核也有三个通道,a[::0]与w[::0]进行卷积计算,也就是对位相乘然后加和,三个通道的卷积计算结束后,再加上一个偏置量1就完成了一次卷积计算过程。

右侧是整个计算的过程,此次卷积计算的结果为-3。

如图一个卷积核同图像子矩阵进行卷积计算只得到了一个数字,那么一个卷积核同图像矩阵进行卷积计算得到的就是一个新的深度为1的矩阵。多个卷积核计算的结果会堆叠成新的矩阵,每多一个卷积核,得到的矩阵的深度就加一。
在这里插入图片描述
如图,根据边框的颜色,可以看出卷积层前向传播的过程。上图步长为1,即每次移动一格。
为了避免尺寸的变化,可以在当前层矩阵的边界加上全0填充(zero-padding)。
在这里插入图片描述
加入全0填充后,就可以保证卷积计算前后,矩阵尺寸不发生变化了。
还可以通过设置卷积核移动的步长来调整结果矩阵的大小。上两图步长均为1,下图展示了当移动步长为2时,卷积层的前向传播过程。
在这里插入图片描述
显然步长为2时,结果矩阵的长和宽只有原来的一半。
下图给出了使用了全0填充、步长为2的卷积层前向传播的计算流程。
在这里插入图片描述
ReLU(0×1+0×(-1)+0×0+1×2+1)=ReLU(3)=3
以下代码实现了卷积层的前向传播过程。

# -*- coding: utf-8 -*-
# @Time    : 2019/3/20 20:36
# @Author  : Chord

import tensorflow as tf;
# 通过tf.get_variable的方式创建卷积核的权重变量和偏置项变量。上面介绍了卷积层
# 的参数个数只和卷积核尺寸、个数以及当前层节点矩阵的深度油管,所以这里声明的参
# 数变量是一个四维矩阵,前面两个维度带包了卷积核的尺寸,第三个尺寸表示当前层的
# 深度,第四个维度表示卷积核的个数
filter_weight = tf.get_variable(
    'weights', [5, 5, 3, 16],
    initializer=tf.truncated_normal_initializer(0.1)
)
# 和卷积层的权重类似,当前层矩阵上不同位置的偏置项也是共享的,所以总共有下一层
# 深度个不同的偏置项,或者每个卷积核有一个偏置项。
biases = tf.get_variable(
    'biases', [16], initializer=tf.constant_initializer(0.1)
)

# tf.nn.conv2d提供了一个非常方便的函数来实现卷积层的前向传播算法。这个函数的第
# 一个输入为当前层的节点矩阵。注意这个矩阵是一个四维矩阵,后面三个维度对应一个
# 节点矩阵,第一维对应一个输入batch。比如在输入层,input[0,:,:,:]表示第一张图片,
# input[1,:,:,:]表示第二张图片。tf.nn.conv2d第二个参数提供了卷积层的权重,第三
# 个参数为不同维度上的步长。虽然第三个参数提供的是一个长度为4的数组,但是第一维
# 和最后一维的数字要求一定是1。这是因为卷积层的步长支队矩阵的长和宽有效。最后一
# 个参数是填充(padding)方法,TensorFlow中听过SAME或是VALID两种选择。启动SAME
# 表示全0填充,VALID表示不添加
conv = tf.nn.conv2d(
    input, filter_weight, strides=[1, 1, 1, 1], padding='SAME'
)

# tf.nn.bias_add提供了一个方便的函数给每一个节点加上偏置项。注意这里不能直接使用
# 加法,因为矩阵上不同位置上的几点都需要加上那个同样的偏置项。
bias = tf.nn.bias_add(conv, biases)
# 将计算结果通过ReLU激活函数完成去线性化
actived_conv = tf.nn.relu(bias)

6.3.2 池化层

池化层的前向传播过程也是通过移动一个滑块结构完成的。池化层一般分为两种。
第一种,使用最大值操作的池化层被称为最大池化层(max pooling)。第二张,使用平均值操作的池化层被称为平均池化层(average pooling)。
池化层的过滤器同样需要人工设定尺寸、步长、是否全0填充等。设置的意义与卷积层相同,唯一的区别在于卷积核的卷积计算横跨深度,而池化层的过滤器每次只影响一个深度上的节点。
下图展示了在输入子矩阵a的第0个通道、第1个通道分别进行最大池化的过程。
在这里插入图片描述

# tf.nn.max_pool实现了最大池化层的前向传播过程,它的参数和tf.nn.conv2d函数类似
# ksize提供了过滤器的尺寸,strides提供了步长信息,padding提供了是否使用全0填充
pool = tf.nn.max_pool(actived_conv, ksize=[1, 3, 3, 1],
                      strides=[1, 2, 2, 1], padding='SAME')
                      # 3×3的过滤器,步长为2                

猜你喜欢

转载自blog.csdn.net/qq_18941713/article/details/88682365