2·MNIST机器学习入门

2016-11-19  本文已影响0人  三千清华少女的梦

MNIST数据集

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

Softmax回归介绍

实现回归模型

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

x不是一个特定的值,而是一个占位符placeholder,我们在TensorFlow运行计算时输入这个值。我们希望能够输入任意数量的MNIST图像,每一张图展平成784维的向量。我们用2维的浮点数张量来表示这些图,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度可以是任何长度的。)

W = tf.Variable(tf.zeros([784,10]))#W的维度是[784,10],因为我们想要用784维的图片向量乘以它以得到一个10维的证据值向量
b = tf.Variable(tf.zeros([10]))#b的形状是[10],所以我们可以直接把它加到输出上面。

一个Variable代表一个可修改的张量,存在在TensorFlow的用于描述交互性操作的图中。它们可以用于计算输入值,也可以在计算中被修改。对于各种机器学习应用,一般都会有模型参数,可以用Variable表示。

y = tf.nn.softmax(tf.matmul(x,W) + b)#输出的y跟x保持同样的第一维的个数

tf.matmul(​​x,W)表示x乘以W,这里x是一个2维张量拥有多个输入。然后再加上b,把和输入到tf.nn.softmax函数里面。

训练模型

y 是我们预测的概率分布, y' 是实际的分布(我们输入的one-hot vector)。
比较粗糙的理解是,交叉熵是用来衡量我们的预测用于描述真相的低效性。

y_ = tf.placeholder("float", [None,10]) # y_就是上面的y',是一个输入的固定的值
cross_entropy = -tf.reduce_sum(y_*tf.log(y))# 是一个y的函数

tf.log计算 y 的每个元素的对数。
接下来,我们把y_的每一个元素和tf.log(y) 的对应元素相乘。
最后,用 tf.reduce_sum 计算张量的所有元素的总和。
注意,这里的交叉熵不仅仅用来衡量单一的一对预测和真实值,而是所有100幅图片的交叉熵的总和。对于100个数据点的预测表现比单一数据点的表现能更好地描述我们的模型的性能。

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)#定义了一个训练方法,在后面作为session.run()的参数

这里TensorFlow用梯度下降算法(gradient descent algorithm)0.01的学习速率最小化交叉熵
当然TensorFlow也提供了其他许多优化算法:只要简单地调整一行代码就可以使用其他的算法。

TensorFlow在这里实际上所做的是,它会在后台给描述你的计算的那张图里面增加一系列新的计算操作单元用于实现反向传播算法和梯度下降算法。然后,它返回给你的只是一个单一的操作,当运行这个操作时,它用梯度下降算法训练你的模型,微调你的变量,不断减少成本。

init = tf.initialize_all_variables()#定义一个初始化的函数动作,将前面定义的W和b初始化为零
sess = tf.Session()#定义一个session
sess.run(init)#启动这个session并初始化变量

会话(session):
客户端通过创建 会话 (session)和 TensorFlow 系统进行交互。一个由会话接口提供的主要的操作就是 Run ,以需要计算的输出名称和替换某些输出节点的张量的操作集合作为其参数输入。通过控制 Run 的参数,TensorFlow 的实现可以计算所有节点的必须执行传递闭包来计算需要的输出,然后安排执行合适节点来保证他们的依赖关系(即如果要计算到参数那一步,前面必须的步骤会自动完成)。大多数 TensorFlow 的使用都是针对一个图启动一个会话,然后执行整个图或者通过 Run 调用来执行分离的子图数千或者数百万次。

for i in range(1000):
      batch_xs, batch_ys = mnist.train.next_batch(100)#随机抓取训练数据mnist中的100个批处理数据点
      sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})#用这些数据点作为参数替换之前的占位符来运行train_step

设计placeholder节点的唯一的意图就是为了提供数据供给(feeding)的方法。placeholder节点被声明的时候是未初始化的, 也不包含数据, 如果没有为它供给数据, 则TensorFlow运算的时候会产生错误, 所以千万不要忘了为placeholder提供数据。

评估我们的模型

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))#比较两个有y和y_对应的标签序列,返回一个bool类型的序列
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))#cast()转换类型,reduce_mean()获得平均值
print (sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

我再来解读一下最后的run函数。
首先函数方法是accuracy,往前看发现引用了一个correct_prediction函数。查看correct_prediction函数,里面有两个参数yy_。往前看,y_是一个placeholdery_确定要传参数进来了。而y是一个函数式,查看此函数式发现需要用到x,再往前找到x定义的地方发现x是一个placeholder,也需要传参数进来,就此终于形成闭包。最终是两个placeholder,并且次序是先xy_,因此用feed_dict={x: mnist.test.images, y_: mnist.test.labels}

按照教程一步一步操作,每输进一行代码都要问一句为什么。不懂得地方仔细琢磨,要想会用tensorflow,必须先读懂它!最重要的一点就是理解tensorflow的闭包的概念!

上一篇 下一篇

猜你喜欢

热点阅读