<script type="text/javascript" async
src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
github 参考地址 https://github.com/orangercat/Tensorflow_learning
MINST数据集介绍
MNIST是一个标准的手写字符测试集,收集者是人工智能领域著名的科学家,现在最火的深度学习网络Convulution Nueral Networks的创始人,现任Facebook AI实验室的主任 -- Yann LeCun
下载MNIST数据集,数据在 http://yann.lecun.com/exdb/mnist/ 上
import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
下载下来的数据集可被分为三部分:55000行训练用点数据集(mnist.train),10000行测试数据集 (mnist.test),以及5000行验证数据集(mnist.validation).这样的切分很重要:在机器学习模型设计时必须有一个单独的测试数据集不用于训练而是用来评估这个模型的性能,从而更加容易把设计的模型推广到其他数据集上(泛化).
每一个 MNIST 数据单元有两部分组成:一张包含手写数字 的图片和一个对应的标签.我们把这些图片设为“xs”,把这些标签设为“ys”.训练数据集和测试数据集都包含 xs 和 ys,比如训练数据集的图片是mnist.train.images ,训练数据集的标签是mnist.train.labels.
每一张图片包含 28 × 28 像素.我们可以用一个数字数组来表示这张图片.因此,每张图片可以理解为28*28=784的数组,目前每个数组的值是0与1之间(针对MNIST,即像素点是否有点),而对应MNIST数据集的标签是介于0到9之间的数字,目前使用的是"one-hot vectors",即标签3将表示为([0,0,0,1,0,0,0,0,0,0]) (此中文PDF中翻译有问题,元素是10个元素而不是11个,此概念在数字集成电路中有,虽然占用寄存器,但是运算较快,对应的编码有格雷码之类),因此,mnist.train.labels是一个[55000, 10]的数字矩阵.
Softmax 介绍
softmax 回归(softmax regression)分两步:首先对输入被分类对象属于某个类的 “证据”相加求和,然后将这个“证据”的和转化为概率.我们使用加权的方法来累积计算一张图片是否属于某类的“证据”。如果图片的像 素强有力的体现该图不属于某个类,则权重为负数,相反如果这个像素拥有有利的证据支持这张图片属于这个类,那么权值为正.
我们使用加权的方法来累积计算一张图片是否属于某类的“证据”。如果图片的像 素强有力的体现该图不属于某个类,则权重为负数,相反如果这个像素拥有有利的证据 支持这张图片属于这个类,那么权值为正.
对于 softmax 回归模型可以用下面的图解释,对于输入的xs加权求和,再分别加上一个b偏置量,最后再输入到softmax函数中:
$$y = softmax(W_x + b)$$
利用Softmax实现学习MNIST步骤
- 实现回归模型
导入Tensorflow
import tensorflow as tf
已经确定利用softmax来实现回归模型,每张图片可以表示成一个784bit的数组,在tensorflow里面我们建立为[None,784] (按照我的理解None代表模型所针对的图片数量没有确定), Tensorflow中含义为为2-D Tensorflow floating-point numbers,with a shape [None,784]
x = tf.placeholder("float",[None,784])
模型中需要权重值和偏置量,当然我们可以把它们当做是另外的输入(使用占位符),但 TensorFlow 有一个更好的方法来表示它们:Variable.一个Variable代表一个可修改的张量,存在在 TensorFlow 的用于 述交互性操作的图中.它们可以用于计算输入值,也可以在计算中被修改.对于各种机器学习应用,一般都会有模型参数,可以用Variable表示.
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
我们赋予tf.Variable 不同的初值来创建不同的Variable:在这里,我们都用全为零 的张量来初始化W和b.因为我们要学习W和b的值,它们的初值可以随意设置.注意,W的维度是[784,10],因为我们想要用784维的图片向量乘以它以得到一个10维的证据值向量(按照我的理解,这个就是代表一个图片针对10维结果的一个权重列表),每一位对应不同数字类.b的形状是[10],所以我们可以直接把它加到输出上面.(b为偏置量)
现在,就可以实现softmax回归模型
y = tf.nn.softmax(tf.matmul(x,W) + b)
- 训练模型
为了训练我们的模型,我们首先需要定义一个指标来评估这个模型是好的.其实,在机器学习,我们通常定义指标来表示一个模型是坏的,这个指标称为成本(cost)或损失(loss),然后尽量最小化这个指标.但是,这两种方式是相同的.
一个非常常见的,非常漂亮的成本函数是“交叉熵”(cross-entropy).交叉熵产生于信 息论里面的信息压缩编码技术,但是它后来演变成为从博弈论到机器学习等其他领域 里的重要技术手段.它的定义如下:
$$H_(y'){y} = - \sum_{i=1}y'_i{log(y_i)}$$
y 是我们预测的概率分布,y′是实际的分布(我们输入的one-hot vector).
为了计算交叉熵,我们首先需要添加一个新的占位符用于输入正确值:
y_ = tf.placeholder("float",[None,10])
计算交叉熵
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
我们要求 TensorFlow 用梯度下降算法(gradient descent algorithm)以 0.01 的学习速率最小化交叉熵.梯度下降算法(gradient descent algorithm)是一个简单的 学习过程,TensorFlow 只需将每个变量一点点地往使成本不断降低的方向移动.当然 TensorFlow 也 供了其他许多优化算法:只要简单地调整一行代码就可以使用其他的 算法.
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
TensorFlow 在这里实际上所做的是,它会在后台给 述你的计算的那张图里面增 加一系列新的计算操作单元用于实现反向传播算法和梯度下降算法.然后,它返回给你 的只是一个单一的操作,当运行这个操作时,它用梯度下降算法训练你的模型,微调你的变量,不断减少成本.
现在,我们已经设置好了我们的模型.在运行计算之前,我们需要添加一个操作来初始化我们创建的变量:
init = tf.initialize_all_variables()
现在我们可以在一个Session里面启动我们的模型,并且初始化变量:
sess = tf.Session()
sess.run(init)
开始训练模型,让模型训练1000次
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})
该循环的每个步骤中,我们都会随机抓取训练数据中的 100 个批处理数据点,然后 我们用这些数据点作为参数替换之前的占位符来运行train_step.
- 评估模型
输入最有可能对应的那些标签,而tf.argmax(y_,1)代表正确的标签.我们可以用tf.equal来检测我们的预测是否真实标签匹配.
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
这行代码会给我们一组布尔值.为了确定正确预测项的比例,我们可以把布尔值转换成浮点数,然后取平均值.
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
最后,计算学习到的模型在测试数据上的准确率
print (sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
0.9209