1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 03:一文全解:使用Tensorflow搭建卷积神经网络CNN识别手写数字图片

03:一文全解:使用Tensorflow搭建卷积神经网络CNN识别手写数字图片

时间:2018-07-13 23:36:16

相关推荐

03:一文全解:使用Tensorflow搭建卷积神经网络CNN识别手写数字图片

标签(空格分隔): 王小草Tensorflow笔记

笔记整理者:王小草

笔记整理时间:2月25日

官方文档原文地址:/get_started/mnist/pros

官方文档最近更新时间:2月15日

欢迎机器学习,深度学习爱好者一起交流。

也欢迎关注我的喜马拉雅账号:”好吧我真的叫王草”。分享由集智俱乐部推出的两本好书:《科学的极致:漫谈人工智能》与《走进2050,注意力,互联网与人工智能》。

在上一篇笔记中介绍了用softmax去识别手写数字的图片,正确率只有92%。这篇笔记,仍然聚焦于同一个案例,但使用一个更复杂一点的模型来做训练:卷积神经网络(简称CNN)。从而正确率会到达99.2%。

关于卷积神经网络CNN在我之前的深度学习系列笔记中有详细介绍,欢迎阅读,在这里就不再赘述了。

1.数据准备

前面的过程与上一篇笔记一样:

1.导入tensorflow包

2.下载数据

3.创建会话

4.为输入的样本特征x与标签y建立占位符

代码如下,不再解释,不懂的可以看上一篇笔记

import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data# 加载数据mnist = input_data.read_data_sets(MNIST_data, one_hot=True)# 创建会话sess = tf.InteractiveSession()# 设置占位符x = tf.placeholder(tf.float32, shape=[None, 784])y_ = tf.placeholder(tf.float32, shape=[None, 10])

2.初始化参数的方法封装

参数在训练中是会不断变更与优化的,所有为参数创建一组变量。因为在神经网络中每层都会有参数,一个一个去创建显然不科学,最好的方式是写一个function去封装创建参数变量的过程。在神经网络里涉及的参数仍然是2类:w,b.

# 创建w参数def weight_variable(shape):initial = tf.truncated_normal(shape, stddev=0.1)return tf.Variable(initial)# 创建b参数def bias_variable(shape):initial = tf.constant(0.1, shape=shape)return tf.Variable(initial)

以上代码中,tf.truncated_normal函数使得w呈正太分布,

stddev设置标准差为0.1。也就是说输入形状大小shape,输出标准差为0.1的正太分布的随机参数作为权重变量矩阵

对于参数b,使用了tf.constant()来创建一组指定大小的常数,常数值为0.1

在方法def中都分别初始化了这两个参数。

注意:在初始化参数的时候,也不是随便给一个值作为初始值的哈。模型对初始的参数是很敏感的,如果参数都很大,那么经过wx+b这个线性函数时,输出的值也会很大,若是经过tanh这个激活函数,输出的结果绝对值都几乎接近于1,也就是说每个神经元的输出都几乎相同,这完全违背了神经网络的初衷,事实上我们希望每个神经网络都能去学习一个不同的特征,他们的输出值应该是有差异的。另一方面,如果w值设置地太小了,经过线性函数wx+b的时候,wx可以忽略不计,于是线性函数的输出都约等于b,经过激活函数后的输出也几乎相同,又造成了神经元彼此雷同的尴尬局面呢。

对于参数b, 因为这里要使用的是RELU这个激活函数,所以最好设置成小一点的正数,从而来避免“神经元死亡”。RELU激活函数是,当输入大于0,则输出=输入值;若输入值小于0,则输出=0,想想,要是b是太大的负数,线性函数的输出也很有可能是负数,经过RELU之后就都变成0了。。。

3.创建卷积层与池化层的方法封装

Tensorflow也在卷积层与池化层给了很多灵活的操作。卷积层与池化层都需要设置一些超参数,比如步长,窗口大小,补全的边界等。那么我们该如何去定义边界,如何去选择步长呢?在这里我们选择使用步长为1,用0补全边界,故卷积层的输出与输入的数据大小是一致的。

在池化层中,使用2*2的窗口选取窗口中的最大值作为输出。

同样,一个神经网络会有很多个卷积层与池化层,我们不可能去一层一层写,为了使代码更简洁,最好将卷积层与池化层的创建封装成两个方法。如下:

# 创建卷积层,步长为1,周围补0,输入与输出的数据大小一样(可得到补全的圈数)def conv2d(x, W):return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=SAME)# 创建池化层,kernel大小为2,步长为2,周围补0,输入与输出的数据大小一样(可得到补全的圈数)def max_pool_2x2(x):return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding=

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。