Python 在Estimator SessionRunHook中更改tf.变量值

Python 在Estimator SessionRunHook中更改tf.变量值,python,tensorflow,Python,Tensorflow,我有一个tf.估计器,它的model\u fn包含一个初始化为1.0的tf.变量。我想根据dev集合上的精度更改每个历元的变量值。为了实现这一点,我实现了一个SessionRunHook,但当我尝试更改该值时,收到以下错误: raiseruntimeerror(“图形已完成,无法修改”) 这是挂钩的代码: class DynamicWeightingHook(tf.train.SessionRunHook): def __init__(self, epoch_size,

我有一个tf.估计器,它的
model\u fn
包含一个初始化为1.0的tf.变量。我想根据dev集合上的精度更改每个历元的变量值。为了实现这一点,我实现了一个
SessionRunHook
,但当我尝试更改该值时,收到以下错误:

raiseruntimeerror(“图形已完成,无法修改”)

这是挂钩的代码:

    class DynamicWeightingHook(tf.train.SessionRunHook):
        def __init__(self, epoch_size, gamma_value):
            self.gamma = gamma_value
            self.epoch_size = epoch_size
            self.steps = 0

        def before_run(self, run_context):
            self.steps += 1

        def after_run(self, run_context, run_values):
            if self.steps % epoch_size == 0:  # epoch 
                with tf.variable_scope("lambda_scope", reuse=True):
                    lambda_tensor = tf.get_variable("lambda_value")
                    tf.assign(lambda_tensor, self.gamma_value)
                    self.gamma_value += 0.1

我知道当我运行钩子时,图形已经完成,但我想知道是否有其他方法可以在培训期间使用Estimator API更改model_fn图形中的变量值。

现在设置钩子的方法实际上是在每次会话运行后创建新的变量/操作。相反,您应该预先定义
tf.assign
op,并将其传递给钩子,以便钩子在必要时可以自己运行op,或者在钩子的
\uuuuu init\uuuu
中定义assign op。您可以通过
run\u上下文
参数在运行后访问
内的会话。大概是

class DynamicWeightingHook(tf.train.SessionRunHook):
    def __init__(self, epoch_size, gamma_value, lambda_tensor):
        self.gamma = gamma_value
        self.epoch_size = epoch_size
        self.steps = 0
        self.update_op = tf.assign(lambda_tensor, self.gamma_placeholder)

    def before_run(self, run_context):
        self.steps += 1

    def after_run(self, run_context, run_values):
        if self.steps % epoch_size == 0:  # epoch 
            run_context.session.run(self.update_op)
            self.gamma += 0.1
这里有一些警告。首先,我不确定是否可以使用类似这样的Python整数执行
tf.assign
,也就是说,一旦更改
gamma
,它是否会正确更新。如果这不起作用,您可以尝试以下方法:

class DynamicWeightingHook(tf.train.SessionRunHook):
    def __init__(self, epoch_size, gamma_value, lambda_tensor):
        self.gamma = gamma_value
        self.epoch_size = epoch_size
        self.steps = 0
        self.gamma_placeholder = tf.placeholder(tf.float32, [])
        self.update_op = tf.assign(lambda_tensor, self.gamma_placeholder)

    def before_run(self, run_context):
        self.steps += 1

    def after_run(self, run_context, run_values):
        if self.steps % epoch_size == 0:  # epoch 
            run_context.session.run(self.update_op, feed_dict={self.gamma_placeholder: self.gamma})
            self.gamma += 0.1
在这里,我们使用一个额外的占位符,以便能够始终将“当前”伽马传递给assign op


其次,由于钩子需要访问变量,因此需要在模型函数中定义钩子。您可以在
spec
中将这些挂钩传递到培训过程中(请参阅)。

谢谢,这是一个好主意。我认为应该在Tensorflow文档中提到它。我将我的操作添加到了uuu init_uuuuu()函数中,并在u run()之前运行它们,结果成功了。