在这篇 TensorFlow 教程中,我们将学习如下内容:

  • TensorFlow 模型文件是怎么样的?
  • 如何保存一个 TensorFlow 模型?
  • 如何恢复一个 TensorFlow 模型?
  • 如何使用一个训练好的模型进行修改和微调?

1. TensorFlow 模型文件

在你训练完一个神经网络之后,你可能需要将这个模型保存下来,在后续实验中使用或者进行生产部署。那么,TensorFlow 模型文件长什么样呢?TensorFlow 模型主要包含我们已经训练好的网络设计(计算图)和网络参数。因此,TensorFlow 模型主要有两个文件:

  1. 元图(meta graph) 
    这是一个保存完整的 TensorFlow 图的协议缓存区,即所有的变量,操作,集合等等。该文件具有 .meta 扩展名。
  2. 检查点文件(checkpoint file) 
    这是一个二进制文件,其中包含所有的权重,偏差,梯度和其他所有保存的值。这个文件的扩展名是 .ckpt。然而,TensorFlow 从版本 0.11 开始已经不再使用一个 .ckpt 文件来表示了,而是采用两个文件,如下:
mymodel.data-00000-of-00001
mymodel.index

.data 文件是包含我们训练变量的文件。除此之外,TensorFlow 还有一个名为 checkpoint 的文件,它用来保存最新检查点的记录。

所以,总而言之,版本大于 0.11 的 TensorFlow 模型文件如下所示:

my_test_model-1000.index
my_test_model-1000.meta
my_test_model-1000.data-00000-of-00001 checkpoin

2. 保存一个 TensorFlow 模型

假设,你正在使用卷积神经网络训练一个图像分类模型。一个传统做法是,你一直在关注损失值和正确率这两个指标,一旦你发现网络收敛了,那么你就会手动停止训练,或者你会运行固定的训练次数然后结束训练。在完成训练之后,我们希望将所有的变量和计算图都保存起来,以便于未来使用。所以,在 TensorFlow 中,我们可以使用 tf.train.Saver() 实例来保存所有的参数和计算图。

saver = tf.train.Saver()
  • 1

请记住,TensorFlow 变量只在会话(session)中存在。因此,你必须在会话中,调用刚刚创建好的 save 方法,将模型保存起来。

saver.save(sess, 'my-test-model')
  • 1

在这里, sess 是一个会话对象,而 my-test-model 就是你给模型起的名字。接下来,让我们看一个完整的例子:

#!/use/bin/env python
# -*- coding: utf-8 -*-

import tensorflow as tf 

w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1') w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2') saver = tf.train.Saver(www.feifanyule.cn/) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.save(sess, './model/my_test_model')

运行上面这个代码,我们可以得到如下的模型文件结构:

model/
├── checkpoint
├── my_test_model.data-00000-of-00001
├── my_test_model.index
└── my_test_model.meta

如果你想在 1000 次迭代之后再保存模型,那么我们可以通过传递步数来调用 save ,如下:

saver.save(sess, 'my_test_model', global_step=1000)
  • 1

这个代码会在模型文件之后添加上 -1000 ,如下:

my_test_model-1000.index
my_test_model-1000.meta
my_test_model-1000.data-00000-of-00001 checkpoint

比如说,在训练的时候,我们每 1000 次保存一下模型,所以 .meta 文件只会在第一次保存的时候创建(也就是第 1000 次的时候),我们不需要在每次保存文件的时候再去创建 .meta 文件。我们只需要保存模型进一步迭代的数据,因为模型的计算图不会再变化。因此,当我们不想要去保存计算图的时候,我们可以使用如下命令:

saver.save(sess, 'my-model', global_step=step,write_meta_graph=False)

如果你只想保存最新的 4 个模型参数,并且希望在训练期间每隔 2 小时保存一个模型,那么我们可以使用 max_to_keep参数和 keep_checkpoint_every_n_hours 参数。

