簡體   English   中英

盡管重用設置為true,Tensorflow仍創建新變量

[英]Tensorflow creating new variables despite reuse set to true

我正在嘗試構建基本的RNN,但是在訓練后嘗試使用網絡時會出錯。 我將網絡架構置於功能inference

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

到目前為止,我已經花了幾個小時閱讀有關變量作用域的信息,但是在運行預測時仍然遇到錯誤, Attempting to use uninitialized value RNN_1/inference/simple_rnn_2/kernel ,每次調用RNN_1的數量都會增加

在您向我們展示SimpleRNN實現之前,這只是猜測。 但是,我懷疑SimpleRNN實現非常差。 tf.get_variabletf.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_variable('w', initializer=1.)而不是w = tf.Variable(1., name='w')可以正常工作。

為什么? 參見文檔:

tf.get_variable:

使用這些參數獲取現有變量或創建一個新變量。 該函數使用當前變量作用域為名稱加上前綴,並執行重用檢查

編輯謝謝您的問題(我在您的問題中添加了keras標志)。 現在,這正成為我最喜歡的向人們展示為什么使用Keras是他們做出的最糟糕決定的原因。

SimpleRNN 在此處創建變量:

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)

這是實施中的明顯缺陷。 在Keras以正確的方式使用TensorFlow之前(至少要尊重scopesvariable-collections ),您應該尋找替代方案。 有人可以給你的最好建議是改用更好的東西,例如官方的tf.layers

@Patwie對錯誤做出了正確的診斷-參考Keras實現中可能存在錯誤。

但是,在我看來,合乎邏輯的結論不是關閉Keras,而是使用tensorflow隨附的Keras實現,該實現可在tf.keras找到。 您會發現在此實現中正確生成了變量。 tf.keras是專門為tf.keras量流實現的,應將此類接口錯誤降至最低。

實際上,如果您已經是張量流,那么使用參考tf.keras而不是tf.keras不會帶來任何特別的好處,除非您使用的是它的最新功能, tf.keras通常在版本方面tf.keras落后(例如,目前在TF 1.8 Wheras中的2.1.5,Keras 2.2.0已經發布了大約一個月。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM