当尝试通过scope.reusevariables()重用cudnnGRU变量时,Tensorflow 1.11.0引发错误

时间:2018-10-21 10:55:40

标签: python tensorflow deep-learning rnn

我正在使用tf.contrib.cudnn_rnn.CudnnGRU()作为编码器来实现编码器-解码器rnn,但是我发现了一个问题:

我想重用变量,以便可以创建相同的模型,但将其与其他数据一起使用,并且简单地说,这就是重现我的问题的代码:

tf.reset_default_graph()

def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                         direction='unidirectional')

# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

with tf.variable_scope('model') as scope:
    model_1 = create_model()
    rnn_out_1, rnn_state_1 = model_1(x)
    scope.reuse_variables()
    model_2 = create_model()
    rnn_out_2, rnn_state_2 = model_2(x)

这将引发以下错误:

  

变量模型/ cudnn_gru_1 / opaque_kernel不存在,或者不是使用tf.get_variable()创建的。您是要在VarScope中设置复用= tf.AUTO_REUSE吗?

第二个模型正在尝试找到model/cudnn_gru_1/opaque_kernel变量,但找不到它,因为它应该在寻找model/cudnn_gru/opaque_kernel:0

问题是我不知道为什么会这样,因为遵循变量tensorflow参考似乎还可以。另一方面,我也尝试用不同的方式编写它,因为tensorflow doc指出我上面的实现和接下来要展示的实现实际上是相同的:

tf.reset_default_graph()

def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                         direction='unidirectional')

# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

with tf.variable_scope('model'):
    model_1 = create_model()
    rnn_out_1, rnn_state_1 = model_1(x)
with tf.variable_scope('model', reuse=True):
    model_2 = create_model()
    rnn_out_2, rnn_state_2 = model_2(x)

第二种方法实际上正在起作用(或者至少我认为是这样)。所以我真的不知道我在第一个实现中做错了什么,我也不确定两个实现是否应该做同样的事情(我认为他们应该这样做)。 那么,请问有人可以帮助我弄清楚我做错了什么或我无法正确理解的事情吗?

预先感谢

1 个答案:

答案 0 :(得分:2)

CudnnGRU看起来像是keras样式的Model对象。因此,您应该重用该对象以在

之类的层之间共享参数
def create_model():
    return tf.contrib.cudnn_rnn.CudnnGRU(num_layers=1, num_units=100,
                                  direction='unidirectional')


# (time, batch_size, num_inputs)
x = tf.random_normal((100, 16, 100))

model = create_model()
rnn_out_1, rnn_state_1 = model(x)
rnn_out_2, rnn_state_2 = model(x)

我不知道为什么只有第二种方法可以正确运行。

编辑

我发现CudnnGRU在其当前变量范围内为其变量创建唯一的变量名。

第一种方式,model_2可以使用诸如cudnn_gru_1之类的新名称来使其唯一。另一方面,通过第二种方法,您创建了一个新的变量作用域,因此model_2的唯一变量名称与model_1的唯一变量名称匹配。

您可以找到为什么CudnnGRU在Layer._set_scope()(tensorflow \ python \ layers \ base.py#L150)中使用唯一的变量名称的原因。 Layer类使用default_name参数为其变量创建了一个新的变量范围(在这种情况下,作用域为None),因此其名称变得唯一。