实验:走进代码
一层神经网络的代码已经编写好了。
请打开mnist_1.0_softmax.py文件,里面有解释。
(所有文件的下载链接在第一章有)
本节中的任务是理解这份原始的代码,以便随后对其进行改进。
您应该看到,文件中的解释和启动器代码之间只有很小的差异。
它们与用于可视化的函数对应,并在注释中作为相应的标记。
你可以忽略它们。
mnist_1.0_softmax.py
import tensorflow as tf X = tf.placeholder(tf.float32, [None, 28, 28, 1]) W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10])) init = tf.initialize_all_variables()
首先定义 TensorFlow变量和placeholders占位符。
TensorFlow变量是您希望训练算法为您确定的所有参数。
在这个例子中,我们的权重和偏置是要确定的参数。
占位符是在训练期间填充实际数据的参数,通常是训练图像。
训练图像的TensorFlow张量的形状是[None,28,28,1],它代表:
- 28, 28, 1:我们的图像是28×28像素×1值每像素(灰度)。最后一个数字是通道数,灰度图通道数只有1,而彩色图像的通道数有3(RGB 3通道),在这里我们的手写数字图片是灰度图,所以是1。
- None: 这个维度将是Mini小批量处理中的图像数量。它将在训练时间被知道
# model Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, 784]), W) + b) # placeholder for correct labels Y_ = tf.placeholder(tf.float32, [None, 10]) # loss function cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y)) # % of correct answers found in batch is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1)) accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
第一行是我们的一层神经网络的模型。Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, 784]), W) + b)
这个公式是我们在前面的理论部分建立的公式。
tf.reshape命令将28x28图像矩阵转换为784像素的单个矢量。
“tf.reshape”命令中的“-1”意味着“让程序自己计算相应的大小(只能有一个-1,多个-1将导致不确定的结果,程序会出错)”。在实际运行中,-1这个参数将会是一个小批量图像的数量。
然后,我们需要一个额外的placeholders占位符去放置真实的的训练集的标签,真实的的训练集的标签与训练图像对应。
现在,我们有了模型预测的结果和正确的标签,所以我们可以计算交叉熵。tf.reduce_mean把向量的所有元素相加。
最后两行计算正确识别数字的百分比。
最后两个使用TensorFlow 的函数,留作练习供读者理解。你也可以跳过它们。(作者TM偷懒了)
我补上:
# tf.equal:比较两个值,对应元素相同的返回1,不同的返回0 # 所以correct_prediction 向量的元素为:0 (不同) 或 1 (相同) # tf.argmax(Y, 1),返回Y里面的最大值 correct_prediction = tf.equal(tf.argmax(Y, 1), tf.argmax(Y_, 1)) # tf.cast:用于改变某个张量的数据类型 # tf.reduce_mean:计算向量的平均值 # 训练模型精度 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))optimizer = tf.train.GradientDescentOptimizer(0.003) train_step = optimizer.minimize(cross_entropy)
这就是TensorFlow神器的地方。
您可以选择一个优化器(有很多可用的),并要求它最小化交叉熵损失。
(tensorflow学习笔记(3):优化器optimizer:https://blog.csdn.net/qq_39683748/article/details/83932077)
在这个步骤中,TensorFlow计算损失函数相对于所有权重和所有偏置的偏导数(梯度)。这是一个形式上的推导,而不是一个太耗时的数值推导。
然后使用梯度来更新权重和偏差。学习率是0.003。
最后,是运行训练循环的时候了。到目前为止,所有TensorFlow指令都在内存中准备计算图,但是还没有计算任何内容。
TensorFlow的“延迟执行”模型:TensorFlow是为分布式计算而构建的。
在开始实际向各种计算机发送计算任务之前,它必须知道要计算什么,即执行图。
这就是它有一个延迟执行模型的原因,其中首先使用TensorFlow函数在内存中创建计算图,然后启动执行Session并使用Session.run执行实际计算。在这一点上,图形不能再被改变。
由于这个模型,TensorFlow可以接管很多分布式计算的后勤工作。
例如,如果您指示在计算机1上运行一部分计算,在计算机2上运行另一部分,则可以使必要的数据传输自动发生。
计算需要将实际数据输入到在TensorFlow代码中定义的占位符中。这是以Python字典的形式提供的,其中键是占位符的名称。
sess = tf.Session() sess.run(init) for i in range(1000): # load batch of images and correct answers batch_X, batch_Y = mnist.train.next_batch(100) train_data={X: batch_X, Y_: batch_Y} # train sess.run(train_step, feed_dict=train_data)
当我们要求TensorFlow最小化交叉熵时,这里就会执行上面的train_step。这是计算梯度和更新权重和偏差的步骤。
最后,我们还需要计算用于显示的两个值,以便能够及时地知道模型的性能。
在训练循环中使用该代码在训练集数据上计算精度和交叉熵(例如,每10次迭代):
# success ? a,c = sess.run([accuracy, cross_entropy], feed_dict=train_data)
可以通过在feed字典中提供测试集数据而不是训练集数据来对测试数据进行计算
(例如,每100次迭代执行一次)。有10000个测试数字,所以这需要一些时间:
# success on test data ? test_data={X: mnist.test.images, Y_: mnist.test.labels} a,c = sess.run([accuracy, cross_entropy], feed=test_data)
TensorFlow和Numpy这两个模块互相兼容度很高:
在准备计算图时,您只需要操作TensorFlow张量和命令,比如tf.matmul、tf.reshape等等。
但是,只要执行
Session.run
命令,它返回的值就是Numpy张量,即numpy.ndarray对象,Numpy和所有基于它的科学编译库都可以使用这些对象。这就是使用基于Numpy的标准Python绘图库matplotlib为这个实验室构建实时可视化的方法。这个简单的模型已经识别出92%的数字。效果不错,但你现在还能显著改善这一点。