使用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

TensorFlow应用实战-9-生成音乐

生成音乐的python文件 # -*- coding: UTF-8 -*- """ 用训练好的神经网络模型参数来作曲 """ import pickle i...

3235
来自专栏机器之心

业界 | 探索Siri背后的技术:将逆文本标准化(ITN)转化为标签问题

2714
来自专栏IT派

TensorFlow中的那些高级API

摘要: 在这篇文章中,我们将看到一个使用了最新高级构件的例子,包括Estimator(估算器)、Experiment(实验)和Dataset(数据集)。值得注...

4475
来自专栏AI科技大本营的专栏

手把手教你自制编程AI:训练2小时,RNN就能写自己的代码

我们都知道,神经网络下围棋能赢柯洁、读X光照片好过医生、就连文本翻译上也快超过人类了……其实在写代码方面,神经网络也丝毫不落下风……用Linux源代码训练2小时...

3577
来自专栏云霄雨霁

加权有向图----单点最短路径问题(Dijkstra算法)

1530
来自专栏有趣的Python

TensorFlow应用实战-7-工具类与网络模型

编写转换midi到mp3的方法 # -*- coding: UTF-8 -*- import os import subprocess def conver...

2725
来自专栏社区的朋友们

深度学习入门实战(二):用TensorFlow训练线性回归

上一篇文章我们介绍了 MxNet 的安装,但 MxNet 有个缺点,那就是文档不太全,用起来可能是要看源代码才能理解某个方法的含义,所以今天我们就介绍一下 Te...

5.4K1
来自专栏崔庆才的专栏

自然语言处理中句子相似度计算的几种方法

1525
来自专栏算法channel

玩转Pandas,让数据处理更easy系列6

玩转Pandas系列已经连续推送5篇,尽量贴近Pandas的本质原理,结合工作实践,按照使用Pandas的逻辑步骤,系统地并结合实例推送Pandas的主要常用功...

772
来自专栏MelonTeam专栏

深度学习入门实战(二)

导语:上一篇文章我们介绍了MxNet的安装,但MxNet有个缺点,那就是文档不太全,用起来可能是要看源代码才能理解某个方法的含义,所以今天我们就介绍一下Te...

19810

扫描关注云+社区