# saves a model every 2 hours and maximum 4 latest models are saved.
saver = tf.train.Saver(max_to_keep=4, keep_checkpoint_every_n_hours=2)

请注意,如果我们没有在 tf.train.Saver() 中指定任何东西,那么它会保存模型所有的变量。如果我们不想保存所有的变量,只想保存其中的某些变量,那么应该怎么操作呢?我们可以指定我们想要保存的变量。在创建 tf.train.Saver()实例时,我们将需要保存的变量通过列表或者字典的形式传入进去。让我们来看一个例子:

#!/use/bin/env python
# -*- coding: utf-8 -*-

import tensorflow as tf 

w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1') w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2') saver = tf.train.Saver([w1, w2]) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.save(sess, './model/my_model', global_step=1000

这个操作可以用来帮助我们去保存 TensorFlow 图中某些特定的部分。

3. 导入一个预训练的模型

如果你想使用别人的预训练好的模型进行微调,那么你需要做两件事:

  1. 构建网络结构 
    你可以通过编写 Python 代码来重新构建整个网络,手动来创建网络中的每一个层。但是,因为我们已经将网络保存在 .meta 文件中了,我们可以直接使用 tf.train.import() 函数来导入这个模型,如下所示:saver = tf.train.import_meta_graph('my_test_model-1000.meta') 。

请记住,import_meta_graph 将 .meta 文件中定义的计算图数据直接附加到我们定义的当前图中。因此,这个操作会帮助我们创建计算图,但是我们仍然需要去加载计算图上面所有已经训练好的权重参数。

  1. 加载参数 
    我们可以通过调用这个 tf.train.Saver() 类来恢复我们网络的参数。
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('./'))

导入之后,类似 w1 和 w2 这样的张量值就可以被访问了。

with tf.Session() as sess:    
    saver = tf.train.import_meta_graph('my-model-1000.meta')
    saver.restore(sess,tf.train.latest_checkpoint('./'))
    print(sess.run('w1:0'))

所以,现在你已经了解了 TensorFlow 模型的保存和载入。在下面一节中,我将给你介绍在实际的工作中是如何来加载一个预训练的模型。

4. 使用恢复的模型

现在,你已经了解了如何去保存和载入一个 TensorFlow 模型,接下来让我们学习一个实际中可以使用的开发方式,用来恢复任何预先训练好的模型,并将其用于模型预测,模型微调或者进一步模型训练。无论你什么时候使用 TensorFlow ,你都需要定义一个计算图来训练数据,学习一些超参数(比如,学习率,步长等等)。使用占位符来输入训练数据和超参数是一种标准的做法。接下来,让我们使用占位符来构建一个小的网络并且保存这个网络,请注意,当我们保存网络的时候,占位符中的值是不进行保存的。

#!/use/bin/env python
# -*- coding: utf-8 -*-


import tensorflow as tf

w1 = tf.placeholder("float",www.vboyule.cn  name="w1") w2 = tf.placeholder("float", name="w2www.baohuayule.net ") b1= tf.Variable(2.0,name="bias") #Define a test operation that we will restore w3 = tf.add(w1,w2) w4 = tf.multiply(w3,b1,name="op_to_restore") #Create a saver object which will save all the variables saver = tf.train.Saver(www.tianhengyl1.com) with tf.Session() as sess: sess.run(tf.global_variables_initializer(www.thd178.com)) print(sess.run(w4,feed_dict ={w1:4,w2:8})) saver.save(sess, 'my_test_model',global_step=1000)

现在,当我们想要去载入这个模型时,我们不仅需要恢复所有的计算图和参数权重,而且还要准备一个新的 feed_dict,用来将新的训练数据送到网络中进行训练。我们可以通过 graph.get_tensor_by_name() 方法来获得对这些保存的操作和占位符变量的引用。

#How to access saved variable/Tensor/placeholders 
w1 = graph.get_tensor_by_name("www.120xh.cn  w1:0")

