导图社区 《TensorFlow实战Google深度学习框架》
第五章:MNIST数字识别问题总结
编辑于2019-08-30 14:52:45TensorFlow2第五章
MNIST数字识别问题
MNIST数据处理
数据
训练集
55000
验证集
5000
神经网络在验证数据集上的表现可以近似地作为评价不同神经网络模型的标准或者决定迭代轮数的依据
为了评测神经网络模型在不同参数下的效果,一般会从训练数据中抽取一部分作为验证数据
交叉验证集
在海量数据的情况下,一般会直接采用验证数据集的形式来评测模型的效果。因为,神经网络训练时间本来就长,交叉验证更会花费大量的时间
训练数据集
测试集
10000
验证数据与测试数据的分布越接近越好
下载数据
mnist = input_data.read_data_sets("/path/to/MNIST_data/", one_hot= true)
one_hot
在多类场景下,one_hot = True表示只有一个元素的值为1,其他元素的值为0;使用one_hot的直接原因是在多分类CNN网络的输出通常会通过softmax层,输出是概率分布。
batch随机梯度下降
批量数据提供训练函数
mnist.train.next_batch(batch_size=100)
优化处理效果排序
正则化
滑动平均模型
指数衰减学习率
变量管理
情景
当神经网络当结构变得复杂,参数变多,需要更好的方式来传递和管理神经网络中的参数
方法/机制
TensorFlow提供通过变量名称来创建或获取一个变量的机制。通过这个机制,在不同的函数中可以直接通过变量的名字来使用变量,而不需要通过参数形式到处传递。
两个函数
tf.get_variable(name, shape=None, dtype=None, initializer=None,...)
tf.variable_scope(<scope_name>,reuse=True/None/AUTO_REUSE)
创建变量tf.get_variable()
创建变量方式一
v = tf.get_variabble( "v", shape=[1], initializer = tf.constant_initializer(1.0))
不同点
常数初始化函数 tf.constant_initializer()
tf.get_variable()会根据这个名字v去创建,如果已存在名字为v的变量,则创建失败;避免无意识的变量复用造成的错误。
创建变量方式二
v = tf.Variable(tf.constant(1.0, shape=[1], name="v" )
不同点
常数生成函数 tf.constant()
tf.get_variable()的name参数是必填的,而tf.Variable中的name属性是选填的。
获取变量with tf.Variable_scope(): tf.get_variable(0
使用方式
如果需要通过tf.get_variable获取一个已经创建的变量,需要通过tf.variable_scope函数来生成一个上下文管理器,并明确指定在这个上下文呢管理器中,tf.variable将直接获取已经生成的变量。
在上下文管理器中创建变量
with tf.Variable_scope("foo"): v = tf.get_Variable("v", [1], initializer=tf.constant_initializer(1.0))
获取“foo”上下文中的v变量
with tf.Variable_scope("foo", reuse=True): v = tf.get_Variable("v", [1])
当reuse=True时,tf.variable_scope将只能获取已经创建过的变量强调:(命名空间/变量名)
嵌套应用
获取当前上下文管理器中reuse参数的取值
适用于嵌套不明确的情况下
tf.get_variable_scope().reuse
当嵌套使用tf.variable_scope的时候,reuse标签具有继承性;如果我们打开一个重用的范围,那么它的自范围也会重用
命名空间
在命名空间内创建的变量名称会自动带上命名空间名作为前缀
在一个名称为空的命名空间中,并甚至reuse=True, 可以直接通过带命名空间的变量名来获取其他命名空间中的变量。
with tf.variable_scope("", reuse=True): v5 = tf.get_variable("foo/bar/v", [1])
TensorFlow模型持久化
持久化
保存和还原一个神经网络模型
API
tf.train.Saver类
声明类
saver = tf.train.Saver()
保存模型
saver.save(session, path)
加载模型
saver.restore(session,path)
数据结构
model.ckpt.meta
保存TensorFlow计算图的结构(神经网络的网络结构)
结构
model.ckpt
TensorFlow程序中每一个变量的取值
取值
计算图的结构和图上的参数取值都是分开保存的
checkpoint
保存一个目录下所有模型文件列表
文件列表
加载模型技巧
一般
从计算图文件中加载模型时,不需要对变量进行初始化
加载模型时,省略重复定义图上的运算
saver = tf.train.import_meta_graph(path)
保存或加载部分变量
在声明tf.train.Saver类时可以提供一个列表来指定需要保存或者加载的变量
saver = tf.train.Saver([v1])
只有v1变量会被加载进来
保存或加载变量时,重命名变量。
TensorFlow通过字典(dictionary)将模型保存时的变量名和需要加载的变量联系起来
应用
方便使用变量的滑动平均值
原因
在TensorFlow中,每一个变量的滑动平均值是通过影子变量维护的,所以要获取变量的滑动平均值实际上就是获得这个应自变量的取值。如果在加载模型时,直接将影子变量映射到变量自身,那么在使用训练好的模型时就不需要再调用函数来获取变量的滑动平均值。
简化操作
tf.train.ExponentialMovingAverage类
variables_to_restore函数
为方便加载时重命名滑动平均变量,以上函数可以生成tf.train.Saver类所需的变量重命名字典。
saver = tf.train.Saver(ema.variables_to_restore())
saver = tf.train.Saver("v/ExponentialMovingAverage" : v)
等价
常数保存计算图的变量及其取值
原因
测试或离线测试
只需要知道从神经网络的输入层经过前向传播计算得到输出层即可,而不需要类似于变量初始化、模型保存等辅助节点的信息。
将计算图结构和取值保存在一个文件,方便性
API
convert_variables_to_constants函数
步骤
导出当前计算图的GraphDef部分
graph_def = tf.get_default_graph().as_graph_def()
将图中的变量及其取值转化为常量,同时将图中不必要的节点去掉
output_graph_def = graph_util.convert_varables_to_constants(sess, graph_def, ['add'])
将导出的模型存入文件
with tf.gfile.GFile("/path/to/model/combined_model.pb","wb") as f: f.write(output_graph_def.SeriablizeToString())
加载常量模型
P117
TensorFlow最佳实践
优化方案
1、变量管理
2、持久化模型
在训练的过程中,需要每隔一段时间保存一次模型训练的结果
3、训练和测试分成两个独立的程序,更加灵活
4、将前向传播抽象成一个单独的库函数
因为训练和测试都要用到
举例:MNIST问题
mnist_inference
定义前向传播的过程和神经网络参数
mnist_train
训练
mnist_eval
测试
程序分解
mnist.inference
mnist_train
def train
def main()
读取数据
加载训练函数
if __name__=='__main__': tf.app.run()
mnist_eval