目录

第5章 MNIST数字识别问题

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

第7章 图像数据处理

 

 


第5章 MNIST数字识别问题

MNIST是一个非常有名的手写体数字识别数据集,在很多资料中,这个数据集都会被用作深度学习的入门样例。MNIST数据集是NIST数据集的一个子集,它包含了60000张图片作为训练数据,10000张图片作为测试数据。以下代码是使用TensorFlow读取MNIST数据集,如果本地不存在则自动下载到本地指定的目录,并打印数据集的训练集、验证集和测试集的维度大小。

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("./MNIST_data/", one_hot=True)

print ("Training data size: ", mnist.train.num_examples)
print ("Validating data size: ", mnist.validation.num_examples)
print ("Testing data size: ", mnist.test.num_examples)

运行结果:

Extracting ./MNIST_data/train-images-idx3-ubyte.gz
Extracting ./MNIST_data/train-labels-idx1-ubyte.gz
Extracting ./MNIST_data/t10k-images-idx3-ubyte.gz
Extracting ./MNIST_data/t10k-labels-idx1-ubyte.gz
Training data size:  55000
Validating data size:  5000
Testing data size:  10000

 

TensorFlow提供了通过变量名称来创建或者获取一个变量的机制。通过这个机制,在不同函数中可以直接通过变量名称来创建或者获取一个变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要将变量通过参数的形式到处传递。TensorFlow中通过变量名称获取变量的机制主要是通过tf.get_variable和tf.variable_scope函数来实现,还可以同规格tf.Variable函数来创建变量。

 

通过tf.variable_scope函数可以控制tf.get_variable函数的语义。当tf.variable_scope函数使用参数reuse=True生成上下文管理器时,这个上下文管理器内所有的tf.get_variable函数会直接获取已经创建的变脸。如果变量不存在,则tf.get_variable函数将报错;相反,如果tf.variable_scope函数使用参数reuse=None或者reuse=False创建上下文管理器,tf.get_variable操作将创建新的变量。如果同名变量已经存在,则tf.get_variable函数将报错。以下代码示例说明了通过variable_scope来管理变量:

import tensorflow as tf

v1 = tf.get_variable("v", [1])
print (v1.name)

with tf.variable_scope("foo"):
    v2 = tf.get_variable("v", [1])
print (v2.name)

with tf.variable_scope("foo"):
    with tf.variable_scope("bar"):
        v3 = tf.get_variable("v", [1])
        print (v3.name)
    
v4 = tf.get_variable("v1", [1])
print (v4.name)

运行结果:

v:0
foo/v:0
foo/bar/v:0
v1:0

 

TensorFlow提供了一个非常简单的API来保存和还原一个神经网络模型。这个API就是tf.train.Saver类。下面代码给出了保存和加载计算图的方法:

import tensorflow as tf

v1 = tf.Variable(tf.random_normal([1], stddev=1, seed=1))
v2 = tf.Variable(tf.random_normal([1], stddev=1, seed=1))
result = v1 + v2

init_op = tf.global_variables_initializer()
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(init_op)
    saver.save(sess, "./Saved_model/model.ckpt")

运行结果:

 TensorFlow实战Google深度学习框架5-7章学习笔记

加载保存的模型:

ith tf.Session() as sess:
    saver.restore(sess, "./Saved_model/model.ckpt")
    print (sess.run(result))

运行结果:

INFO:tensorflow:Restoring parameters from ./Saved_model/model.ckpt
[-1.6226364]

 

 


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

连接神经网络处理图像的最大问题在于全连接层的参数太多,参数增多除了导致计算速度减慢,还很容易导致过拟合问题。所以需要一个更合理的神经网络结构来有效地减少神经网络中参数个数,卷积神经网络就可以达到这个目的。

 

卷积神经网络主要由5种结构组成:输出层、卷积层、池化层、全连接层和Softmax层。

 

输入层:输入层是整个神经网络的输入,在处理图像的卷积神经网络中,它一般代表了一张图片的像素矩阵。

卷积层:从名字可以看出。卷积层是一个卷积神经网络中最为重要的部分。和传统全连接层不同,卷积层中每一个节点的输入只是上一层神经网络的一小块,这个小块常用的大小有3*3或者5*5。卷积层试图将神经网络中的每一小块进行更加深入地分析从而得到抽象程度更高的特征。一般来说,通过卷积层处理过的节点矩阵会变得更深。

