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 基础学习五:MNIST手写数字识别

Tensorflow学习笔记:MNIST机器学习入门

TensorFlow入门实战|第1周:实现mnist手写数字识别

TensorFlow入门实战|第1周:实现mnist手写数字识别

TensorFlow入门实战|第1周:实现mnist手写数字识别