使用TensorFlow实现手写识别(Softmax)

准备工作

由于将TensorFlow安装到了Conda的tensorflow环境,虽然可以用Jupyter notebook打开,但是没有提示,写代码不方便,所以使用PyCharm进行编写。设置如下:

  • 如果是新建项目,在选择使用python的地址的地方,找到anaconda目录,点击envs ----> tensorflow -----> bin -----> python2.7(我的是2.7)
  • 如果已经创建了项目,但是没有用该环境下的python,就进入项目的设置里,找到project interpreter这一项,做同上面相同的事。

MNIST数据集简介

该数据集是机器学习入门级别的数据集,也是tensorflow在教程中使用的数据集。包含手写数字图片以及图片的标签(标签告诉我们图片中是数字几)。数据集分为三部分:

mnist.train(训练数据),包含55000个数据点;mnist.test(测试数据),包含10000个数据点;mnist.validation(验证数据),包含5000个数据点。

开始之前

先将下面代码拷贝到pycharm中,试试能否运行(不必懂,主要先试运行,测试环境是否有问题)。

import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) x = tf.placeholder(tf.float32, [None, 784]) W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10])) y = tf.nn.softmax(tf.matmul(x, W) + b) # Training y_ = tf.placeholder(tf.float32, [None, 10]) cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) # run init = tf.global_variables_initializer()

sess = tf.Session() sess.run(init) for i in range(1000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) # evaluate 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}))

分析模型

每个图片的大小都由28*28=784个像素点组成,可以抽象成一个784维的向量,每一位的值代表像素强度。下图横坐标代表图片索引,纵坐标代表每个像素值。

索引-像素图

每个图片有一个标签,代表它是数字几,那么下图的横坐标代表图片索引,纵坐标代表数字几。

索引-标签图

我们给每个数字的每个像素都标一个权重,如果是这个数字该有的部分,则为正圈中,如果是不该有的部分,则标为负权重,如下图,蓝色代表正权重,红色代表负权重。

数字权重图

我们再给每个像素添加一些偏差b,则可以得到下面公式

线性函数公式

再用softmax函数将evidence转化成我们想要的一系列可能性y

softmax函数

为啥这么做呢,假设输入一个手写图片,那么像素点值大的地方肯定是那个数字,把我们刚才设置的所有权重都和这个图的像素点做一下上面公式的运算,就能得出10个图,最后再看这些图,假设这个图是1,那么它和1的权重图运算后是1的部分就会变更大更黑,是1的可能性也就越大,我们用softmax函数的目的就是给出没种运算后的可能性,根据one-hot编码让我们知道它是数字几。

用图表示会更形象:

softmax regression

softmax写成公式图

向量化

开始

新建python文件,导入tensorflow,输入下面两行,可以自动下载并读取mnist数据集:

import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data", one_hot=True)

写完这里有个疑问,如果我想读取别的数据集怎么办?追踪input方法,发现一大堆读取的代码,为了不偏离主线,先放过,过后查询。

还有一个发现,括号里的one_hot=True没有空格,加了空格反而会显示:unexpected spaces around keyword/parameter equals,所以看来和java不同,键值之间的等号不能加空格。

还有,import语句一定写在最上面,虽然这是常识,不过由于教程里面是先讲的自动下载数据集,然后讲的import tensorflow,所以我还是试了试如果把import放下面咋办,果然报错了。

设置占位符x

x = tf.placeholder(tf.float32, [None, 784])

tensorflow是需要我们先绘制一个dataflow graph,这个graph我理解其实就是设置变量、参数、用的激活函数、损失函数等等,把公式先写好,未知数用一个占位符先占着,这里的x就是上图中的[x1,x2,x3,x4],None代表该维度可以任意长。

设置变量

W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10]))

W的第一个维度代表784个像素,第二个维度代表10个类,初始化成0。

b的维度代表10个类,初始化成0。

设置softmax求出结果

y = tf.nn.softmax(tf.matmul(x, W) + b)

训练

在tensorflow里,我们也先用占位符来表示预期结果

y_ = = tf.placeholder(tf.float32, [None, 10])

为了训练我们的模型,通常会定义它怎么样才算一个好模型,在机器学习里,我们通过比对模型输出和预期值的差异,成为损失函数或者代价函数,差异越小越好,“交叉熵”是经常使用的损失函数,公式如下:

交叉熵公式

y是预期分布,y'是真实分布。

用tensorflow实现交叉熵函数:

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

