Python Tensorflow在重用设置为true的情况下创建新变量

Python Tensorflow在重用设置为true的情况下创建新变量,python,tensorflow,keras,Python,Tensorflow,Keras,我正在尝试构建一个基本的RNN,但在培训后尝试使用网络时会出现错误。 我在函数推理 def inference(inp): with tf.name_scope("inference"): layer = SimpleRNN(1, activation='sigmoid', return_sequences=False)(inp) layer = Dense(1)(layer) return layer 但每次我调用它时,都会创建另一组变

我正在尝试构建一个基本的RNN,但在培训后尝试使用网络时会出现错误。 我在函数
推理

def inference(inp):
    with tf.name_scope("inference"):
        layer = SimpleRNN(1, activation='sigmoid',   return_sequences=False)(inp)
        layer = Dense(1)(layer)

    return layer 
但每次我调用它时,都会创建另一组变量,尽管在培训中使用了相同的作用域:

def train(sess, seq_len=2, epochs=100):
    x_input, y_input = generate_data(seq_len)

    with tf.name_scope('train_input'):
        x = tf.placeholder(tf.float32, (None, seq_len, 1))
        y = tf.placeholder(tf.float32, (None, 1))

    with tf.variable_scope('RNN'):
        output = inference(x)

    with tf.name_scope('training'):
        loss = tf.losses.mean_squared_error(labels=y, predictions=output)
        train_op = tf.train.RMSPropOptimizer(learning_rate=0.1).minimize(loss=loss, global_step=tf.train.get_global_step())

    with sess.as_default():
        sess.run([tf.global_variables_initializer(), tf.local_variables_initializer()])

        for i in tqdm.trange(epochs):
            ls, res, _ = sess.run([loss, output, train_op], feed_dict={x:x_input, y:y_input})
            if i%100==0:
                print(f'{ls}: {res[10]} - {y_input[10]}')
            x_input, y_input = generate_data(seq_len)
预测:

def predict_signal(sess, x, seq_len):   
    # Preparing signal (omitted)
    # Predict
    inp = tf.convert_to_tensor(prepared_signal, tf.float32)
    with sess.as_default():
        with tf.variable_scope('RNN', reuse=True) as scope:
            output = inference(inp)
            result = output.eval()

    return result

到目前为止,我已经花了几个小时阅读了变量范围,但是在运行预测时,我仍然得到一个错误
,试图使用未初始化的值RNN_1/推理/simple_RNN_2/内核
,其中RNN_1的数量随着每次调用的增加而增加

这只是猜测,直到您向我们展示
SimpleRNN
实现。然而,我怀疑
SimpleRNN
的实现非常糟糕。有一个不同的getween
tf.get_variable
tf.variable
。我希望您的
SimpleRNN
使用
tf.Variable

要重现这种行为:

import tensorflow as tf


def inference(x):
    w = tf.Variable(1., name='w')
    layer = x + w
    return layer


x = tf.placeholder(tf.float32)

with tf.variable_scope('RNN'):
    output = inference(x)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(output, {x: 10}))

    with sess.as_default():
        with tf.variable_scope('RNN', reuse=True):
            output2 = inference(x)

    print(sess.run(output2, {x: 10}))
这会产生完全相同的错误:

试图使用未初始化的值RNN_1/w

但是,使用
w=tf.get_变量('w',初始值设定项=1。)
而不是
w=tf.variable(1',name='w')
的版本可以工作

为什么??见文件:

获取具有这些参数的现有变量或创建新变量。 此函数使用当前变量范围作为名称的前缀,并执行重用检查

编辑 谢谢你的提问(我在你的问题中添加了keras标志)。这正成为我最喜欢的理由,向人们展示为什么使用Keras是他们做过的最糟糕的决定

单纯形

这个

哪个

这是实现中的一个明显缺陷。
在Keras以正确的方式使用TensorFlow之前(至少涉及
范围
变量集合
),您应该寻找替代方案。有人能给你的最好建议是切换到更好的版本,比如官方的
tf.layers

@Patwie对错误做出了正确的诊断-参考Keras实现中可能存在的错误

然而,在我看来,合乎逻辑的结论不是排除Keras,而是使用tensorflow附带的Keras实现,可以在
tf.Keras
中找到。您将发现在这个实现中正确地生成了变量
tf.keras
是专门为tensorflow实现的,应将此类接口错误降至最低


事实上,如果您已经是tensorflow,我看不到使用参考Keras而不是
tf.Keras
有什么特别的好处,除非您使用它的最新功能,
tf.Keras
在版本上通常有点落后(例如,目前在TF1.8中是2.1.5,而Keras 2.2.0已经发布了大约一个月).

我使用来自keras的SimpleRN实现keras有太多问题。Keras不尊重
范围
集合
打破TensorFlow的所有常见假设。有人能给你的最好建议就是坚持使用官方的
tf.layers
。现在凯拉斯·范博伊斯让落选开始了。伟大的观察@Patwie!我遇到了一些来自keras simpleRNN的奇怪行为,他们试图解决一个相当简单的任务。发布了关于它的消息。我相信这是由于这个实现错误造成的。切换到keras tf似乎可以解决这个问题。只是想让你的观点更有力,我现在坚信,如果你使用tensorflow,那么就使用专门为它实现的keras,而不是一般的keras。我还没有测试过tf.keras。但是快速查看一下实现,就会发现
add\u weight
中涉及到更多的逻辑。我这边请大家投票,建议使用tf.keras来代替keras(我认为它们应该是一样的)。但是如果这有帮助,为什么不呢。
self.kernel = self.add_weight(shape=(input_shape[-1], self.units),
                                      name='kernel',...)
weight = K.variable(initializer(shape),
                    dtype=dtype,
                    name=name,
                    constraint=constraint)
v = tf.Variable(value, dtype=tf.as_dtype(dtype), name=name)