tensorflow识别MNIST数据集1

目录

数据准备

1、引入MNIST数据集

2、保存前30条数据的原始图片

 一、softmax实现单神经元模型

1、初始化变量

2、向前传播以及损失函数

3、向后传播以及优化参数

4、开始训练

5、评估模型

补充

二、两层卷积网络分类

1、初始化变量

2、预定义函数

3、卷积层

4、全连接层

5、定义交叉熵损失以及测试的准确率

6、开始训练

总结


数据准备

简单的说,MNIST就是一组最基础的数据集,M代表Modified,NIST代表国家标准和技术研究所,包括从0~9的训练数字的图片,这个分类问题是机器学习最简单和最广泛使用的测试之一。

1、引入MNIST数据集


  
  
  1. from tensorflow.examples.tutorials.mnist import input_data
  2. # 从MNIST_data/中读取MNIST数据。这条语句在数据不存在时,会自动执行下载
  3. mnist = input_data.read_data_sets( "MNIST_data/", one_hot= True)
  4. # 查看训练数据的大小
  5. print(mnist.train.images.shape) # (55000, 784)
  6. print(mnist.train.labels.shape) # (55000, 10)
  7. # 查看验证数据的大小
  8. print(mnist.validation.images.shape) # (5000, 784)
  9. print(mnist.validation.labels.shape) # (5000, 10)
  10. # 查看测试数据的大小
  11. print(mnist.test.images.shape) # (10000, 784)
  12. print(mnist.test.labels.shape) # (10000, 10)

MNIST官网下载的四个数据包放在MNIST_data中。不需要解压,不需要解压,不需要解压。

若没有数据包,Tensorflow会检测到并且会自动下载到MNIST_data文件夹中。

2、保存前30条数据的原始图片


  
  
  1. import scipy.misc
  2. import os
  3. # 我们把原始图片保存在MNIST_data/raw/文件夹下
  4. # 如果没有这个文件夹会自动创建
  5. save_dir = 'MNIST_data/raw/'
  6. if os.path.exists(save_dir) is False:
  7. os.makedirs(save_dir)
  8. # 保存前30张图片
  9. for i in range( 30):
  10. # 请注意,mnist.train.images[i, :]就表示第i张图片(序号从0开始)
  11. image_array = mnist.train.images[i, :]
  12. # TensorFlow中的MNIST图片是一个784维的向量,我们重新把它还原为28x28维的图像。
  13. image_array = image_array.reshape( 28, 28)
  14. # 保存文件的格式为 mnist_train_0.jpg, mnist_train_1.jpg, ... ,mnist_train_19.jpg
  15. filename = save_dir + 'mnist_train_%d.jpg' % i
  16. # 将image_array保存为图片
  17. # 先用scipy.misc.toimage转换为图像,再调用save直接保存。
  18. scipy.misc.toimage(image_array, cmin= 0.0, cmax= 1.0).save(filename)
  19. print( 'Please check: %s ' % save_dir)

 一、softmax实现单神经元模型

1、初始化变量


  
  
  1. import tensorflow as tf
  2. x = tf.placeholder(tf.float32,[ None, 784])
  3. W = tf.Variable(tf.zeros([ 784, 10]))
  4. b = tf.Variable(tf.zeros([ 10]))
  5. y = tf.nn.softmax(tf.matmul(x,W)+b)
  6. y_ = tf.placeholder(tf.float32,[ None, 10])

因为图片是28x28像素的,所以1张图片,即x中的一张图片转化成(1,784)的向量,它的便签值y_也转化为向量(1,10)。

因为不确定样本的数量,所以用“占位符(placeholder)”占据一定形式的内存空间,等待用户传值来决定具体的样本数量。我理解成一个有784个小格子高度的容器,由用户来决定有多少个这样的容器。

w,b为“变量”,规定了维度具体大小,即规定了有784个10个格子高度的容器,并把格子中装的值初始化为0。

因为x的值是固定的,所以预测值y的值主要由w,b来决定。

思考:

a、占位符和变量的区别是什么?

b、什么是softmax?为什么使用softmax?

2、向前传播以及损失函数

为了确定预测的y与标签值y_的差距,需要定义cost function去评估预测的准确性,即算法的优良性。

cross_entropy =  tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y)))
  
  

思考:

a、该损失函数的具体原理是什么?

3、向后传播以及优化参数

