如何将张量还原为过去的值,而不将值保存到磁盘?

2024-04-23 09:24:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我在做张量流的实验,遇到了一个障碍。我试图用TF来评估模型中的变化,然后根据损失函数的变化保留或恢复模型。我已经解决了最难的部分(条件控制),但我仍然坚持一些应该相当简单的事情:我似乎不能为迭代存储tf.trainable_variables,然后在需要时恢复它。在

假设一个构建一个操作:

...
store_trainable_vars = []

for v in tf.trainable_variables():

    store_trainable_vars.append(v)
...

然后,我想将tf.trainable_variables还原为上次运行此操作时的值。我想做些类似的事情:

^{pr2}$

显然,这将重新计算store_trainable_vars,后者又链接到tf.trainable_variables()的当前值,从而避免了{}操作。我需要一些方法来存储和检索张量的值,而不需要回呼这些张量的当前值。有点像

...
store_trainable_vars = []

for v in tf.trainable_variables():

    store_trainable_vars.append(v.value_right_now())
...

其中v.value_right_now()返回一个常量,该常量在重写之前不会更改。在

我知道我可以使用Saver,但是这个解决方案会写入磁盘,这对于这个应用程序来说是不可接受的,因为它将在一个训练循环中运行。在

我可能遗漏了一些显而易见的东西-任何指导都会很感激。在


Tags: storein模型rightforvaluetfvars
2条回答

要手动恢复图形状态,您需要使用^{}^{}操作,这将修改大容量更改的流:

This creates a tuple of tensors with the same values as the tensors argument, except that the value of each tensor is only returned after the values of all tensors have been computed.

[更新]我可以这样做:

import numpy as np
import tensorflow as tf

x = tf.placeholder(shape=[None, 5], dtype=tf.float32, name='x')
W = tf.Variable(np.zeros([5, 5]), dtype=tf.float32, name='W')
b = tf.Variable(np.zeros([5]), dtype=tf.float32, name='b')
y = tf.add(tf.matmul(x, W), b)

with tf.Session() as session:
  batch = np.ones([2, 5])
  session.run(tf.global_variables_initializer())
  print session.run(y, feed_dict={x: batch})      # prints [2, 5] zeros

  # store the current value
  store = {v.name: v.eval(session) for v in tf.trainable_variables()}
  print store                                     # prints [5, 5] and [5] zeros

  # update
  new = {'W:0': np.ones([5, 5]), 'b:0': np.ones([5])}
  session.run(tf.tuple([tf.assign(var, new[var.name]) for var in tf.trainable_variables()]))
  print session.run(y, feed_dict={x: batch})      # prints [2, 5] sixes

  # restore
  session.run(tf.tuple([tf.assign(var, store[var.name]) for var in tf.trainable_variables()]))
  print session.run(y, feed_dict={x: batch})      # prints [2, 5] zeros again

但是我真的认为你应该重新考虑你关于Saver的决定,因为它也是设计用来在训练循环中使用的。在内部,Saver会为您完成所有棘手的工作(尤其是,如果需要,它还可以执行restore op调用tf.group和{}),否则可能会成为非常讨厌的bug的来源。此外,磁盘(几乎)总是比你的GPU和主内存大,所以如果你能负担得起在内存中存储模型,你也应该能够在磁盘上存储。在

以下是有助于控制磁盘上检查点文件扩散的some parameters

  • max_to_keep表示最近检查点文件的最大数量 保持。创建新文件时,会删除旧文件。如果无或0,则保留所有检查点文件。默认为5(即最近的5个 保留检查点文件)。在
  • keep_checkpoint_every_n_hours:除了保留最新的 max_to_keep检查点文件,您可能希望保留一个检查点文件 每N小时的训练。如果您以后想用的话,这会很有用 分析一个模型在一个长时间的培训过程中是如何发展的。为 例如,传递keep_checkpoint_every_n_hours=2可确保每2小时培训保留一个检查点文件。默认值10000小时将有效地禁用该功能。在

[Update]如评论中所述,主要问题是磁盘延迟,如果访问太频繁,可能会减慢训练速度。如果您正在使用Linux,它caches经常使用的磁盘页,Windows does it也是。{但是如果你确实想用^的话。在

我并不是想亲自回答这个问题,但我想出了一个行之有效的方法。所以,我想分享一下。{很聪明的答案来自于洞察力。方法是重用为初始变量赋值创建的赋值节点。下面给出了实现该方法的完整类。在

import tensorflow as tf


class TensorFlowState(object):

    def __init__(self):

        # Get the graph.
        graph = tf.get_default_graph()

        # Extract the global varibles from the graph.
        self.gvars = graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)

        # Exract the Assign operations for later use.
        self.assign_ops = [graph.get_operation_by_name(v.op.name + "/Assign")
                           for v in self.gvars]

        # Extract the initial value ops from each Assign op for later use.
        self.init_values = [op.inputs[1] for op in self.assign_ops]

    def start(self, sess):

        self.sess = sess

    def store(self):

        # Record the current state of the TF global varaibles
        self.state = self.sess.run(self.gvars)

    def restore(self):
    # Create a dictionary of the iniailizers and stored state of globals.
    feed_dict = {init_value: val
                 for init_value, val in zip(self.init_values, self.state)}

    # Use the initializer ops for each variable to load the stored values.
    return(self.sess.run(self.assign_ops, feed_dict=feed_dict))

要使用,只需实例化该类,调用start方法来传递tf.Session,并根据需要在命令式训练循环中调用store和{}方法。我用这个实现构建了一个优化器,它的运行速度和TensorFlow中包含的梯度下降优化器一样快。在

相关问题 更多 >