因为这种写法得到的分布值不平稳,所以常用 tf.nn.softmax_cross_entropy_with_logits函数来得到平稳的结果

到这里,tensorflow知道了整个graph,它会自动通过反向传播算法找到让损失函数最小的变量值,它还提供了一些优化算法来帮助让损失函数最小。如梯度下降法:

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

run tensorflow

1、初始化变量

init = tf.global_variables_initializer()

这里只是定义了,还没有执行初始化。

2、创建session,执行初始化

sess = tf.Session() sess.run(init)

3、训练

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

运行1000次,每次采样100个x和y,放在batch里,替换占位符(相当于赋值给占位符)。

4、衡量模型

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}))

tf.argmax(y, 1)第二个参数代表维度,correct_prediction给了我们一个布尔列表;

accuracy一句将布尔集合转换为数字集合,比如[True, True, False, False, False],转换为[1, 1, 0, 0, 0],正确率为0.4,对所有正确率求平均数;

最后一句,运行精度计算,得到精度。

遇到的问题

1、对他的dimension表示疑惑,可能受其他语言影响,认为[1,2,3,...,784]是一个一维数组,[1][2]才是2维数组,但是它说了个784-dimensional vector,一下子把我搞蒙了,不过后来似乎转过弯了,[1,2,3,...,784]就是一个784维的向量,不是要在空间画出来,只是这样表示而已,[784,10]代表784列10行的一个二维矩阵。

2、在运行后,发出警告,说The TensorFlow library wasn't compiled to use SSE4.1/SSE4.2 /AVX/AVX2/FMA instructions, but these are available on your machine and could speed up CPU computations.

那么怎么使用这些提高CPU计算速度呢,到StackOverFlow上查了一下,说是最好从sources编译它,应该就是说安装的时候从sources安装,但是我是通过anaconda安装的,等实在忍不下去这个速度了再从sources编译吧,就先不在这里耗时了,毕竟我花了两天才安装好它……

后续将补充的

今天的主要目的是跑通并理解整个程序,所以没有深究所有算法的原理,接下来的几天将进行下面知识补充:

softmax regression

Python数组问题

交叉熵

激活函数

反向传播算法

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-10-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏python读书笔记

python 数据分析基础 day18-使用pandas进行数据清洗以及探索

今天是读《python数据分析基础》的第18天,读书笔记的内容是使用pandas进行数据清洗以及探索 由于原始数据在某种程度上是“脏”的,原始数据并不能完全使...

3528
来自专栏IT派

从框架优缺点说起,这是一份TensorFlow入门极简教程

这一系列教程分为 6 部分,从为什么选择 TensorFlow 到卷积神经网络的实现,介绍了初学者所需要的技能。机器之心在本文介绍了 PyTorch 和 Caf...

962
来自专栏GAN&CV

从0到1实现YOLO v3(part two)

本部分是 从0到1 实现YOLO v3 的第二部分,前两部分主要介绍了YOLO的工作原理,包含的模块的介绍以及如何用pytorch搭建完整的YOLOv3网络结构...

1124
来自专栏李智的专栏

Deep learning基于theano的keras学习笔记(0)-keras常用的代码

这里不推荐使用pickle或cPickle来保存Keras模型。 1. 一般使用model.save(filepath)将Keras模型和权重保存在一个HD...

741
来自专栏WindCoder

TensorFlow入门:一篇机器学习教程

TensorFlow是一个由Google创建的开源软件库,用于实现机器学习和深度学习系统。这两个名称包含一系列强大的算法,它们共享一个共同的挑战——让计算机学习...

961
来自专栏机器之心

从框架优缺点说起,这是一份TensorFlow入门极简教程

2008
来自专栏mathor

“达观杯”文本智能处理挑战赛

 由于提供的数据集较大,一般运行时间再10到15分钟之间,基础电脑配置在4核8G的样子(越消耗内存在6.2G),因此,一般可能会遇到内存溢出的错误

892
来自专栏云时之间

深度学习与神经网络:基于自建手写字体数据集上的模型测试

883
来自专栏简书专栏

基于jieba、gensim.word2vec、LogisticRegression的文档分类

建议读者安装anaconda,这个集成开发环境自带了很多包。 到2018年8月30日仍为最新版本的anaconda下载链接: https://pan.baid...

1004
来自专栏北京马哥教育

python实现拼写检查器21行轻松搞定

除了这段代码外,作为机器学习的一部分,肯定还应该有大量的样本数据,准备了big.txt作为我们的样本数据。

1284

扫码关注云+社区