## How to access saved operation op_to_restore = graph.get_tensor_by_name("op_to_restore:0"

如果我们只想用不同的数据来运行相同的网络,那么我们只需要通过 feed_dict 来给网络传递数据就可以了。

with tf.Session() as sess:
    saver = tf.train.import_meta_graph(www.qinlinyule.cn 'my_test_model-1000.meta')
    saver.restore(sess,tf.www.089188.cn train.latest_checkpoint('./'))
    graph = tf.get_default_graph()
    w1 = graph.get_tensor_by_name("w1:0") w2 = graph.get_tensor_by_name("w2:0") feed_dict ={w1:13.0,w2:17.0} op_to_restore = graph.get_tensor_by_name("op_to_restore:0") print(sess.run(op_to_restore,feed_dict))

如果你想在原来的计算图基础上添加更多的操作和图层,并且进行训练。那么你可以按照如下操作来编写:

import tensorflow as tf

with tf.Session() as sess:
    saver = tf.train.import_meta_graph('my_test_model-1000.meta') saver.restore(sess,tf.train.latest_checkpoint('./')) graph = tf.get_default_graph() w1 = graph.get_tensor_by_name("w1:0") w2 = graph.get_tensor_by_name("w2:0") feed_dict ={w1:13.0,w2:17.0} op_to_restore = graph.get_tensor_by_name("op_to_restore:0") # 添加新的操作 add_on_op = tf.multiply(op_to_restore, 2.) print(sess.run(add_on_op,feed_dict))

但是,我们可以恢复原图中的一部分,然后自己再添加一部分图,重新组成一张新的计算图来记性微调计算吗?当然可以,我们可以通过 graph.get_tensor_by_name() 来访问相应的操作,并且在其上构建计算图。我们来举一个真实的例子,我们通过 .meta 文件来导入一个 VGG 预训练好的模型,然后把最后的输出改为二分类,最后在新数据上面对这个模型进行微调。



 


转载于:


在这篇 TensorFlow 教程中,我们将学习如下内容:

  • TensorFlow 模型文件是怎么样的?
  • 如何保存一个 TensorFlow 模型?
  • 如何恢复一个 TensorFlow 模型?
  • 如何使用一个训练好的模型进行修改和微调?

1. TensorFlow 模型文件

在你训练完一个神经网络之后,你可能需要将这个模型保存下来,在后续实验中使用或者进行生产部署。那么,TensorFlow 模型文件长什么样呢?TensorFlow 模型主要包含我们已经训练好的网络设计(计算图)和网络参数。因此,TensorFlow 模型主要有两个文件:

  1. 元图(meta graph) 
    这是一个保存完整的 TensorFlow 图的协议缓存区,即所有的变量,操作,集合等等。该文件具有 .meta 扩展名。
  2. 检查点文件(checkpoint file) 
    这是一个二进制文件,其中包含所有的权重,偏差,梯度和其他所有保存的值。这个文件的扩展名是 .ckpt。然而,TensorFlow 从版本 0.11 开始已经不再使用一个 .ckpt 文件来表示了,而是采用两个文件,如下:
mymodel.data-00000-of-00001
mymodel.index

.data 文件是包含我们训练变量的文件。除此之外,TensorFlow 还有一个名为 checkpoint 的文件,它用来保存最新检查点的记录。

所以,总而言之,版本大于 0.11 的 TensorFlow 模型文件如下所示:

my_test_model-1000.index
my_test_model-1000.meta
my_test_model-1000.data-00000-of-00001 checkpoin

2. 保存一个 TensorFlow 模型

假设,你正在使用卷积神经网络训练一个图像分类模型。一个传统做法是,你一直在关注损失值和正确率这两个指标,一旦你发现网络收敛了,那么你就会手动停止训练,或者你会运行固定的训练次数然后结束训练。在完成训练之后,我们希望将所有的变量和计算图都保存起来,以便于未来使用。所以,在 TensorFlow 中,我们可以使用 tf.train.Saver() 实例来保存所有的参数和计算图。