为了最小化损失函数,需要向后传播计算出dw以及db,即w和b对损失函数的影响程度,然后通过w-学习率*dw、b-学习率*db更新w和b的值。当然,Tensorflow将这两步通过一行代码同时实现了:

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
  
  

 代码中学习率为0.01

4、开始训练

首先初始化所有变量并申请内存空间:


  
  
  1. init = tf.global_variables_initializer()
  2. sess = tf.Session()
  3. sess.run(init)

 

 之后,梯度下降1000步:


  
  
  1. for _ in range( 1000):
  2. batch_xs,batch_ys = mnist.train.next_batch( 100)
  3. sess.run(train_step,feed_dict={x:batch_xs,y_:batch_ys})

 运行完后,模型便已被训练完成了,即参数w,b已经被训练好,尽可能的使y(预测值)接近y_(标签纸),在损失函数的图像上,使值尽可能的接近最凹的点,即最优的点。

5、评估模型


  
  
  1. correct_prediction = tf.equal(tf.argmax(y, 1),tf.argmax(y_, 1))
  2. accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
  3. print(sess.run(accuracy,feed_dict={x:mnist.test.images,y_:mnist.test.labels}))

输出: 

0.9168
  
  

思考:

a、为什么使用tf.argmax来进行评估?

补充

1、占位符和变量的区别是什么?

占位符和变量都属于Tensor(张量:一个数组中的元素分布在若干维的规则网格中,则称之为张量)。

占位符不依赖于其他Tensor,具体的值由用户传入,一般用来存储样本数据和标签值。

变量是计算过程中可以改变的值,每次计算后变量的值都会被保存下来,一般用来存储模型的参数。

2、什么是softmax?为什么使用softmax?

softmax函数是用于区分多个类别的函数,例如,对(a,b,c)三个类别进行softmax后,每个类别的概率为(\LARGE \frac{e^{a}}{e^{a}+e^{b}+e^{c}},\LARGE \frac{e^{b}}{e^{a}+e^{b}+e^{c}},\LARGE \frac{e^{c}}{e^{a}+e^{b}+e^{c}}),每个数值都在0-1,并且和为1。

相比于“hardmax”只将值表示为0或者1,softmax更详细的输出了每个类别的概率并且能够进行多个类别的判断,所以这里使用它。

3、 tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y))) 损失函数的具体原理是什么?

只从代码来看表示将 y_-{}\times (-\ln y)  公式的矩阵中所有值求和最后再求平均值。因为y的值肯定在0-1之间,为了保证损失值为正,添加符号取负。

若要损失函数的值最小:

当y_向量中某元素为0时,具体含义表示该图片不是某一张图,该项的损失函数值也为0,即相当于最后将10个类别的损失值求和的时候不考虑。

当y_向量中某元素为1时,只有当y的对应元素的值尽可能的接近1时,y_-{}\times (-\ln y)才尽可能最小,即尽可能接近0。所有让损失值最小的过程就是让预测值y的值无限接近真实值的情况。

4、为什么使用tf.argmax(y,1)来进行评估?

该函数表示取得最大值的下标,而值最大的元素的下标值就表示图片中真实数字的值。所以tf.argmax(y_,1)取得的下标值为真实图片的数字值,例如[0,2,7,1];tf.argmax(y,1)取得y向量中,对每个类别的预测值里最大值的下标值,即预测的图片的数字值,例如[8,2,7,5]。最后tf.equal进行比较,得到类似[0,1,1,0]的数组,通过tf.reduce_mean得到平均值0.5,表示预测准确率。

二、两层卷积网络分类

 采用单神经元进行预测,最后的准确率为大约为91.6%,采用卷积网络进行图片识别可将准确率提高到99%

1、初始化变量


  
  
  1. import tensorflow as tf
  2. from tensorflow.examples.tutorials.mnist import input_data
  3. #读入数据
  4. mnist = input_data.read_data_sets( "MNIST_data/",one_hot= True)
  5. #创建占位符
  6. x = tf.placeholder(tf.float32,[None, 784])
  7. y_ = tf.placeholder(tf.float32,[None, 10])
  8. #将向量还原,-1表示第一维度由x的具体数据确定,即由x的矩阵中样本个数来确定
  9. x_image = tf.reshape(x,[ -1, 28, 28, 1])

