【问题标题】:Tensorflow reuse variables different before and after training训练前后不同的 TensorFlow 重用变量
【发布时间】:2016-11-22 20:59:58
【问题描述】:

在尝试了解一些有关 Tensorflow 的信息时,我一直在构建一个变分自动编码器,它正在工作,但是我注意到,在训练之后,我从共享相同变量的解码器中得到了不同的结果。

我创建了两个解码器,因为第一个我针对我的数据集进行训练,第二个我想最终提供一个新的 Z 编码以产生新的值。

我的检查是我应该能够将编码过程生成的 Z 值发送到两个解码器并获得相同的结果。

我有 2 个解码器(D,D_new)。 D_new 与 D 共享变量范围。

在训练之前,我可以将值发送到编码器 (E) 以生成输出值以及它生成的 Z 值 (Z_gen)。

如果我在训练之前使用 Z_gen 作为 D_new 的输入,那么它的输出与预期的 D 的输出相同。

然而,经过几次迭代训练,D 的输出与 D_new 相比开始发散(尽管它们非常相似)。

我已将其与我的代码的更简单版本配对,该版本仍会重现错误。我想知道其他人是否发现了这种情况,以及我可以在哪里纠正它。

以下代码可以在 jupyter notebook 中运行。我正在使用 Tensorflow r0.11 和 Python 3.5.0



    import numpy as np
    import tensorflow as tf
    import matplotlib
    import matplotlib.pyplot as plt
    import os
    import pylab as pl
    mgc = get_ipython().magic
    mgc(u'matplotlib inline')
    pl.rcParams['figure.figsize'] = (8.0, 5.0)



    ##-- Helper function Just for visualizing the data
    def plot_values(values, file=None):
        t = np.linspace(1.0,len(values[0]),len(values[0]))
        for i in range(len(values)):
            plt.plot(t,values[i])
        if file is None:
            plt.show()
        else:
            plt.savefig(file)
        plt.close()



    def encoder(input, n_hidden, n_z):
        with tf.variable_scope("ENCODER"):
            with tf.name_scope("Hidden"):
                n_layer_inputs = input.get_shape()[1].value
                n_layer_outputs = n_hidden
                with tf.name_scope("Weights"):
                    w = tf.get_variable(name="E_Hidden", shape=[n_layer_inputs, n_layer_outputs], dtype=tf.float32)
                with tf.name_scope("Activation"):
                    a = tf.tanh(tf.matmul(input,w))
                prevLayer = a

            with tf.name_scope("Z"):
                n_layer_inputs = prevLayer.get_shape()[1].value
                n_layer_outputs = n_z
                with tf.name_scope("Weights"):
                    w = tf.get_variable(name="E_Z", shape=[n_layer_inputs, n_layer_outputs], dtype=tf.float32)
                with tf.name_scope("Activation"):
                    Z_gen = tf.matmul(prevLayer,w)
        return Z_gen

    def decoder(input, n_hidden, n_outputs, reuse=False):
        with tf.variable_scope("DECODER", reuse=reuse):
            with tf.name_scope("Hidden"):
                n_layer_inputs = input.get_shape()[1].value
                n_layer_outputs = n_hidden
                with tf.name_scope("Weights"):
                    w = tf.get_variable(name="D_Hidden", shape=[n_layer_inputs, n_layer_outputs], dtype=tf.float32)
                with tf.name_scope("Activation"):
                    a = tf.tanh(tf.matmul(input,w))
                prevLayer = a

            with tf.name_scope("OUTPUT"):
                n_layer_inputs = prevLayer.get_shape()[1].value
                n_layer_outputs = n_outputs
                with tf.name_scope("Weights"):
                    w = tf.get_variable(name="D_Output", shape=[n_layer_inputs, n_layer_outputs], dtype=tf.float32)
                with tf.name_scope("Activation"):
                    out = tf.sigmoid(tf.matmul(prevLayer,w))
        return out