saver = tf.train.Saver()
  • 1

请记住,TensorFlow 变量只在会话(session)中存在。因此,你必须在会话中,调用刚刚创建好的 save 方法,将模型保存起来。

saver.save(sess, 'my-test-model')
  • 1

在这里, sess 是一个会话对象,而 my-test-model 就是你给模型起的名字。接下来,让我们看一个完整的例子:

#!/use/bin/env python
# -*- coding: utf-8 -*-

import tensorflow as tf 

w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1') w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2') saver = tf.train.Saver(www.feifanyule.cn/) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.save(sess, './model/my_test_model')

运行上面这个代码,我们可以得到如下的模型文件结构:

model/
├── checkpoint
├── my_test_model.data-00000-of-00001
├── my_test_model.index
└── my_test_model.meta

如果你想在 1000 次迭代之后再保存模型,那么我们可以通过传递步数来调用 save ,如下:

saver.save(sess, 'my_test_model', global_step=1000)
  • 1

这个代码会在模型文件之后添加上 -1000 ,如下:

my_test_model-1000.index
my_test_model-1000.meta
my_test_model-1000.data-00000-of-00001 checkpoint

比如说,在训练的时候,我们每 1000 次保存一下模型,所以 .meta 文件只会在第一次保存的时候创建(也就是第 1000 次的时候),我们不需要在每次保存文件的时候再去创建 .meta 文件。我们只需要保存模型进一步迭代的数据,因为模型的计算图不会再变化。因此,当我们不想要去保存计算图的时候,我们可以使用如下命令:

saver.save(sess, 'my-model', global_step=step,write_meta_graph=False)

如果你只想保存最新的 4 个模型参数,并且希望在训练期间每隔 2 小时保存一个模型,那么我们可以使用 max_to_keep参数和 keep_checkpoint_every_n_hours 参数。

# saves a model every 2 hours and maximum 4 latest models are saved.
saver = tf.train.Saver(max_to_keep=4, keep_checkpoint_every_n_hours=2)

请注意,如果我们没有在 tf.train.Saver() 中指定任何东西,那么它会保存模型所有的变量。如果我们不想保存所有的变量,只想保存其中的某些变量,那么应该怎么操作呢?我们可以指定我们想要保存的变量。在创建 tf.train.Saver()实例时,我们将需要保存的变量通过列表或者字典的形式传入进去。让我们来看一个例子:

#!/use/bin/env python
# -*- coding: utf-8 -*-

import tensorflow as tf 

w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1') w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2') saver = tf.train.Saver([w1, w2]) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) saver.save(sess, './model/my_model', global_step=1000

这个操作可以用来帮助我们去保存 TensorFlow 图中某些特定的部分。

3. 导入一个预训练的模型

如果你想使用别人的预训练好的模型进行微调,那么你需要做两件事:

  1. 构建网络结构 
    你可以通过编写 Python 代码来重新构建整个网络,手动来创建网络中的每一个层。但是,因为我们已经将网络保存在 .meta 文件中了,我们可以直接使用 tf.train.import() 函数来导入这个模型,如下所示:saver = tf.train.import_meta_graph('my_test_model-1000.meta') 。

请记住,import_meta_graph 将 .meta 文件中定义的计算图数据直接附加到我们定义的当前图中。因此,这个操作会帮助我们创建计算图,但是我们仍然需要去加载计算图上面所有已经训练好的权重参数。

  1. 加载参数 
    我们可以通过调用这个 tf.train.Saver() 类来恢复我们网络的参数。
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('./'))

导入之后,类似 w1 和 w2 这样的张量值就可以被访问了。

with tf.Session() as sess:    
    saver = tf.train.import_meta_graph('my-model-1000.meta')
    saver.restore(sess,tf.train.latest_checkpoint('./'))
    print(sess.run('w1:0'))

