您的位置:首页 > 其它

TensorsFlow学习笔记5----TensorFlow Mechanics 101基本运作方式

2017-05-04 08:44 686 查看
原文教程:tensorflow官方教程

翻译教程:极客学院

记录关键内容与学习感受。未完待续。。

TensorFlow Mechanics 101基本运作方式

代码:tensorflow/examples/tutorials/mnist/

——本教程的目标是展示如何使用tensorflow,利用MNIST数据集,训练和评估一个可以识别手写数字的简单的前馈神经网络。因此受众是对机器学习有经验并且对tensorflow感兴趣的用户。

——因此本教程并不是为了教授机器学习。

——请确定你已经看了安装教程

1、教程使用的文件

——-本教程参考一下文件:

文件目的
mnist.py这份代码建立了一个全连接模型
fully_connected_feed.py训练和建立MNIST模型的主要代码,以数据反馈字典的形式作为输入模型
.

——只要直接运行fully_connected_feed.py文件,就可以开始训练。

python fully_connected_feed.py


2、准备数据

——在机器学习中,MNIST是一个分类问题,这个问题是通过查看28x28像素点的手写数字的灰度图来决定这个数字图像所代表的是0到9中的哪个数字。



——更多信息获取点击Yann LeCun’s MNIST pageChris Olah’s visualizations of MNIST

2.1 下载

——在run_training()方法的一开始,input_data.read_data_sets()函数将确保正确的数据下载到你的本地训练文件夹下,并且解压数据返回一个含有DataSet实例的字典。

data_sets = input_data.read_data_sets(FLAGS.train_dir,FLAGS.fake_data)


——如图fully_connected_feed.py文件中所示:



——注意:fake_data的标签是用来单元测试的,读者可以完全忽略。

数据集目的
data_sets.train55000份图像和标签,用于主要训练
data_sets.validation5000份图像和标签,用于迭代验证训练的准确性
data_sets.test10000份图像和标签,用于最终测试训练的准确性

2.2 输入和占位符

——placeholder_inputs()函数生成了两个tf.placeholder操作来定义传入图的shape参数,shape参数中包含batch_size,后面还会将实际的训练用例传入到图中。

images_placeholder = tf.placeholder(tf.float32,shape=(bath_size, mnist.IMAGE_PIXELS))
labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))


——如图fully_connected_feed.py文件中所示:



——在训练循环的后续步骤中,整个图像和标签数据集被分片,以符合每一步操作设定的batch_size,占位符操作会填补以符合batch_size值,然后使用feed_dict参数,将数据传入到 sess.run()函数中。

3、创建图

——在创建数据的占位符之后,在mnist.py文件中,根据三阶段模式:inference(),loss()和training(),建立图graph。

inference():尽可能的构建好图,以满足运行网络前向反馈来获取预测。

loss():向inference图中添加生成损失所需的操作。

training():向loss图中添加计算和应用梯度所需的操作。



——如图mnist.py文件中所示:







3.1 推理inference

——inference()函数尽可能的构建图,以做到返回包含输出预测的tensor。

——它将图像的占位符作为输入,并且在此之上借助Relu激励函数构建了一对全连接层,以及一个有着10个节点,指明了输出logits的线性层。

——每一层都在一个唯一的tf.name_scope下面创建,创建于该作用域下的所有元素都带有其前缀。

with tf.name_scope('hidden1'):


——在该定义的作用域下,每一层都要使用的权重和偏置值由tf.Variable实例来生成,并且带有他们想要的大小。

with tf.name_scope('hidden1'):
weights = tf.Variable(
tf.truncated_normal([IMAGE_PIXELS, hiddenl_units], stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))), name='weights')
biases = tf.Variable(
tf.zeros([hidden1_units]), name='biases')




——例如,当这些层在在hidden1的作用域下生成时,赋予权重变量唯一的名字将是“hidden1/weights”。

——每个变量在构建时,都会获得初始化操作。

——在最常见的情况下,通过tf.truncated_normal初始化权重,并且给了2维tensor的形状,其中第一个维度代表每层中权重连接的单元数量(单元指向权重?),第二个维度表示每层中权重所连接到的单元数量(权重指向单元?)。对于第一层,命名为hidden1,维度是[IMAGE_PIXELS, hidden1_units],因为权重将图像输入连接到了hidden1层。tf.truncated_normal初始函数根据得到的均值和标准差,产生一个随机分布。

——然后,偏置值由tf.zeros函数初始化,以确保它们初始都是0值,形状是该层偏置值所连接的单元数量。

——图的三个主要操作,分别是两个tf.nn.relu操作,它们中嵌入了隐藏层所需的tf.matmul,一个logits所需的另一个tf.matmul操作。三者依次创建,各自的tf.Variable则与每一个输入占位符或者是前一层的输出tensor相连。

