MNIST 是一个入门级计算机视觉数据集,包含了不少手写数字图片,如图所示:python
数据集中包含了图片和对应的标注,在 TensorFlow 中提供了这个数据集,咱们能够用以下方法进行导入:算法
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('MNIST_data/', one_hot=True) print(mnist)
输出结果以下:网络
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 Datasets(train=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x101707ef0>, validation=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x1016ae4a8>, test=<tensorflow.contrib.learn.python.learn.datasets.mnist.DataSet object at 0x1016f9358>)
在这里程序会首先下载 MNIST 数据集,而后解压并保存到刚刚制定好的 MNIST_data 文件夹中,而后输出数据集对象。机器学习
数据集中包含了 55000 行的训练数据集(mnist.train)、5000 行验证集(mnist.validation)和 10000 行的测试数据集(mnist.test),文件以下所示:函数
正如前面提到的同样,每个 MNIST 数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。咱们把这些图片设为 xs,把这些标签设为 ys。训练数据集和测试数据集都包含 xs 和 ys,好比训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels,每张图片是 28 x 28 像素,即 784 个像素点,咱们能够把它展开造成一个向量,即长度为 784 的向量。性能
因此训练集咱们能够转化为 [55000, 784] 的向量,第一维就是训练集中包含的图片个数,第二维是图片的像素点表示的向量。学习
Softmax 能够当作是一个激励(activation)函数或者连接(link)函数,把咱们定义的线性函数的输出转换成咱们想要的格式,也就是关于 10 个数字类的几率分布。所以,给定一张图片,它对于每个数字的吻合度能够被 Softmax 函数转换成为一个几率值。Softmax 函数能够定义为:测试
展开等式右边的子式,能够获得:优化
好比判断一张图片中的动物是什么,可能的结果有三种,猫、狗、鸡,假如咱们能够通过计算得出它们分别的得分为 3.二、5.一、-1.7,Softmax 的过程首先会对各个值进行次幂计算,分别为 24.五、164.0、0.18,而后计算各个次幂结果占总次幂结果的比重,这样就能够获得 0.1三、0.8七、0.00 这三个数值,因此这样咱们就能够实现差异的放缩,即好的更好、差的更差。编码
若是要进一步求损失值能够进一步求对数而后取负值,这样 Softmax 后的值若是值越接近 1,那么获得的值越小,即损失越小,若是越远离 1,那么获得的值越大。
首先导入 TensorFlow,命令以下:
import tensorflow as tf
接下来咱们指定一个输入,在这里输入即为样本数据,若是是训练集那么则是 55000 x 784 的矩阵,若是是验证集则为 5000 x 784 的矩阵,若是是测试集则是 10000 x 784 的矩阵,因此它的行数是不肯定的,可是列数是肯定的。
因此能够先声明一个 placeholder 对象:
x = tf.placeholder(tf.float32, [None, 784])
这里第一个参数指定了矩阵中每一个数据的类型,第二个参数指定了数据的维度。
接下来咱们须要构建第一层网络,表达式以下:
这里其实是对输入的 x 乘以 w 权重,而后加上一个偏置项做为输出,而这两个变量实际是在训练的过程当中动态调优的,因此咱们须要指定它们的类型为 Variable,代码以下:
w = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10]))
接下来须要实现的就是上图所述的公式了,咱们再进一步调用 Softmax 进行计算,获得 y:
y = tf.nn.softmax(tf.matmul(x, w) + b)
经过上面几行代码咱们就已经把模型构建完毕了,结构很是简单。
为了训练咱们的模型,咱们首先须要定义一个指标来评估这个模型是好的。其实,在机器学习,咱们一般定义指标来表示一个模型是坏的,这个指标称为成本(cost)或损失(loss),而后尽可能最小化这个指标。可是这两种方式是相同的。
一个很是常见的,很是漂亮的成本函数是“交叉熵”(cross-entropy)。交叉熵产生于信息论里面的信息压缩编码技术,可是它后来演变成为从博弈论到机器学习等其余领域里的重要技术手段。它的定义以下:
y 是咱们预测的几率分布, y_label 是实际的分布,比较粗糙的理解是,交叉熵是用来衡量咱们的预测用于描述真相的低效性。
咱们能够首先定义 y_label,它的表达式是:
y_label = tf.placeholder(tf.float32, [None, 10])
接下来咱们须要计算它们的交叉熵,代码以下:
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_label * tf.log(y), reduction_indices=[1]))
首先用 reduce_sum() 方法针对每个维度进行求和,reduction_indices 是指定沿哪些维度进行求和。
而后调用 reduce_mean() 则求平均值,将一个向量中的全部元素求算平均值。
这样咱们最后只须要优化这个交叉熵就行了。
因此这样咱们再定义一个优化方法:
train = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
这里使用了 GradientDescentOptimizer,在这里,咱们要求 TensorFlow 用梯度降低算法(gradient descent algorithm)以 0.5 的学习速率最小化交叉熵。梯度降低算法(gradient descent algorithm)是一个简单的学习过程,TensorFlow 只需将每一个变量一点点地往使成本不断下降的方向移动便可。
定义好了以上内容以后,至关于咱们已经构建好了一个计算图,即设置好了模型,咱们把它放到 Session 里面运行便可:
with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for step in range(total_steps + 1): batch_x, batch_y = mnist.train.next_batch(batch_size) sess.run(train, feed_dict={x: batch_x, y_label: batch_y})
该循环的每一个步骤中,咱们都会随机抓取训练数据中的 batch_size 个批处理数据点,而后咱们用这些数据点做为参数替换以前的占位符来运行 train。
这里须要一些变量的定义:
batch_size = 100 total_steps = 5000
测试模型
那么咱们的模型性能如何呢?
首先让咱们找出那些预测正确的标签。tf.argmax() 是一个很是有用的函数,它能给出某个 Tensor 对象在某一维上的其数据最大值所在的索引值。因为标签向量是由 0,1 组成,所以最大值 1 所在的索引位置就是类别标签,好比 tf.argmax(y, 1) 返回的是模型对于任一输入 x 预测到的标签值,而 tf.argmax(y_label, 1) 表明正确的标签,咱们能够用 tf.equal() 方法来检测咱们的预测是否真实标签匹配(索引位置同样表示匹配)。
correct_prediction = tf.equal(tf.argmax(y, axis=1), tf.argmax(y_label, axis=1))
这行代码会给咱们一组布尔值。为了肯定正确预测项的比例,咱们能够把布尔值转换成浮点数,而后取平均值。例如,[True, False, True, True] 会变成 [1, 0, 1, 1] ,取平均值后获得 0.75。
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
最后,咱们计算所学习到的模型在测试数据集上面的正确率,定义以下:
steps_per_test = 100 if step % steps_per_test == 0: print(step, sess.run(accuracy, feed_dict={x: mnist.test.images, y_label: mnist.test.labels}))
这个最终结果值应该大约是92%。
这样咱们就经过完成了训练和测试阶段,实现了一个基本的训练模型,后面咱们会继续优化模型来达到更好的效果。
运行结果以下:
0 0.453 100 0.8915 200 0.9026 300 0.9081 400 0.9109 500 0.9108 600 0.9175 700 0.9137 800 0.9158 900 0.9176 1000 0.9167 1100 0.9186 1200 0.9206 1300 0.9161 1400 0.9218 1500 0.9179 1600 0.916 1700 0.9196 1800 0.9222 1900 0.921 2000 0.9223 2100 0.9214 2200 0.9191 2300 0.9228 2400 0.9228 2500 0.9218 2600 0.9197 2700 0.9225 2800 0.9238 2900 0.9219 3000 0.9224 3100 0.9184 3200 0.9253 3300 0.9216 3400 0.9218 3500 0.9212 3600 0.9225 3700 0.9224 3800 0.9225 3900 0.9226 4000 0.9201 4100 0.9138 4200 0.9184 4300 0.9222 4400 0.92 4500 0.924 4600 0.9234 4700 0.9219 4800 0.923 4900 0.9254 5000 0.9218
结语
本节经过一个 MNIST 数据集来简单体验了一下真实数据的训练和预测过程,可是准确率还不够高,后面咱们会学习用卷积的方式来进行模型训练,准确率会更高。