使用tf.data.Dataset可以使保存的模型更大

时间:2018-04-09 12:33:54

标签: python tensorflow

我最近遇到了以更大的尺寸保存模型的问题。 我正在使用 tensorflow 1.4

之前,我用过

tf.train.string_input_producer()tf.train.batch()

从文本文件加载图像。在培训中,

tf.train.start_queue_runners()tf.train.Coordinator()

用于向网络提供数据。在这种情况下,每次我使用

保存模型

saver.save(sess, checkpoint_path, global_step=iters)

只给了我一个小尺寸的文件,即一个名为 model.ckpt-1000.data-00000-of-00001 的文件,只有1.6MB。

现在,我使用

tf.data.Dataset.from_tensor_slices()

将图像提供给输入placeholder,保存的模型变为290MB。但我不知道为什么。我怀疑张量流saver也将数据集保存到模型中。如果是这样,如何删除它们以使其变小,并且仅保存网络的权重。

这不是网络依赖,因为我在两个网络中尝试过它们都是这样的。

我用谷歌搜索,但遗憾的是没有看到任何与此问题有关的灵感。 (或者这不是问题,只是我不知道怎么办?)

非常感谢您的任何想法和帮助!

修改

我初始化数据集的方法是:

1.首先生成numpy.array数据集:

self.train_hr, self.train_lr = cifar10.load_dataset(sess)

初始数据集是numpy.array,例如[8000,32,32,3]。我将sess传递给此函数是因为在函数中,我执行了tf.image.resize_images()并使用sess.run()生成numpy.array。返回self.train_hrself.train_lr的形状numpy.array[8000,64,64,3]

2.然后我创建了数据集:

self.img_hr = tf.placeholder(tf.float32)
self.img_lr = tf.placeholder(tf.float32)
dataset = tf.data.Dataset.from_tensor_slices((self.img_hr, self.img_lr))
dataset = dataset.repeat(conf.num_epoch).shuffle(buffer_size=conf.shuffle_size).batch(conf.batch_size)
self.iterator = dataset.make_initializable_iterator()
self.next_batch = self.iterator.get_next()

3.然后我初始化了网络和数据集,进行了培训并保存了模型:

self.labels = tf.placeholder(tf.float32,
                                     shape=[conf.batch_size, conf.hr_size, conf.hr_size, conf.img_channel])
self.inputs = tf.placeholder(tf.float32,
                                     shape=[conf.batch_size, conf.lr_size, conf.lr_size, conf.img_channel])
self.net = Net(self.labels, self.inputs, mask_type=conf.mask_type,
                       is_linear_only=conf.linear_mapping_only, scope='sr_spc')

sess.run(self.iterator.initializer,
                         feed_dict={self.img_hr: self.train_hr, self.img_lr: self.train_lr})
while True:
    hr_img, lr_img = sess.run(self.next_batch)
    _, loss, summary_str = sess.run([train_op, self.net.loss, summary_op],
                                    feed_dict={self.labels: hr_img, self.inputs: lr_img})
    ...
    ...
    checkpoint_path = os.path.join(conf.model_dir, 'model.ckpt')
    saver.save(sess, checkpoint_path, global_step=iters)

所有sess都是相同的实例。

3 个答案:

答案 0 :(得分:2)

我怀疑您从数据集中创建了张量流常量tf.constant,这可以解释数据集与图表一起存储的原因。有一个可初始化的数据集,可让您在运行时使用feed_dict提供数据。它需要配置一些额外的代码,但它可能是您想要使用的。

https://www.tensorflow.org/programmers_guide/datasets

请注意,在Python包装器中自动为您创建常量。以下陈述是等效的:

tf.Variable(42)
tf.Variable(tf.constant(42))

答案 1 :(得分:0)

Tensorflow确实会保存您的数据集。要解决它,让我们理解为什么。

张量流如何工作以及它节省了什么?

简而言之,Tensorflow API允许您通过代码构建计算图,然后对其进行优化。您在图中定义的每个op / variable / constant都在处理张量并且是该图的一部分。这个框架很方便,因为Tensorflow只是构建一个图形,然后框架决定(或指定)计算图形的位置,以便从硬件中获得最大速度,例如,通过在GPU上进行计算。

GPU就是一个很好的例子,因为这是一个很好的例子。从HDD / RAM /处理器向GPU发送数据在时间上是昂贵的。因此,Tensorflow还允许您创建输入生成器,通过排队和管理threads,几乎可以自动管理在所有外围设备之间传输的数据。但是,我从这种方法中获得了很多好处。 请注意,数据集生成的输入也是张量,特别是用作网络输入的常量/变量。。因此,它们是图表的一部分。

保存图表时,我们会保存以下几项内容:

  1. 元数据 - 定义图形及其结构。
  2. 值 - 图中每个变量/常量,以便加载并重用网络。
  3. 使用数据集时,会保存不可训练变量的值,因此检查点文件会更大。

    要更好地理解数据集,请在包文件中查看其实现。

    TL; DR - 如何解决问题?

    1. 如果没有降低性能,请使用提供字典来提供占位符。不要使用张量来存储数据。这样就不会保存这些变量。

    2. 仅保存您要加载的张量(权重,偏差等)。您可以使用.eval()方法查找其值,将其另存为JSON等,然后通过重新构建图表来加载它。

    3. 祝你好运!

答案 2 :(得分:0)

我解决了这个问题(不完美,因为我还不知道问题发生在哪里)。相反,我做了一个解决方法,以避免保存大量数据。

我在一个特定的变量列表中定义了一个saver。该列表仅包含我的图表的节点。在这里,我展示了我的解决方法的一个小例子:

import tensorflow as tf  

v1= tf.Variable(tf.random_normal([784, 200], stddev=0.35), name="v1")  
v2= tf.Variable(tf.zeros([200]), name="v2")  

saver = tf.train.Saver( [v2])  
# saver = tf.train.Saver()  
with tf.Session() as sess:  
    init_op = tf.global_variables_initializer()  
    sess.run(init_op)  
    saver.save(sess,"checkpoint/model_test",global_step=1)

v2是变量列表。或者您可以使用variables_list = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='net')收集所有节点。