hidden1 = tf.nn.rulu(tf.matmul(images, weights) + biases)
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
logits = tf.matmul(hidden2, weights) + biases


——最终,程序会返回包含了输出结果的logits tensor。

3.2 损失loss

——loss函数通过添加所需要的损失操作,进一步构建图。

——首先,labels_placeholder中的值被转换成64位的整数,然后tf.nn.sparse_softmax_cross_entropy_with_logits操作被添加进来,用来从labels_placeholder中自动生成1-hot标签,最后,将inference()函数产生的输出logits和这些1-hot标签比较。

labels = tf.to_int64(labels)
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, labels, name='xentropy')


——接着,用tf.reduce_mean函数计算batch维度(第一维度)下交叉熵的平均值,作为总损失。

loss = tf.reduce_mean(cross_entropy, name='xentropy_mean')


——最后程序会返回包含了loss的tensor。



——注意:交叉熵是信息论中的一个观点,它允许我们去描述,基于已有的事实,相信神经网络的预测会有多么差。更多信息请阅读博客《可视化信息理论》

3.3 训练

——training()函数添加了通过梯度下降最小化loss所需的操作。

——首先,取出loss()函数中的loss tensor,并用tf.scalar_summary处理,tf.scalar_summary这个操作可以与SummaryWriter(见下文)配合使用,可以向事件文件(events file)中生成汇总值(summary values)。在本教程中,每次写入汇总值时,它都会释放loss tensor的当前值。

tf.scalar_summary(loss.op.name, loss)


——接下来,我们实例化一个tf.train.GradientDescentOptimizer,负责按照要求的学习速率应用梯度下降法。

optimizer = tf.train.GradientDescentOptimizer(learning_rate)


——之后,我们生成一个单一变量,用来保存全局训练步骤的次数,并用minimize()操作更新系统中的三角权重(trainable weights),增加全局步骤的操作。根据惯例,这个操作称之为train_op,必须在tensorflow的会话中运行,以诱发一个完整训练步骤(见下文)。

global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)




4、训练模型

——一旦图构建好,用户可以在fully_connected_feed.py文件中用代码控制在一个循环中迭代训练和评估图。

4.1 图graph

——在run_training()函数的开始,是Python语言中的with命令,它表明,所有已经构建的操作,与默认的tf.Graph全局实例是关联起来的。

with tf.Graph().as_default():


——tf.Graph实例是一系列可以作为整体运行的操作。tensorflow大部分场景只需要依赖于单一默认的图即可。

——利用多个图的更加复杂的场景也是可能的,但是超出了本教程的范围。



4.2 会话session

——-一旦已经完成所有的构建准备,生成所有需要的操作,为了运行图,需要创建tf.Session

sess = tf.Session()


——另外,也可以用with模块生成session,限制作用域。

with tf.Session() as sess:


——session中没有参数表明,这份代码将依附于(如果没有创建会话,就先创建会话)默认的本地会话。

——在生成session之后,所有的tf.Variable实例都要都要通过各自初始化操作中的sess.run()函数来初始化。

init = tf.global_variable_initializer()
sess.run(init)


——sess.run()方法将运行图中,与作为参数传入的操作相对应的完整子集。在第一调用时,它只包含了变量初始化程序tf.group,图的其他部分不会在这里运行,它们将发生在下面的训练循环中。





4.3 训练循环train loop

——在会话中初始化所有变量后,训练就开始了。

——训练的每一步都是有用户代码控制的,最简单的循环可以做有用的训练:

for step in xrange(FLAGS.max_steps):
sess.run(train_op)


—–然而,本教程在这方面会稍微复杂一点,它必须把输入的数据根据每一步的情况进行切分,以匹配前面生成的占位符。

4.3.1 向图提供反馈

——对每一步,代码都会生成一个反馈字典,包含了对应步骤中训练所使用的例子集合,这些例子的哈希键就是其所代表的占位符操作。

——在fill_feed_dict()函数中,为了下一批次图像和标签的batch_size集合,会查询给定的DataSet,并且与占位符匹配的tensor会包含下一批次的图像和标签。

images_feed, labels_feed = data_set.next_batch(FLAGS.batch_size, FLAGS.fake_data)


——以占位符作为哈希键,创建一个Python字典对象,键值则是其代表的反馈tensor。

feed_dict = {
images_placeholder:images_feed,
labels_placeholder:labels_feed,
}


——这传给sess.run()函数的feed_dict参数,为这一步的训练提供输入例子。



4.3.2 检查状态

——在运行sess.run()函数时,要在代码中明确其获取的两个值,[train_op, loss]。

for step in xrange(FLAGS.max_steps):
feed_dict = fill_feed_dict(
data_sets.train,
images_placeholder,
labels_placeloder
)
_, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)