池化层:池化层神经网络不会改变三维矩阵的深度,但是它可以缩小矩阵的大小。池化操作可以认为是将一张分辨率较高的图片转化为分辨率较低的图片。通过池化层,可以进一步缩小最后全连接层中节点的个数,从而达到减少整个神经网络中参数的目的。

全连接层:我可以将卷积层和池化层看成自动图像特征提取的过程。在特征提取完成之后,仍然需要使用全连接层来完成分类任务。

Softmax层:Softmax层主要用于分类问题,通过Softmax层可以得到当前样例属于不同种类的概率分布情况。

 

卷积层神经网络结构中最重要的部分,称之为过滤器(filter)或者内核(kernel)。过滤器可以将当前层神经网络上的一个子节点矩阵转化为下一层神经网络上的一个单位节点矩阵。单位节点矩阵指的是一个长和宽都为1,但深度不限的节点矩阵。子节点矩阵的尺寸也被称之为过滤器的尺寸,常用的过滤器尺寸有3*3或5*5。因为过滤器处理的矩阵深度和当前层神经网络节点矩阵的深度是一致的,所以虽然节点矩阵是三维的,但过滤器的尺寸只需要指定两个维度。过滤器中另外一个需要人工指定的设置是处理得到的单位节点矩阵的深度,这个设置称之为过滤器的深度。

 

卷积层的参数个数要远远小于全连接层,而且卷积层的参数个数和图片的大小无关,它只和过滤器的尺寸、深度以及当前层节点矩阵的深度有关,这使得卷积神经网络可以很好地扩展到更大的图像数据上。

 

在卷积层之间往往会加上一个池化层,池化层可以非常有效地缩小矩阵的尺寸,从而减少最后全连接层中的参数。使用池化层可以加快计算速度,也有防止过拟合问题的作用。池化层前向传播过程也是通过移动一个类似过滤器的结构完成的,不过池化层过滤器中的计算不是节点的加权和,而实采用更加简单的最大值或者平均值计算。

 

卷积层和池化层中过滤器移动的方式是相似的,唯一的区别在于卷积层使用的过滤器是横跨整个深度的,而池化层使用的过滤器只影响一个深度上的节点。所以池化层的过滤器除了在长和宽两个维度移动,它还需要在深度这个维度上移动。

 

以下正则表达式公式总结了一些经典的用于图片分类问题的卷积神经网络结构:

输入层—>(卷积层+—>池化层?) +—>全连接层+

在以上公式中,“卷积层+”表示一层或者多层卷积层,大部分卷积神经网络中一般最多连续使用三层卷积层。“池化层?”表示没有或者一层池化层。池化层虽然可以起到减少参数防止过拟合问题,但是在部分论文中也发现可以直接通过调整卷积步长来完成。在多轮卷积层和池化层后,卷积神经网络在输出之前一般会经过1~2个全连接层。比如LeNet-5模型就可以表示为以下结构:

输入层—>卷积层—>池化层—>卷积层—>池化层—>全连接层—>全连接层—>输出层

 

Inception结构是一种和LeNet-5结构完全不同的卷积神经网络结构。在LeNet-5模型中,不同卷积层通过串联的方式连接在一起,而Inception-v3模型中的Inception结构是将不同的卷积层通过并联的方式结合在一起。Inception模块中一般会使用不同尺寸的过滤器处理输入矩阵,通过使用全零填充且步长为1,那么前向传播得到的结果矩阵的长和宽都与输入矩阵一致。这样经过不同过滤器处理的结果矩阵可以拼接成一个更深的矩阵。一般推荐使用TensorFlow-Slim工具来更加简洁地实现一个卷积层。例如:

net = slim.conv2d(input, 32, [3, 3]) 

 

 


第7章 图像数据处理

TensorFlow提供了一种统一的格式来存储数据,这个格式就是TFRecord。

 

一般图像的原始输入数据是直接使用图像原始的像素矩阵,但是可以通过对图像的预处理,可以尽量避免受到无关因素的影响。TensorFlow提供了几类图像处理函数,分别为图像编码处理、图像大小调整、图像翻转、图像色彩调整和处理标注框。