【发布时间】: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