目录
from tensorflow.examples.tutorials.mnist import input_data
tf.nn.sparse_softmax_cross_entropy_with_logits()
tf.contrib.layers.l2_regularizer()
tf.control_dependencies()/tf.no_op()
Ch5:MNIST数字识别问题
from tensorflow.examples.tutorials.mnist import input_data
#将数据集提取为三个部分:mnist.train、mnist.test和mnist.validation,每个部分包含有images和labels。train、test和validation中样本的数量分别为55000、10000和5000。
mnist = input_data.read_data_sets("../../datasets/MNIST_data/", one_hot=True)
batch_size = 100
xs, ys = mnist.train.next_batch(batch_size) # 从train的集合中选取batch_size个训练数据。
tf.nn.relu()
线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元。等同于max(0,x),将输入小于0的值赋值为0,输入大于0的值不变。
import tensorflow as tf
a = tf.constant([-1.0, 2.0,-3.6])
with tf.Session() as sess:
b = tf.nn.relu(a)
print(sess.run(b))
#实际上是上一章调用ema的average接口,来获取当前时序数据的指数滑动平均值
avg_class.average(weights2)
tf.truncated_normal()
tf.truncated_normal(shape, mean, stddev) :shape表示生成张量的维度,mean是均值,stddev是标准差。这个函数产生正态分布,均值和标准差自己设定。这是一个截断的产生正态分布的函数,就是说产生正态分布的值如果与均值的差值大于两倍的标准差,那就重新生成。和一般的正态分布的产生随机数据比起来,这个函数产生的随机数与均值的差距不会超过两倍的标准差,但是一般的别的函数是可能的。
tf.argmax()
tf.argmax(vector, 1):返回的是vector中的最大值的索引号,如果vector是一个向量,那就返回一个值,如果是一个矩阵,那就返回一个向量,这个向量的每一个维度都是相对应矩阵行的最大值元素的索引号。
import tensorflow as tf
import numpy as np
A = [[1,3,4,5,6]]
B = [[1,3,4], [2,4,1]]
with tf.Session() as sess:
print(sess.run(tf.argmax(A, 1)))
print(sess.run(tf.argmax(B, 1)))
输出:
[4]
[2 1]
tf.nn.sparse_softmax_cross_entropy_with_logits()
注意与tf.nn.sigmoid_cross_entropy_with_logits以及tf.nn.softmax_cross_entropy_with_logits的区别和联系。首先顾名思义,tf.nn.sparse_softmax_cross_entropy_with_logits和tf.nn.softmax_cross_entropy_with_logits都是将输入送到softmax层,再利用softmax层的输入和实际的标签数据,来计算交叉熵,交叉熵是分类问题中常见的损失函数。二者的区别主要在于二者使用的标签真值形式是不同的。
- sparse_softmax_cross_entropy_with_logits:
使用的是实数来表示类别,数据类型为int16,int32,或者 int64,标签大小范围为[0,num_classes-1],标签的维度为[batch_size]大小
- softmax_cross_entropy_with_logits
使用的是one-hot二进制码来表示类别,数据类型为float16,float32,或者float64,维度为[batch_size, num_classes]。这里需要说明一下的时,标签数据类型并不是Bool型的。这是因为实际上在tensorflow中,softmax_cross_entropy_with_logits中的每一个类别是一个概率分布,tensorflow中对该模块的说明中明确指出了这一点,Each row labels[i] must be a valid probability distribution。很显然,one-hot的二进码也可以看是一个有效的概率分布。
import tensorflow as tf
sess = tf.InteractiveSession()
logits = tf.constant([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]])
labels = tf.constant([[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]])
softmax = tf.nn.softmax(logits)
sparse_labels = tf.argmax(labels, 1)
cross_entropy = -tf.reduce_sum(labels * tf.log(softmax))
cross_entropy2 = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels))
cross_entropy3 = tf.reduce_sum(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=sparse_labels))
print("sparse_labels : {}".format(sparse_labels.eval()))
print("cross entropy by tf : %.4f" % cross_entropy.eval())
print("cross entropy by softmax_cross : %.4f" % cross_entropy2.eval())
print("cross entropy by sparse_softmax_cross: %.4f" % cross_entropy3.eval())
注意:tf.nn.softmax函数默认(dim=-1)是对张量最后一维的shape=(p,)向量进行softmax计算,得到一个概率向量。不同的是,tf.nn.sigmoid函数对一个张量的每一个标量元素求得一个概率。也就是说tf.nn.softmax默认针对1阶张量进行运算,可以通过指定dim来针对1阶以上的张量进行运算,但不能对0阶张量进行运算。而tf.nn.sigmoid是针对0阶张量,。
下面说说tf.nn.sigmoid_cross_entropy_with_logits:不同于softmax系列函数是张量中向量与向量间的运算。sigmoid_cross_entropy_with_logits函数则是张量中标量与标量间的运算。
z = 0.8
x = 1.3
cross_entropy4 = tf.nn.sigmoid_cross_entropy_with_logits(labels=z, logits=x)
# tf.nn.sigmoid_cross_entropy_with_logits的具体实现:
cross_entropy5 = - z * tf.log(tf.nn.sigmoid(x)) \
- (1-z) * tf.log(1-tf.nn.sigmoid(x))
sess = tf.InteractiveSession()
print(sess.run(cross_entropy4))
print(sess.run(cross_entropy5))
cross_entropy4 与cross_entropy5 的值是相等的。sigmoid_cross_entropy_with_logits的具体实现就是
如果sigmoid_cross_entropy_with_logits的labels和logits是相同shape的张量,输出结果则是与labels和logits有相同shape的张量。张量的每个元素都是labels和logits相对的值捉对按上述方法计算出来的交叉熵。
tf.contrib.layers.l2_regularizer()
创建一个L2正则化方法
tf.control_dependencies()/tf.no_op()
在有些机器学习程序中我们想要指定某些操作执行的依赖关系,这时我们可以使用tf.control_dependencies()来实现。control_dependencies(control_inputs)返回一个控制依赖的上下文管理器,使用with关键字可以让在这个上下文环境中的操作都在control_inputs 执行。
with g.control_dependencies([a, b, c]):
# `d` and `e` will only run after `a`, `b`, and `c` have executed.
d = ...
e = ...
可以嵌套control_dependencies 使用
with g.control_dependencies([a, b]):
# Ops constructed here run after `a` and `b`.
with g.control_dependencies([c, d]):
# Ops constructed here run after `a`, `b`, `c`, and `d`.
可以传入None 来消除依赖:
with g.control_dependencies([a, b]):
# Ops constructed here run after `a` and `b`.
with g.control_dependencies(None):
# Ops constructed here run normally, not waiting for either `a` or `b`.
with g.control_dependencies([c, d]):
# Ops constructed here run after `c` and `d`, also not waiting
# for either `a` or `b`.
在训练模型时,我们每步训练可能要执行两种操作,op a,b这时我们就可以使用如下代码
with tf.control_dependencies([a, b]):
c= tf.no_op(name='train') # tf.no_op;什么也不做
sess.run(c)
# 也可以将其替换为
c= tf.group([a, b])
sess.run(c)
tf.cast()
tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换,比如读入的图片如果是int8类型的,一般在要在训练前把图像的数据格式转换为float32。
cast定义:
cast(x, dtype, name=None)
第一个参数 x: 待转换的数据(张量)
第二个参数 dtype: 目标数据类型
第三个参数 name: 可选参数,定义操作的名称
tf.train.Saver()
模型保存,先要创建一个Saver对象:如
saver = tf.train.Saver(max_to_keep=0)
这里的max_keep参数代表的是保存模型的个数,默认为5。
TensorFlow中的Saver对象是用于参数保存和恢复的。其实 创建 saver对象时使用的键值对就是表达了一种对应关系:
save时, 表示:variable的值应该保存到 checkpoint文件中的哪个 key下
restore时,表示:checkpoint文件中key对应的值,应该restore到哪个variable
参数会保存到 checkpoint 文件中,通过键值对的形式在 checkpoint中存放着。如果 Saver 的构造函数中传的是 dict,那么在 save 的时候,checkpoint文件中存放的就是对应的 key-value。如下:
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
我们利用官方提供的工具来查看一下checkpoint中保存了什么
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
print_tensors_in_checkpoint_file("test-ckpt/model-2", None, True)
# 输出:
#tensor_name: variable_1
#1.0
#tensor_name: variable_2
#2.0
如果构建saver对象的时候,我们传入的是 list, 那么将会用对应 Variable 的 variable.op.name 作为 key。
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver([v1, v2])
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
我们再使用官方工具打印出 checkpoint 中的数据,得到
tensor_name: v1
1.0
tensor_name: v2
2.0
如果我们现在想将 checkpoint 中v2的值restore到v1 中,v1的值restore到v2中,我们该怎么做?
这时,我们只能采用基于 dict 的 saver
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
restore的代码和save的代码有所不同
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
#restore的时候,variable_1对应到v2,variable_2对应到v1,就可以实现目的了。
saver = tf.train.Saver({"variable_1":v2, "variable_2": v1})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.restore(sess, 'test-ckpt/model-2')
print(sess.run(v1), sess.run(v2))
# 输出的结果是 2.0 1.0,如我们所期望的那样
回顾总结:
save时, 表示:variable的值应该保存到 checkpoint文件中的哪个 key下;restore时,表示:checkpoint文件中key对应的值,应该restore到哪个variable。
tf.train.import_meta_graph()
import_meta_graph将定义在.meta的网络导入到当前图中。所以,这会替你创造图/网络,但我们仍然需要导入在这张图上训练好的参数。一般来说加载完成模型之后,会需要手动加载参数,所以会和saver.restore()api联合使用。
with tf.Session() as sess:
new_saver = tf.train.import_meta_graph('my_test_model-1000.meta')
new_saver.restore(sess, tf.train.latest_checkpoint('./'))
tf.assign()
tf.assign(A, new_number): 这个函数的功能主要是把A的值变为new_number
直接在保存模型时保存时序数据的ema值
v = tf.Variable(0, dtype = tf.float32, name="v")
ema = tf.train.ExponentialMovingAverage(0.99)
print(ema.variables_to_restore())
saver = tf.train.Saver(ema.variables_to_restore())
with tf.Session() as sess:
saver.restore(sess, "Saved_model/model2.ckpt")
其它
tf.get_default_graph().as_graph_def():得到当前图的计算节点信息
graph_util.convert_variables_to_constants():将相关节点的values固定
tf.gfile.GFile(): # 保存模型
graph_def.ParseFromString(f.read())通过得到模型中的图和变量数据
tf.import_graph_def()加载目前的图
gfile.FastGFile()
tf.gfile.FastGFile(path,decodestyle)
函数功能:实现对图片的读取。
函数参数:(1)path:图片所在路径 (2)decodestyle:图片的解码方式。(‘r’:UTF-8编码; ‘rb’:非UTF-8编码)
saver.export_meta_graph():详见https://zhuanlan.zhihu.com/p/31308381
tf.train.NewCheckpointReader() 用于创建一个reader对象,进而导出持久化模型的所有变量
reader = tf.train.NewCheckpointReader("/home/penglu/Desktop/lp/model.ckpt")
variables = reader.get_variable_to_shape_map()
for ele in variables:
print(ele)
reader.get_tensor(key) 用于查看ckpt模型文件中的变量