TensorFlow学习笔记MNIST手写数字识别
Posted 準提童子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TensorFlow学习笔记MNIST手写数字识别相关的知识,希望对你有一定的参考价值。
MNIST是机器学习中的Hello world,前期准备要了解Softmax (multinomial logistic ) regression
MNIST的是一个简单的计算机视觉数据集,它包含一系列手写数字图片,我们将训练一个模型识别图片中的数字
我们本次目的不是训练一个精准模型,以达到稳定的高性能,而是学会如何使用Tensorflow解决简单的问题
本次使用一个简单的模型Softmax Regression,代码是简单的,所有有趣的事情都发生在几行代码里,明白背后中TensorFlow是如何工作的,以及机器学习的核心概念
本文完成以下任务:
1.了解MNIST数据以及Softmax Regression
2.构建一个模型,根据图片的像素识别数字
3.基于上千个样例,使用TensorFlow训练模型识别数字
4.使用测试数据检验正确性
MINIST 数据集
MNIST的数据在机器学习大牛Yann leCun的个人网站上有http://yann.lecun.com/exdb/mnist/
可以使用代码下载数据集:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
数据集被分为三个部分:55000个
数据点data points作为训练mnist.train,10000作为测试mnist.test,5000作为验证mnist.validation
每个MNIST数据点有两个部分:手写的数字图片和其相应的标签,将图片作为x, 标签作为y
每个图片为28*28像素,我们可以将其抽象为数字:
扁平化数据为一个28*28=784大小的向量,如何扁平化是无关紧要的,只要能保证所有图片的扁平化方式一致
按照这种方式,图片被抽象为784维度的向量空间
扁平化数据的过程,丢失图片的2D属性,这是不是不太好?答案是肯定的,后边我们会涉及好的方法,但是在此我们使用简单的方式
处理后的结果是,mnist.train.imgages是一个张量tensor with shape [55000,784], 对于图片中的特定像素,tensor中每个条目中的值为0或1
每个图片有一个相应的标签,为0-9,每个标签抽象为“one-hot vectors” (指只有一个维度为1其他维度都为0的向量),
这样mnist.train.labels就是一个tensor with shape[55000,10]
Softmax Regression
主要讲解模型Softmax 回归
定义模型
在python数值计算中,经常会使用到一些别的库,像numpy,在python外进行昂贵的操作,如矩阵计算。但是Python内外的数据交互会使得高的开销,为避免这些,Tensorflow使用先描述计算图,后再一起计算的方式。
声明placeholder参数化的从外部输入数据,None代表维度可以是任意值
x=tf.placeholder(tf.float32,[None,784])
定义
权重weight和
偏差biase
W=tf.Variable(tf.zeros([784,10]))
b=tf.Variable(tf.zeros([10]))
将W和b初始化为全0张量,这是无关紧要的,因为机器学习过程中会自动修改他们
W定义为一个tensor with [784,10],是因为我们要将784维的向量转换为10维的。
实现模型:
y=tf.nn.softmax(tf.matmul(x,W)+b)
使用
tf.matmul(x,W)实现x和W的相乘。仅此一行代码就定义了模型!
训练
为了训练模型,我们需要明确什么样的情况意味着模型好, 交叉熵cross-entropy决定模型损失(Softmax模型通过最小化交叉熵来训练)存放真实值
y_=tf.placeholder(tf.float32,[None,10])
交叉熵计算:
cross_entropy=tf.reduce_mean(-tf.reduce_sum(y_*tf.log(y), reduction_indices=[1]))
tf.log计算y中元素的对数,tf.reduce_sum计算y中第2维元素的相加(y为tensor with shape[None, 10]),因为参数reduction_indices=[1]
最后tf.reduce_mean计算平均值,在源代码中我们不使用该方程,因为它数字上不是稳定的
对于非规范化的逻辑,使用tf.nn.softmax_cross_entropy_with_logits
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
使用选择的优化算法修改变量,减少损失
train_step=tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
我们使用
学习率learning rate为0.5的
梯度下降算法gradient descent algorithm
Tensorflow提供了很多别的优化算法,使用其中一个只需调整一行代码,非常简单
现在可以运行模型,通过InteractiveSession
sess=tf.InteractiveSession()
初始化变量
tf.global_variables_initializer().run()
训练1000次
for _ in range(1000):
batch_xs,batch_ys=mnist.train.next_batch(100)
sess.run(train_step,feed_dict=x:batch_xs,y_:batch_ys)
循环中的每一步,随机取100个数据点为一个批次,作为训练。
使用小批次的随机数据称为随机训练stochastic training,理想化的来讲,应该使用所有的为每一步训练,但是这样是昂贵的,
所以,每次使用一个不同子集,这样运算成本低廉,而且同样有效
评估模型
tf.argmax是一个非常有用的方法,它给出张量tensor中沿着某个轴最高条目的索引(未明白),例如tf.argmax(y,1)是模型预测的输出label,tf.argmax(y_,1)是真实的label,使用tf.equal检验预测与真实是否相匹配
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
tf.equal返回一列boolean, 我们转换为0,1,计算平均值:
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
最后运行计算图获取精确值:
print(sess.run(accuracy,feed_dict=x:mnist.test.images,y_:mnist.test.labels))
准确度为92%
这个结果是否足够好呢?不是的,事实上是非常low的,这是因为我们使用了一个简单的模型,稍微改变可以达到97%,最好的模型可以达到99.7%
重要的是我们在这个模型中学到的东西。
完整代码:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
FLAGS = None
def main(_):
# Import data
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.matmul(x, W) + b
# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])
# The raw formulation of cross-entropy,
#
# tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
# reduction_indices=[1]))
#
# can be numerically unstable.
#
# So here we use tf.nn.softmax_cross_entropy_with_logits on the raw
# outputs of 'y', and then average across the batch.
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict=x: batch_xs, y_: batch_ys)
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict=x: mnist.test.images,
y_: mnist.test.labels))
if __name__ == '__main__':
# argparse模块,python用于解析命令行参数
parser = argparse.ArgumentParser()
# 指定数据集加载目录为MNIST_data
parser.add_argument('--data_dir', type=str, default='MNIST_data',
help='Directory for storing input data')
FLAGS, unparsed = parser.parse_known_args()
tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
以上是关于TensorFlow学习笔记MNIST手写数字识别的主要内容,如果未能解决你的问题,请参考以下文章
学习笔记TF024:TensorFlow实现Softmax Regression(回归)识别手写数字
TensorFlow入门实战|第1周:实现mnist手写数字识别