——因为要获取这两个值,sess.run()会返回一个有两个元素的元组。列表中的每一个tensor对象,都对应了返回元组中的numpy数组,而这些数组中包含了当前这步训练中对应的tensor的值。由于train_op操作没有输出值,在返回元组中对应的元素就是None,所以会抛弃。然而,如果在训练过程中模型出现偏差,loss tensor的值可能会变成NaN,所以我们要获取它的值,并记录下来。

——假设训练没有出现NaNs,训练循环将每100次训练后,打印一个简单的状态文本 ,让用户知道现在的训练状态。

if step % 100 == 0:
print 'Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, duration)




4.3.3 状态可视化

——-为了释放TensorBoard所使用的事件文件,所有的即时数据(在这里只有一个)在图建立期间都要合并在一个tensor中。

summary = tf.merge_all_summaries()


—–然后在会话创建后,可以实例化一个tf.train.SummaryWriter,用于写入包含了图本身和即时数据的具体值的事件文件。

summary_writer = tf.train.SummaryWriter(FLAGS.train_dir, sess.graph)


——最后,每次评估summary时,这个事件文件将会用新的即时数据更新,函数的输出会传入到事件文件读写器(writer)的add_summary()函数中。

summary_str = sess.run(summary, feed_dict=feed_dict)
summary_writer.add_summary(summary_str, step)


——当事件文件写入完成后,训练文件夹将会运行一个TensorBoard,查看即时数据的情况。









——注意:更多关于建立和运行Tensorboard的信息,请查看相关教程Tensorboard: 训练过程可视化

4.3.4 保存检查点checkpoint

——为了得到可以用来后续恢复模型以进一步训练和评估的检查点文件,我们实例化一个tf.train.Saver

saver = tf.train.Saver()


——在训练循环中,saver.save()方法被定期调用,用来向训练文件夹写入包含了当前所有可训练变量值的检查点文件。

saver.save(sess, FLAGS.train_dir, global_step=step)


——这样,以后我们就可以使用saver.restore()方法,重载模型的参数,继续训练。

saver.restore(sess, FLAGS.train_dir)






5、评估模型

——在每1000步后,代码将会用训练数据集和测试数据集评估模型,do_eval()函数将会被调用3次,分别使用训练数据集、验证数据集和测试数据集。

print 'Training Data Eval:'
do_eval(
sess,
images_placeholer,
labels_placeholder,
data_sets.train
)
print 'Validation Data Eval:'
do_eval(
sess,
eval_correct,
images_placeholder,
labels_placeholder,
data_sets.validation
)
print 'Test Data Eval:'
do_eval(
eval_correct,
images_placeholder,
labels_placeholder,
data_sets.test
)




——注意:越复杂的使用场景,通常越要隔绝data_sets.test测试数据集,只有在大量的超参数优化调整(hyperparameter tuning)之后才检查。但是由于MNIST问题比较简单,我们可以一次性评估所有的数据。

5.1 建立评估图

——在进入训练循环之前,评估操作可以通过调用mnist.py文件的evaluation()函数来建立,传入和loss()函数相同的logits/labels参数。

eval_correct = mnist.evaluation(logits, labels_placeholder)


——evaluation()函数会产生一个tf.nn.in_top_k操作,如果在k个最有可能的预测中,发现真的标签,那个这个操作就会将模型的输出标记为正确。在这里,我们将k的值标记为1,也就是只有在预测是真的标签时,才判定它是正确的。

eval_correct = tf.nn.in_top_k(logits, labels, 1)






5.2 评估输出

——接着创建一个循环,向其中添加feed_dict,并且在调用sess.run()时传入eval_correct操作以在给定的数据集上评估模型。

for step in xrange(steps_per_epoch):
feed_dict = fill_feed_dict(
data_set,
images_placeholder,
labels_placeholder
)
true_count += sess.run(eval_correct, feed_dict=feed_dict)


——true_count变量会累加所有in_top_k操作判定为正确的预测之和,然后只需要将正确测试的总数,除以例子总数,就可以得到正确率了。

precision = true_count / num_examples
print('  Num examples: %d  Num correct: %d  Precision @ 1: %0.04f' % (num_examples, true_count, precision))


6、实际运行

——官网下载源代码,如下:



——第一次出现一点问题,File “fully_connected_feed.py”, line 155, in run_training

summary_writer = tf.train.SummaryWriter(FLAGS.log_dir, sess.graph)

AttributeError: ‘module’ object has no attribute ‘SummaryWriter’

——截图如下:



——原因是最新版的tensorflow修改了很多API(更多内容查看官网),这里的也做了修改:



——修改代码,将第一行替换为第二行

summary_writer = tf.SummaryWriter(FLAGS.log_dir, sess.graph)
summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)


——再次运行结果如下:



——以上,tensorflow的基本操作已经完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: