TensorFlow 与深度学习 (6) 阅读代码
单层神经网络的代码已经写好了。请打开
mnist_1.0_softmax.py
文件并按说明进行操作。
你在本节的任务是理解代码,以便之后对其改进。
你应该看到,在文档中的说明和启动代码只有微小的差别。它们对应于可视化的函数,并且在注释中被标记。此处可忽略。
1 | import tensorflow as tf |
我们首先定义 TensorFlow 的变量和占位符。变量是你希望训练算法为你确定的所有的参数,在我们的例子中参数有权重和偏置。
占位符是在训练期间填充实际数据的参数,通常是训练图像。持有训练图像的张量的形式是 [None, 28, 28, 1],其中的参数代表
- 28, 28, 1: 图像是 28x28 像素 x 1(灰度)。最后一个数字对于彩色图像是 3,但在这里不是必须的。
- None: 这是代表 mini-batch 中的图像数量。在训练时可以得到。
1 | # model |
第一行是我们单层神经网络的模型。公式是我们在前面的理论部分建立的。tf.reshape
命令将我们的 28×28 的图像转化成 784 个像素的单向量。在 reshape 中的 “-1”
意思是:“帮我算出这个数,只有一种可能”。实际上,这就是 mini-batch
中的图像数量。
然后,我们需要一个额外的占位符用于存放训练集的 labels,这些 label 与训练图像一起被提供。
现在我们有模型预测和正确的
label,可以计算交叉熵了。tf.reduce_sum
是对向量的所有元素求和。
最后两行计算了正确识别数字的百分比。这是留给读者的理解练习,参考 TensorFlow API reference。你可以先跳过这部分。
1 | optimizer = tf.train.GradientDescentOptimizer(0.003) |
这才是 TensorFlow 发挥力量的地方。你选择一个 optimiser(有许多可供选择)并用它最小化 cross-entrophy loss。在这一步中,TensorFlow 计算损失函数对于所有权重和偏置的偏导数,也就是梯度。这是一个形式推导的过程,而非耗时的数值方法计算。
梯度然后被用来更新权重和偏置,学习率为 0.003。
最后,是时候来启动训练循环(training loop)了!目前为止,这些 TensorFlow 指令已经在内存中准备了一个计算图,但是还未开始计算。
TensorFlow 的延迟执行(deferred execution)”模型:TensorFlow 是为分布式计算构建的。它必须知道你要计算的是什么、你的执行图(execution graph),然后才开始发送计算任务到各种计算机。这就是为什么它有一个延迟执行模型——你首先使用 TensorFlow 函数在内存中创造一个计算图,然后启动一个执行 Session 并且使用 Session.run 执行实际计算任务。此刻,图形无法被更改。
多亏了这个模型,TensorFlow 能接管分布式计算的大部分逻辑。举例而言,假如你指示它在计算机 1 上运行计算的一部分 ,而在计算机 2 上运行另一部分,它可以自动进行必要的数据传输。
计算需要将实际数据填进你在 TensorFlow 代码中定义的占位符。这是以 Python 的字典类型给出的,其中 key 是占位符的名字。
1 | sess = tf.Session() |
这里的 train_step
是我们之前定义的,意思是让 TensorFlow
最小化交叉熵。这就是计算梯度以及更新权重、偏置的那一步。
最终,我们还需要显示一些值,以便我们看到模型性能的变化。
在训练循环里,我们用这行代码来计算准确度和交叉熵(例如每 10 次迭代):
1 | # success ? |
通过在 feed_dict
中提供测试数据(而不是训练数据),我们可以对测试数据进行同样的计算(例如每
100 次迭代计算一次。有 10,000 个测试数字,所以会耗费一些时间):
1 | # success on test data ? |
TensorFlow 和 Numpy 是朋友:在准备计算图时,你只需要操纵 TensorFlow 张量和命令,比如
tf.matmul
,tf.reshape
等。然而,只要执行
Session.run
命令,它的返回值就是 Numpy 张量,即 Numpy 可以使用的numpy.ndarray
对象以及基于它的所有科学计算库。这就是为什么我们能用 matplotlib(基于 Numpy 的标准 Python 绘图库)为实验构建实时可视化。
这个简单的模型已经能识别 92% 的数字了!不错,但是你现在要显著地改善它。