这里是设置 TensorFlow 图表的地方:



    batch_size = 3
    n_inputs = 100
    n_hidden_nodes = 12
    n_z = 2

    with tf.variable_scope("INPUT_VARS"):
        with tf.name_scope("X"):
            X = tf.placeholder(tf.float32, shape=(None, n_inputs))
        with tf.name_scope("Z"):
            Z = tf.placeholder(tf.float32, shape=(None, n_z))

    Z_gen = encoder(X,n_hidden_nodes,n_z)

    D = decoder(Z_gen, n_hidden_nodes, n_inputs)
    D_new = decoder(Z, n_hidden_nodes, n_inputs, reuse=True)

    with tf.name_scope("COST"):
        loss = -tf.reduce_mean(X * tf.log(1e-6 + D) + (1-X) * tf.log(1e-6 + 1 - D))
        train_step = tf.train.AdamOptimizer(0.001, beta1=0.5).minimize(loss)

我正在生成一个包含 3 个具有 100 个数据点的正态分布噪声样本的训练集,然后对其进行排序以更容易地可视化:



    train_data = (np.random.normal(0,1,(batch_size,n_inputs)) + 3) / 6.0
    train_data.sort()
    plot_values(train_data)

启动会话:



    sess = tf.InteractiveSession()
    sess.run(tf.group(tf.initialize_all_variables(), tf.initialize_local_variables()))

让我们看看网络在训练之前最初生成的内容......



    resultA, Z_vals = sess.run([D, Z_gen], feed_dict={X:train_data})
    plot_values(resultA)

提取 Z 生成的值并将它们提供给 D_new,它正在重用来自 D 的变量:



    resultB = sess.run(D_new, feed_dict={Z:Z_vals})
    plot_values(resultB)

为了理智,我将绘制两者之间的差异以确保它们相同...

现在运行 1000 个训练 epoch 并绘制结果...



    for i in range(1000):
        _, resultA, Z_vals = sess.run([train_step, D, Z_gen], feed_dict={X:train_data})
    plot_values(resultA)

现在让我们将相同的 Z 值输入 D_new 并绘制这些结果...



    resultB = sess.run(D_new, feed_dict={Z:Z_vals})
    plot_values(resultB)

它们看起来很相似。但是(我认为)它们应该完全相同。来看看有什么区别...



    plot_values(resultA - resultB)

您现在可以看到有一些变化。对于更复杂数据的更大网络,这变得更加引人注目,但仍然出现在这个简单的示例中。 关于发生了什么的任何线索?

【问题讨论】:

  • 我不确定这是一个实际的答案,因为我仍然在我更复杂的示例中看到这些结果。但我发现,如果在训练循环之后再次对 Z_gen 值进行采样,则 D 和 D_new 的结果匹配。当我用更复杂的数据(一组正弦波训练)尝试这个时,我仍然看到一些变化。 run() 方法完成后,值似乎有一些非常小的变化。

标签: python python-3.x tensorflow


【解决方案1】:

有一些方法(不知道具体是哪一种)可以提供种子值。除此之外,我什至不确定训练过程是否完全确定,尤其是在GPU is involved 时,仅仅是由于并行化的性质。

this question

【讨论】:

    【解决方案2】:

    虽然我没有完整解释原因,但我能够通过更改来解决我的问题:

    for i in range(1000):
        _, resultA, Z_vals = sess.run([train_step, D, Z_gen], feed_dict={X:train_data})
    plot_values(resultA)
    
    resultB = sess.run(D_new, feed_dict={Z:Z_vals})
    plot_values(resultB)
    plot_values(resultA - resultB)
    

    到...

    for i in range(1000):
        _, resultA, Z_vals = sess.run([train_step, D, Z_gen], feed_dict={X:train_data})
    
    resultA, Z_vals = sess.run([D, Z_gen], feed_dict={X:train_data})
    
    plot_values(resultA)
    
    resultB = sess.run(D_new, feed_dict={Z:Z_vals})
    plot_values(resultB)
    plot_values(resultA - resultB)
    

    请注意,我最后一次只是运行并提取了结果和 Z_vals,没有 train_step

    我在更复杂的设置中仍然看到问题的原因是我有偏差变量(即使它们被设置为 0.0)是用...生成的。

    b = tf.Variable(tf.constant(self.bias_k, shape=[n_layer_outputs], dtype=tf.float32))
    

    在将reusetf.variable_scope 一起使用时,不知何故没有考虑到这一点。所以从技术上讲,有些变量没有被重用。为什么设置为 0.0 时会出现这样的问题,我不确定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 2017-11-30
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      相关资源
      最近更新 更多