代码之家  ›  专栏  ›  技术社区  ›  ERed

TensorFlow 1.11.0在尝试用scope.Reusevariables()重用cudngru变量时引发错误。

  •  0
  • ERed  · 技术社区  · 6 年前

    我正在使用 tf.contrib.cudnn_rnn.CudnnGRU() 作为编码器,我发现了一个问题:

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

    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)
    

    这将引发以下错误:

    变量model/cudnn_gru_1/opaque_kernel不存在,或者不是用tf.get_variable()创建的。您是想在varscope中设置reuse=tf.auto_reuse吗?

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

    问题是,我不知道为什么会发生这种情况,因为通过跟踪变量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)
    

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

    提前谢谢

    1 回复  |  直到 6 年前
        1
  •  2
  •   saket    6 年前

    Cudngru看起来像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)
    

    我不知道为什么只有第二条路运行正常。

    编辑

    我发现cudngru在当前变量范围内唯一地为变量命名。

    首先,模型“2”会产生一个新的名称,比如“Cudnn-Gru-1”,使其名称独一无二。另一方面,第二种方法是创建一个新的变量范围,因此模型_2的唯一变量名与模型_1的唯一变量名相匹配。

    您可以找到为什么cudngru在layer.set_scope()(tensorflow\python\layers\base.py_l150)中使用唯一的变量名。layer类使用默认的\name参数为其变量创建一个新的变量作用域(在本例中,作用域为none),因此其名称变得唯一。