Tensorflow官方文档学习理解 (六)-TensorFlow运作方式入门
我的微信公众号名称:深度学习与智能决策
微信公众号ID:MultiAgent1024
公众号介绍:主要研究强化学习、计算机视觉、深度学习、机器学习等相关内容,分享学习过程中的学习笔记和心得!期待您的关注,欢迎一起学习交流进步!
在这篇文档里面依旧是使用前馈神经网络(feed-forward neural network)来构建MNIST识别的神经网络,只不过神经网络的编写更加规范了。主要是对mnist.py 和fully_connected_feed.py 这两个文件代码的一个解释。这两个文件在tensorflow的官方github中都可以找到tensorflow/tensorflow/examples/tutorials/mnist/。在mnist.py里面主要编写的就是构建全连接神经网络-mnist的模型,在fully_connected_feed.py里面主要编写利用mnist数据集的训练代码。运行fully_connected_feed.py就可以开始训练我们的模型。
mnist.py
在开始之前我们需要导入一些模块:
import math
import tensorflow as tf
在mnist.py里面我们经过三阶段的模式函数操作:inference()
, loss()
,和training(),
就能够把图表构建完成了。
1.inference()
—— 尽可能地构建好图表,满足促使神经网络向前反馈并做出预测的要求。
2.loss()
—— 往inference图表中添加生成损失(loss)所需要的操作(ops)。
3.training()
—— 往损失图表中添加计算并应用梯度(gradients)所需的操作。
inference():
inferfence()函数会尽可能地构建图表,返回包含了预测结果(out prediction)的Tensor。它以图片的占位符(image placeholder)作为输入,借助ReLu(Rectified Linear Units)激活函数,构建一对全连接层。
每一层都创建于一个唯一的tf.name_scope之下,创建于该作用域之下的所有元素都将带有其前缀。
with tf.name_scope('hidden1'):
接下来我们需要构建第一层的神经元了,我们知道第一层的神经元以图像作为输入,因此我们首先需要去给出图像的大小的参数:
IMAGE_SIZE = 28
IMAGE_PIXELS = IMAGE_SIZE * IMAGE_SIZE
我们有了这个参数之后,我们就可以构建输入层,也就是第一层的神经元的权重(weight)和偏置(bias)了,第一层的输出为隐藏层第一层的输入:
weights = tf.Variable(tf.truncated_normal([IMAGE_PIXELS, hidden1_units],stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),name='weights')biases = tf.Variable(tf.zeros([hidden1_units]),name='biases')
因此权重W的维度是:[IMAGE_PIXELS, hidden1_units],tf.truncated_normal
初始函数将根据所得到的均值和标准差,生成一个随机分布。
定义好了权重和偏置之后,接下来就需要将其和输入图像连接起来并经过激活函数:
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
这样的话第一层神经元就构建好了,接下来我们以同样的方式构建第二层神经元:
with tf.name_scope('hidden2'):weights = tf.Variable(tf.truncated_normal([hidden1_units, hidden2_units],stddev=1.0 / math.sqrt(float(hidden1_units))),name='weights')biases = tf.Variable(tf.zeros([hidden2_units]),name='biases')hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
最后我们希望输出是10个类别,因此我们需要定义一个参数去确定我们的输出是多少维度的:
NUM_CLASSES = 10
之后构建输出层(至于这里为啥没有经过激活函数我也不是很清楚,如果有知道的同学的话还希望可以留言告诉我一下,嘻嘻):
with tf.name_scope('softmax_linear'):weights = tf.Variable(tf.truncated_normal([hidden2_units, NUM_CLASSES],stddev=1.0 / math.sqrt(float(hidden2_units))),name='weights')biases = tf.Variable(tf.zeros([NUM_CLASSES]),name='biases')logits = tf.matmul(hidden2, weights) + biases
整个inference函数的构建如下所示:
def inference(images, hidden1_units, hidden2_units):with tf.name_scope('hidden1'):weights = tf.Variable(tf.truncated_normal([IMAGE_PIXELS, hidden1_units],stddev=1.0 / math.sqrt(float(IMAGE_PIXELS))),name='weights')biases = tf.Variable(tf.zeros([hidden1_units]),name='biases')hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)with tf.name_scope('hidden2'):weights = tf.Variable(tf.truncated_normal([hidden1_units, hidden2_units],stddev=1.0 / math.sqrt(float(hidden1_units))),name='weights')biases = tf.Variable(tf.zeros([hidden2_units]),name='biases')hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)with tf.name_scope('softmax_linear'):weights = tf.Variable(tf.truncated_normal([hidden2_units, NUM_CLASSES],stddev=1.0 / math.sqrt(float(hidden2_units))),name='weights')biases = tf.Variable(tf.zeros([NUM_CLASSES]),name='biases')logits = tf.matmul(hidden2, weights) + biasesreturn logits
loss():
loss()函数通过添加所需的op来构建图:
首先,这个来自lables_placeholder是被编码成一个1-hot的向量。例如:如果一个标签是被定义为数字“3”,那么它的表示形式如下所示:
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
loss()函数的编写如下:
def loss(logits, labels):labels = tf.to_int64(labels)return tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
tf.to_int64将张量转换为 int64 类型;
使用tf.nn.sparse_softmax_cross_entropy_with_logits的交叉熵(cross-entropy)loss。
- labels:形状为[d_0, d_1, ..., d_{r-1}]的Tensor(其中,r是labels和结果的秩),并且有dtype int32或int64。labels中的每个条目必须是[0, num_classes)中的索引。当此操作在CPU上运行时,其他值将引发异常,并返回NaNGPU上相应的loss和梯度行。
- logits:形状为[d_0, d_1, ..., d_{r-1}, num_classes],并且是dtype float32或float64的未缩放的日志概率。
返回与logits具有相同类型的加权损失Tensor。
training():
training的代码如下图所示:
def training(loss, learning_rate):tf.summary.scalar('loss', loss)optimizer = tf.train.GradientDescentOptimizer(learning_rate)global_step = tf.Variable(0, name='global_step', trainable=False)train_op = optimizer.minimize(loss, global_step=global_step)return train_op
对于tf.summary.scalar()函数的理解:TensorBoard可以将训练过程中的各种绘制数据展示出来,包括标量(scallars),图片(images),音频(Audio),计算图(graph)分布,直方图(histograms)和嵌入式向量。
如果我们需要使用TensorBoard展示数据的话,我们需要在执行Tensorflow就计算图的过程中,将各种类型的数据汇总并记录到日志文件中。然后使用TensorBoard读取这些日志文件,解析数据并产生数据可视化的Web页面,让我们可以在浏览器中观察各种汇总数据。summary_op包括了summary.scalar、summary.histogram、summary.image等操作,这些操作的输出是各种summary protobuf,最后通过summary.writer写入到event文件中。
Tensorflow API中包含系列生成summary数据的API接口,这些函数将汇总信息存放在protobuf中,以字符串形式表达。具体的更加细致的用法可以参考博客。接下来的操作就跟之前的一样,使用梯度下降算法优化迭代更新,不同的是我们生成一个变量用于保存全局训练步骤(global training step)的数值。
之后还多了一个函数,如下所示:
def evaluation(logits, labels):correct = tf.nn.in_top_k(logits, labels, 1)return tf.reduce_sum(tf.cast(correct, tf.int32))
tf.nn.in_top_k组要是用于计算预测的结果和实际结果的是否相等,返回一个bool类型的张量,tf.nn.in_top_k(prediction, target, K):prediction就是表示你预测的结果,大小就是预测样本的数量乘以输出的维度,类型是tf.float32等。target就是实际样本类别的标签(是mnist标签对应的下标值,一个10维的标签代表一个值(这个十维的标签的最大值的下标),具体的解析参考博客),大小就是样本数量的个数。K表示每个样本的预测结果的前K个最大的数里面是否含有target中的值。一般都是取1。
tf.cast表示将数据转化为tf.int32格式。tf.reduce_sum表示为压缩求和。
fully_connected_feed.py
在开始训练之前我们需要先用tf.placeholder占位符帮手写体数据集占一个位置,这里我们的标签的维度是[batch_size, 1]:
def placeholder_inputs(batch_size):images_placeholder = tf.placeholder(tf.float32, shape=(batch_size,mnist.IMAGE_PIXELS))labels_placeholder = tf.placeholder(tf.int32, shape=(batch_size))return images_placeholder, labels_placeholder
run_training():
在开始训练之前,我们需要去读取数据:
data_sets = input_data.read_data_sets(FLAGS.input_data_dir, FLAGS.fake_data)
read_data_sets函数是input_data.py源码中的函数,主要用于读取数据,它需要三个参数:
- train_dir——文件夹的文件夹的位置
- fake_data——是否使用假数据,默认为False
- one_hot——是否把标签转为一维向量,默认为False,由于这里没有采用one-hot编码,那么这里的返回值就是图片数字的下标,也就是图片数字到底是几。是一个单纯的数字,而不是一个十维的向量([0, 0, 0, 1, 0, 0, 0, 0, 0, 0])。
在run_training()
这个函数的一开始,是一个Python语言中的with
命令,这个命令表明所有已经构建的操作都要与默认的tf.Graph
全局实例关联起来。
with tf.Graph().as_default():
tf.Graph
实例是一系列可以作为整体执行的操作。TensorFlow的大部分场景只需要依赖默认图表一个实例即可。利用多个图表的更加复杂的使用场景也是可能的,但是超出了本教程的范围。
之后的话,我们需要调用之前写好的神经网络来对其进行训练,在训练之前需要调用之前写好的占位符函数placeholder_input()来给输入数据占个位置:
images_placeholder, labels_placeholder = placeholder_inputs(FLAGS.batch_size)
这样的话我们就假装我们有了输入的图片和其对应的标签(其实是没有的,我们需要之后再将其传进来,嘻嘻),接下来我们构建图的输出公式:
logits = mnist.inference(images_placeholder,FLAGS.hidden1,FLAGS.hidden2)
选择损失和训练参数:
loss = mnist.loss(logits, labels_placeholder)train_op = mnist.training(loss, FLAGS.learning_rate)
评估模型结果指标:
eval_correct = mnist.evaluation(logits, labels_placeholder)
接下来我们把图运行过程中发生的事情(产生的数据记录下来):
summary = tf.summary.merge_all()
初始化变量:
init = tf.global_variables_initializer()
建立一个保存训练中间数据的存档点:
saver = tf.train.Saver()
建立会话:
sess = tf.Session()
创建一个记事本写入器(这里我也想吐槽一下,为什么不之前的创建记事本放在一起):
summary_writer = tf.summary.FileWriter(FLAGS.log_dir, sess.graph)
之后再初始化变量:
sess.run(init)
做完这些基本的操作之后我们就可以对其进行迭代训练了,但是在迭代训练之前我们得处理一下我们的输入数据,之前我们一直都是用tf.placeholder来假装我们有输入数据,现在我们需要将真实数据传入进来:
def fill_feed_dict(data_set, images_pl, labels_pl):images_feed, labels_feed = data_set.next_batch(FLAGS.batch_size,FLAGS.fake_data)feed_dict = {images_pl: images_feed,labels_pl: labels_feed}return feed_dict
fill_feed_dict函数输入是数据,图像placeholder的变量名称,和标签placeholder的变量名称,返回一个字典,即需要传入到会话图中的数据。再接着就可以对其进行迭代训练:
for step in xrange(FLAGS.max_steps):start_time = time.time()feed_dict = fill_feed_dict(data_sets.train,images_placeholder,labels_placeholder)_, loss_value = sess.run([train_op, loss],feed_dict=feed_dict)
sess.run()
会返回一个有两个元素的元组。其中每一个Tensor
对象,对应了返回的元组中的numpy数组,而这些数组中包含了当前这步训练中对应Tensor的值。由于train_op
并不会产生输出,其在返回的元祖中的对应元素就是None
,所以会被抛弃。但是,如果模型在训练中出现偏差,loss
Tensor的值可能会变成NaN,所以我们要获取它的值,并记录下来。我们也希望记录一下程序运行的时间:
duration = time.time() - start_time
如果进行顺利的话,我们每隔100步,打印一下步数,损失函数值,和程序运行的时间。
if step % 100 == 0:print('Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, duration))summary_str = sess.run(summary, feed_dict=feed_dict)summary_writer.add_summary(summary_str, step)summary_writer.flush()
在每次运行summary时,都会往事件文件中写入最新的即时数据,函数的输出会传入事件文件读写器(writer)的add_summary()函数。
我们也希望能够保存我们的训练模型:
if (step + 1) % 1000 == 0 or (step + 1) == FLAGS.max_steps:checkpoint_file = os.path.join(FLAGS.log_dir, 'model.ckpt')saver.save(sess, checkpoint_file, global_step=step)
接下来我们定义一个评估模型的函数:
def do_eval(sess,eval_correct,images_placeholder,labels_placeholder,data_set):true_count = 0 # Counts the number of correct predictions.steps_per_epoch = data_set.num_examples // FLAGS.batch_sizenum_examples = steps_per_epoch * FLAGS.batch_sizefor 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)precision = float(true_count) / num_examplesprint('Num examples: %d Num correct: %d Precision @ 1: %0.04f' %(num_examples, true_count, precision))
do_eval(sess,eval_correct,images_placeholder,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(sess,eval_correct,images_placeholder,labels_placeholder,data_sets.test)
每隔一千个训练步骤,我们的代码会尝试使用训练数据集与测试数据集,对模型进行评估。do_eval
函数会被调用三次,分别使用训练数据集、验证数据集合测试数据集。
总的代码文件目录如下:
总的代码文档链接:链接:https://pan.baidu.com/s/1TqOJSWeHbIV6kMJBwT1mYA 提取码:2h6h
https://github.com/18279406017/code-of-csdn/tree/master/Tensorflow/six
参考
http://www.tensorfly.cn/tfdoc/tutorials/mnist_tf.html
https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/g3doc/tutorials/mnist/tf/index.md
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/mnist/fully_connected_feed.py
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/mnist/mnist.py
Tensorflow官方文档学习理解 (六)-TensorFlow运作方式入门相关推荐
- tensorflow学习笔记十7:tensorflow官方文档学习 How to Retrain Inception's Final Layer for New Categories
现代物体识别模型有数以百万计的参数,可能需要数周才能完全训练.学习迁移是一个捷径,很多这样的工作,以充分的训练模式的一组类ImageNet技术,并从现有的权重进行新课.在这个例子中,我们将从头再训练最 ...
- 每天一小时python官方文档学习(六)————循环和条件控制的进阶用法
学习完数据结构之后,我们就能够对之前在第二天中讲过的流程控制工具,添加更多的用法了,这里主要介绍的是for循环语句和if与while条件判断语句. 5.6. 循环的技巧 我们学过的遍历序列for i ...
- TensorFlow官方文档中的sub 和mul中的函数已经在API中改名了
照着tensorflow 官方文档学习tensorflow时,出现问题: 第一,执行程序 #进入一个交互式Tensorflow会话 import tensorflow as tf sess = tf. ...
- TensorFlow 官方文档中文版发布啦(持续维护)
TensorFlow 是 Google 研发的第二代人工智能学习系统,是 Google 为了帮助全球开发者们更加方便和高效地开发机器学习 (Machine Learning)和人工智能 (AI) 应用 ...
- tensorflow官方文档_开源分享:最好的TensorFlow入门教程
如果一门技术的学习曲线过于陡峭,那么我们在入门时的场景往往是,一鼓作气,没入门,再而衰,三而竭.演绎一出从入门到放弃的败走麦城. 今天发现一个入门TensorFlow的宝藏,迫不及待的分享给大家.这个 ...
- TensorFlow 官方文档中文版发布啦(持续维护) 1
TensorFlow 是 Google 研发的第二代人工智能学习系统,是 Google 为了帮助全球开发者们更加方便和高效地开发机器学习 (Machine Learning)和人工智能 (AI) 应用 ...
- 嫌官方文档太烂?TensorFlow 开源工具书,助你快速上手开发!
公众号关注 "GitHubDaily" 设为 "星标",每天带你逛 GitHub! 转自机器之心 「官方文档排布凌乱.搜索难用.API 丑陋不堪--」这是很多人 ...
- TensorFlow 官方文档中文版
TensorFlow 官方文档中文版: http://wiki.jikexueyuan.com/project/tensorflow-zh/ w3cschool https://www.w3cscho ...
- Spring Boot 官方文档学习(一)入门及使用
Spring Boot 官方文档学习(一)入门及使用 个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问 ...
- HarmonyOS(一) 快速开始学习鸿蒙开发,官方文档学习路线解析
系列文章目录 HarmonyOS(一):快速开始学习鸿蒙开发,官方文档学习路线解析 HarmonyOS(二):应用开发环境搭建准备 HarmonyOS(三):创建你的第一个HelloWorld应用 文 ...
最新文章
- 咨询业或将危害电力信息化进程?
- Java学习笔记32
- Spring IoC 源码系列(四)bean创建流程与循环依赖问题分析
- linux下反删除软件,浅谈Linux文件系统反删除方法(二)
- ble 连接成功后找不到服务_闷声发大财的BLE芯片龙头
- 1个报表工具,5大体系,60种可视化图表,靠这些打动领导就够了
- 蚁群算法路径规划_环境感知与规划专题(十)——基于采样的路径规划算法(二)...
- 变异数分析_人工智能系统中分析变异的祸害
- Vista暴力破解器只是一个玩笑 谁说破解谁撒谎
- 算法笔记练习 题解合集
- java jbutton方法_java-如何设置JButton的大小?
- 这么连接计算机网络,详细教您手机怎么连接电脑上网
- 06 Redis中BigKey、HotKey的发现与处理
- Titan数据库简介
- FULL JOIN 数据库全连接查询SQL
- 旧瓶新酒之ngx_lua fail2ban实现主动诱捕
- python画图入门例子
- Revit获取族预览图
- linux系统拷贝文件到桌面,centos拷贝文件夹命令
- JDK 12 ,JDK 13 , JDK 14 新特性 详解