使用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
    • 初始化变量
init = tf.global_variables_initializer()

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

  • 创建session,执行初始化
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})

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

  • 衡量模型
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,对所有正确率求平均数;
最后一句,运行精度计算,得到精度。

遇到的问题

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

  • 在运行后,发出警告,说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数组问题
  • 交叉熵
  • 激活函数
  • 反向传播算法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 一.目的 类似学习开发语言的第一个代码,Hello World! 机器学习中,我们通过MNIST来学习手写输入法的...
    Coming0524阅读 6,467评论 2 8
  • 简单线性回归 import tensorflow as tf import numpy # 创造数据 x_dat...
    CAICAI0阅读 3,538评论 0 49
  • MNIST For ML Beginners 这个教程是给机器学习和TensorFlow的新手准备的,如果你已经知...
    迅速傅里叶变换阅读 1,987评论 0 3
  • 1 我们身边总有那么一个两个三个四个爱炫耀的人,包括我们自己有时也会忍不住炫耀点拿得出手东西。有时候想想,炫耀这行...
    老邵阅读 551评论 0 3
  • 组织企业去淳化做公益。其实早早就联系好了学校,只待合适的时候拉着物资过去。终于,经过各方的努力协调,这个事敲定到今...
    白杨树在北方阅读 135评论 1 1