TensorsFlow学习笔记5----TensorFlow Mechanics 101基本运作方式
2017-05-04 08:44
686 查看
原文教程:tensorflow官方教程
翻译教程:极客学院
记录关键内容与学习感受。未完待续。。
——本教程的目标是展示如何使用tensorflow,利用MNIST数据集,训练和评估一个可以识别手写数字的简单的前馈神经网络。因此受众是对机器学习有经验并且对tensorflow感兴趣的用户。
——因此本教程并不是为了教授机器学习。
——请确定你已经看了安装教程。
.
——只要直接运行fully_connected_feed.py文件,就可以开始训练。
——更多信息获取点击Yann LeCun’s MNIST page和Chris Olah’s visualizations of MNIST
——如图fully_connected_feed.py文件中所示:
——注意:fake_data的标签是用来单元测试的,读者可以完全忽略。
——如图fully_connected_feed.py文件中所示:
——在训练循环的后续步骤中,整个图像和标签数据集被分片,以符合每一步操作设定的batch_size,占位符操作会填补以符合batch_size值,然后使用feed_dict参数,将数据传入到 sess.run()函数中。
inference():尽可能的构建好图,以满足运行网络前向反馈来获取预测。
loss():向inference图中添加生成损失所需的操作。
training():向loss图中添加计算和应用梯度所需的操作。
——如图mnist.py文件中所示:
——它将图像的占位符作为输入,并且在此之上借助Relu激励函数构建了一对全连接层,以及一个有着10个节点,指明了输出logits的线性层。
——每一层都在一个唯一的tf.name_scope下面创建,创建于该作用域下的所有元素都带有其前缀。
——在该定义的作用域下,每一层都要使用的权重和偏置值由tf.Variable实例来生成,并且带有他们想要的大小。
——例如,当这些层在在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相连。
——最终,程序会返回包含了输出结果的logits tensor。
——首先,labels_placeholder中的值被转换成64位的整数,然后tf.nn.sparse_softmax_cross_entropy_with_logits操作被添加进来,用来从labels_placeholder中自动生成1-hot标签,最后,将inference()函数产生的输出logits和这些1-hot标签比较。
——接着,用tf.reduce_mean函数计算batch维度(第一维度)下交叉熵的平均值,作为总损失。
——最后程序会返回包含了loss的tensor。
——注意:交叉熵是信息论中的一个观点,它允许我们去描述,基于已有的事实,相信神经网络的预测会有多么差。更多信息请阅读博客《可视化信息理论》。
——首先,取出loss()函数中的loss tensor,并用tf.scalar_summary处理,tf.scalar_summary这个操作可以与SummaryWriter(见下文)配合使用,可以向事件文件(events file)中生成汇总值(summary values)。在本教程中,每次写入汇总值时,它都会释放loss tensor的当前值。
——接下来,我们实例化一个tf.train.GradientDescentOptimizer,负责按照要求的学习速率应用梯度下降法。
——之后,我们生成一个单一变量,用来保存全局训练步骤的次数,并用minimize()操作更新系统中的三角权重(trainable weights),增加全局步骤的操作。根据惯例,这个操作称之为train_op,必须在tensorflow的会话中运行,以诱发一个完整训练步骤(见下文)。
——tf.Graph实例是一系列可以作为整体运行的操作。tensorflow大部分场景只需要依赖于单一默认的图即可。
——利用多个图的更加复杂的场景也是可能的,但是超出了本教程的范围。
——另外,也可以用with模块生成session,限制作用域。
——session中没有参数表明,这份代码将依附于(如果没有创建会话,就先创建会话)默认的本地会话。
——在生成session之后,所有的tf.Variable实例都要都要通过各自初始化操作中的sess.run()函数来初始化。
——sess.run()方法将运行图中,与作为参数传入的操作相对应的完整子集。在第一调用时,它只包含了变量初始化程序tf.group,图的其他部分不会在这里运行,它们将发生在下面的训练循环中。
——训练的每一步都是有用户代码控制的,最简单的循环可以做有用的训练:
—–然而,本教程在这方面会稍微复杂一点,它必须把输入的数据根据每一步的情况进行切分,以匹配前面生成的占位符。
——在fill_feed_dict()函数中,为了下一批次图像和标签的batch_size集合,会查询给定的DataSet,并且与占位符匹配的tensor会包含下一批次的图像和标签。
——以占位符作为哈希键,创建一个Python字典对象,键值则是其代表的反馈tensor。
——这传给sess.run()函数的feed_dict参数,为这一步的训练提供输入例子。
——因为要获取这两个值,sess.run()会返回一个有两个元素的元组。列表中的每一个tensor对象,都对应了返回元组中的numpy数组,而这些数组中包含了当前这步训练中对应的tensor的值。由于train_op操作没有输出值,在返回元组中对应的元素就是None,所以会抛弃。然而,如果在训练过程中模型出现偏差,loss tensor的值可能会变成NaN,所以我们要获取它的值,并记录下来。
——假设训练没有出现NaNs,训练循环将每100次训练后,打印一个简单的状态文本 ,让用户知道现在的训练状态。
—–然后在会话创建后,可以实例化一个tf.train.SummaryWriter,用于写入包含了图本身和即时数据的具体值的事件文件。
——最后,每次评估summary时,这个事件文件将会用新的即时数据更新,函数的输出会传入到事件文件读写器(writer)的add_summary()函数中。
——当事件文件写入完成后,训练文件夹将会运行一个TensorBoard,查看即时数据的情况。
——注意:更多关于建立和运行Tensorboard的信息,请查看相关教程Tensorboard: 训练过程可视化
——在训练循环中,saver.save()方法被定期调用,用来向训练文件夹写入包含了当前所有可训练变量值的检查点文件。
——这样,以后我们就可以使用saver.restore()方法,重载模型的参数,继续训练。
——注意:越复杂的使用场景,通常越要隔绝data_sets.test测试数据集,只有在大量的超参数优化调整(hyperparameter tuning)之后才检查。但是由于MNIST问题比较简单,我们可以一次性评估所有的数据。
——evaluation()函数会产生一个tf.nn.in_top_k操作,如果在k个最有可能的预测中,发现真的标签,那个这个操作就会将模型的输出标记为正确。在这里,我们将k的值标记为1,也就是只有在预测是真的标签时,才判定它是正确的。
——true_count变量会累加所有in_top_k操作判定为正确的预测之和,然后只需要将正确测试的总数,除以例子总数,就可以得到正确率了。
——第一次出现一点问题,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(更多内容查看官网),这里的也做了修改:
——修改代码,将第一行替换为第二行
——再次运行结果如下:
——以上,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 page和Chris 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.train | 55000份图像和标签,用于主要训练 |
data_sets.validation | 5000份图像和标签,用于迭代验证训练的准确性 |
data_sets.test | 10000份图像和标签,用于最终测试训练的准确性 |
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的基本操作已经完成。
相关文章推荐
- TensorFlow官方教程学习 TensorFlow Mechanics 101
- TensorFlow Mechanics 101解读
- TensorFlow Mechanics 101
- tensorflow学习(2)TensorFlow Mechanics 101
- tensorflow学习笔记十三:TF官方教程学习 TensorFlow Mechanics 101
- TensorFlow官方教程学习 TensorFlow Mechanics 101
- ubuntu + cuda8.0 + tensorflow最简单的安装方式
- #####tensorflow+入门笔记︱基本张量tensor理解与tensorflow运行结构 ***********######
- TensorFlow+Python基础知识和基本包的使用
- Ajax的基本运作方式
- tensorflow IOError: [Errno socket error] [Errno 101] Network is unreachable
- Different Readers for different file types(Tensorflow 的几种读取数据的方式)
- tensorflow serving:bazel方式部署模型+docker方式部署模型及提供服务以及使用该服务介绍(总有一款适合你)
- 『PyTorch x TensorFlow』第八弹_基本nn.Module层函数
- TensorFlow for machine learning 基本模板
- TensorFlow CNN 以库函数的方式实现MNIST手写识别
- Tensorflow + ResNet101 + fasterRcnn 训练自己的模型 数据(一)
- 在浏览器中进行深度学习:TensorFlow.js (三)更多的基本模型
- windows系统下基于anaconda的方式安装tensorflow+theano+keras
- Tensorflow——Graph Tensor Session 等基本概念汇总