2、预定义函数


  
  
  1. def weight_variable(shape):
  2. inital = tf.truncated_normal(shape)
  3. return tf.Variable(inital)
  4. def bias_variable(shape):
  5. inital =tf.constant( 0.1,shape=shape)
  6. return tf.Variable(inital)
  7. def conv2d(x,W):
  8. return tf.nn.conv2d(x,W,strides=[ 1, 1, 1, 1],padding= 'SAME')
  9. def max_pool_2x2(x):
  10. return tf.nn.max_pool(x, ksize=[ 1, 2, 2, 1],strides=[ 1, 2, 2, 1], padding= 'SAME')

分别表示得到一定维度的参数,指定值的偏执项,卷积函数,2x2最大池化函数。

这里池化函数的过滤器为2x2,步长为2x2,当为此情况时,输出图片的维度是输入图片维度的一半

3、卷积层


  
  
  1. #第一卷积层
  2. w_conv1 = weight_variable([ 5, 5, 1, 32])
  3. b_conv1 = bias_variable([ 32])
  4. h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)
  5. h_pool1 = max_pool_2x2(h_conv1)
  6. #第二卷积层
  7. w_conv2 = weight_variable([ 5, 5, 32, 64])
  8. b_conv2 = bias_variable([ 64])
  9. h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)
  10. h_pool2 = max_pool_2x2(h_conv2)

第一卷积层:

32个5x5的卷积核进行卷积,padding为same,所以h_conv1的维度为(-1,28,28,32),-1表示该维度由具体样本数量决定;最后经过2x2最大池化卷积,得到h_pool,维度为(-1,14,14,32)

第二卷积层:

进行立体卷积,立体卷积时要保证卷积核的通道数与将要处理图片的通道数相同,所以卷积核维度为(5,5,32),有64个卷积核。h_conv2的维度为(-1,14,14,64),经过2x2池化层后,h_pool2的维度为(-1,7,7,64)

 

4、全连接层


  
  
  1. #全连接层
  2. w_fc1 = weight_variable([ 7* 7* 64, 1024])
  3. b_fc1 = bias_variable([ 1024])
  4. h_pool2_flat = tf.reshape(h_pool2, [ -1, 7* 7* 64])
  5. h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1)+ b_fc1)
  6. #使用dropout
  7. keep_prob = tf.placeholder(tf.float32)
  8. h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  9. #最后一层全连接层
  10. w_fc2 = weight_variable([ 1024, 10])
  11. b_fc2 = bias_variable([ 10])
  12. y_conv = tf.matmul(h_fc1_drop,w_fc2)+b_fc2

第一层全连接层:

将h_pool2后三维转化成一维向量,输出1024维的向量;使用dropout,每一步训练时,一定概率的去掉全连接层中某些连接,防止过度拟合。

第二层全连接层:

将1024维度h_fc1_drop转化为10个类别的打分。

5、定义交叉熵损失以及测试的准确率

y_conv相当于softmax的logit(即wx+b),所以当然可以用softmax定义将其转换为10个类别的概率,再定义交叉熵损失。但是tensorflow有打包好的函数,直接对logit定义交叉熵损失: 

cross_entropy =  tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y_,logits=y_conv))

  
  

 取预测后结果的平均值得到准确率:


  
  
  1. correct_prediction = tf.equal(tf.argmax(y_conv, 1),tf.argmax(y_, 1))
  2. accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf. float32))

6、开始训练


  
  
  1. #创建Session,对变量初始化
  2. sess = tf.InteractiveSession()
  3. sess.run(tf.global_variables_initializer())
  4. # 训练20000步
  5. for i in range( 20000):
  6. batch = mnist.train.next_batch( 50)
  7. # 每100步报告一次在验证集上的准确度
  8. if i % 100 == 0:
  9. train_accuracy = accuracy.eval(feed_dict={x: batch[ 0], y_: batch[ 1], keep_prob: 1.0})
  10. print( "step %d, training accuracy %g" % (i, train_accuracy))
  11. train_step.run(feed_dict={x: batch[ 0], y_: batch[ 1], keep_prob: 0.5})
  12. # 训练结束后报告在测试集上的准确度
  13. print( "test accuracy %g" % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

 

总结

主要完成了Tesorflow建立Softmax回归模型以及两层卷积的神经网络,了解如何读入数据集以及Tensorflow建立模型的基本流程:

  1. 创建还没有执行的tensor(以及自定义辅助函数)
  2. 给tensor间书写逻辑
  3. 初始化各个tensor
  4. 建立以及运行会话

目录

猜你喜欢

转载自blog.csdn.net/qq_32790593/article/details/85307004
今日推荐