所以,现在你已经了解了 TensorFlow 模型的保存和载入。在下面一节中,我将给你介绍在实际的工作中是如何来加载一个预训练的模型。

4. 使用恢复的模型

现在,你已经了解了如何去保存和载入一个 TensorFlow 模型,接下来让我们学习一个实际中可以使用的开发方式,用来恢复任何预先训练好的模型,并将其用于模型预测,模型微调或者进一步模型训练。无论你什么时候使用 TensorFlow ,你都需要定义一个计算图来训练数据,学习一些超参数(比如,学习率,步长等等)。使用占位符来输入训练数据和超参数是一种标准的做法。接下来,让我们使用占位符来构建一个小的网络并且保存这个网络,请注意,当我们保存网络的时候,占位符中的值是不进行保存的。

#!/use/bin/env python
# -*- coding: utf-8 -*-


import tensorflow as tf

w1 = tf.placeholder("float",www.vboyule.cn  name="w1") w2 = tf.placeholder("float", name="w2www.baohuayule.net ") b1= tf.Variable(2.0,name="bias") #Define a test operation that we will restore w3 = tf.add(w1,w2) w4 = tf.multiply(w3,b1,name="op_to_restore") #Create a saver object which will save all the variables saver = tf.train.Saver(www.tianhengyl1.com) with tf.Session() as sess: sess.run(tf.global_variables_initializer(www.thd178.com)) print(sess.run(w4,feed_dict ={w1:4,w2:8})) saver.save(sess, 'my_test_model',global_step=1000)

现在,当我们想要去载入这个模型时,我们不仅需要恢复所有的计算图和参数权重,而且还要准备一个新的 feed_dict,用来将新的训练数据送到网络中进行训练。我们可以通过 graph.get_tensor_by_name() 方法来获得对这些保存的操作和占位符变量的引用。

#How to access saved variable/Tensor/placeholders 
w1 = graph.get_tensor_by_name("www.120xh.cn  w1:0")

## How to access saved operation op_to_restore = graph.get_tensor_by_name("op_to_restore:0"

如果我们只想用不同的数据来运行相同的网络,那么我们只需要通过 feed_dict 来给网络传递数据就可以了。

with tf.Session() as sess:
    saver = tf.train.import_meta_graph(www.qinlinyule.cn 'my_test_model-1000.meta')
    saver.restore(sess,tf.www.089188.cn train.latest_checkpoint('./'))
    graph = tf.get_default_graph()
    w1 = graph.get_tensor_by_name("w1:0") w2 = graph.get_tensor_by_name("w2:0") feed_dict ={w1:13.0,w2:17.0} op_to_restore = graph.get_tensor_by_name("op_to_restore:0") print(sess.run(op_to_restore,feed_dict))

如果你想在原来的计算图基础上添加更多的操作和图层,并且进行训练。那么你可以按照如下操作来编写:

import tensorflow as tf

with tf.Session() as sess:
    saver = tf.train.import_meta_graph('my_test_model-1000.meta') saver.restore(sess,tf.train.latest_checkpoint('./')) graph = tf.get_default_graph() w1 = graph.get_tensor_by_name("w1:0") w2 = graph.get_tensor_by_name("w2:0") feed_dict ={w1:13.0,w2:17.0} op_to_restore = graph.get_tensor_by_name("op_to_restore:0") # 添加新的操作 add_on_op = tf.multiply(op_to_restore, 2.) print(sess.run(add_on_op,feed_dict))

但是,我们可以恢复原图中的一部分,然后自己再添加一部分图,重新组成一张新的计算图来记性微调计算吗?当然可以,我们可以通过 graph.get_tensor_by_name() 来访问相应的操作,并且在其上构建计算图。我们来举一个真实的例子,我们通过 .meta 文件来导入一个 VGG 预训练好的模型,然后把最后的输出改为二分类,最后在新数据上面对这个模型进行微调。