Tensorflow 1.11.0 在尝试使用 scope.reusevariables() 重用 cudnnGRU 变量时抛出错误

Tensorflow 1.11.0 throws an error when trying to reuse cudnnGRU variables with scope.reusevariables()

我正在通过使用 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)

这将引发以下错误:

Variable model/cudnn_gru_1/opaque_kernel does not exist, or was not created with tf.get_variable(). Did you mean to set reuse=tf.AUTO_REUSE in VarScope?

所以第二个模型试图找到 model/cudnn_gru_1/opaque_kernel 变量但找不到它,因为它应该寻找 model/cudnn_gru/opaque_kernel:0.

问题是我不知道为什么会这样,因为按照 Variables tensorflow 参考似乎没问题。另一方面,我也尝试以不同的方式编写它,因为 tensorflow 文档指出我上面的实现和我接下来展示的实现实际上是一样的:

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)

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

提前致谢

CudnnGRU 看起来像 keras 风格的模型对象。所以你应该重用这个对象来在层之间共享参数,比如

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.

的唯一变量名称相匹配

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