问题陈述
我在Linux RedHat 7.3上使用TensorFlow v1.0.1尝试训练一个动态RNN(在Windows 7上也有相同的问题),无论我尝试什么方法,每个epoch的训练和验证错误都完全相同,即我的权重没有更新。
我非常感谢您能提供的任何帮助。
示例
我尝试将这个问题简化为一个最小的示例来展示我的问题,但即使是最小的示例仍然相当大。我主要基于这个gist来构建网络结构。
网络定义
import functoolsimport numpy as npimport tensorflow as tfdef lazy_property(function): attribute = '_' + function.__name__ @property @functools.wraps(function) def wrapper(self): if not hasattr(self, attribute): setattr(self, attribute, function(self)) return getattr(self, attribute) return wrapperclass MyNetwork: """ 定义用于标记时间序列的RNN的类。 """ def __init__(self, data, target, num_hidden=64): self.data = data self.target = target self._num_hidden = num_hidden self._num_steps = int(self.target.get_shape()[1]) self._num_classes = int(self.target.get_shape()[2]) self._weight_and_bias() # 创建权重和偏置张量 self.prediction self.error self.optimize @lazy_property def prediction(self): """定义循环神经网络的预测方案。""" # 动态LSTM。 network = tf.contrib.rnn.BasicLSTMCell(self._num_hidden) output, _ = tf.nn.dynamic_rnn(network, data, dtype=tf.float32) # 展平并对所有时间步应用相同的权重。 output = tf.reshape(output, [-1, self._num_hidden]) prediction = tf.nn.softmax(tf.matmul(output, self.weight) + self.bias) prediction = tf.reshape(prediction, [-1, self._num_steps, self._num_classes]) return prediction @lazy_property def cost(self): """定义网络的成本函数。""" cross_entropy = -tf.reduce_sum(self.target * tf.log(self.prediction), axis=[1, 2]) cross_entropy = tf.reduce_mean(cross_entropy) return cross_entropy @lazy_property def optimize(self): """定义优化方案。""" learning_rate = 0.003 optimizer = tf.train.RMSPropOptimizer(learning_rate) return optimizer.minimize(self.cost) @lazy_property def error(self): """定义预测误差的度量。""" mistakes = tf.not_equal(tf.argmax(self.target, 2), tf.argmax(self.prediction, 2)) return tf.reduce_mean(tf.cast(mistakes, tf.float32)) def _weight_and_bias(self): """返回输出层适当大小的权重和偏置张量。""" self.weight = tf.Variable(tf.truncated_normal( [self._num_hidden, self._num_classes], mean=0.0, stddev=0.01, dtype=tf.float32)) self.bias = tf.Variable(tf.constant(0.1, shape=[self._num_classes]))
训练
这是我的训练过程。all_data
类只是保存我的数据和标签,并使用批量生成器类在调用all_data.train.next()
和all_data.train_labels.next()
时输出用于训练的批次。您可以使用任何喜欢的批量生成方案进行重现,如果您认为这相关,我可以添加代码;我觉得这已经太长了。
tf.reset_default_graph()data = tf.placeholder(tf.float32, [None, all_data.num_steps, all_data.num_features])target = tf.placeholder(tf.float32, [None, all_data.num_steps, all_data.num_outputs])model = MyNetwork(data, target, NUM_HIDDEN)print('正在训练模型...')with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print('已初始化。') for epoch in range(3): print('Epoch {} |'.format(epoch), end='', flush=True) for step in range(all_data.train_size // BATCH_SIZE): # 生成下一个训练批次并训练。 d = all_data.train.next() t = all_data.train_labels.next() sess.run(model.optimize, feed_dict={data: d, target: t}) # 定期更新用户。 if step % summary_frequency == 0: print('.', end='', flush=True) # 在每个epoch结束时显示训练和验证错误。 print('|', flush=True) train_error = sess.run(model.error, feed_dict={data: d, target: t}) valid_error = sess.run(model.error, feed_dict={ data: all_data.valid, target: all_data.valid_labels }) print('训练错误: {}%'.format(100 * train_error)) print('验证错误: {}%'.format(100 * valid_error)) # 在一切完成后检查测试错误。 test_error = sess.run(model.error, feed_dict={ data: all_data.test, target: all_data.test_labels }) print('训练{}个epoch后的测试错误: {}%'.format(epoch + 1, 100 * test_error))
对于一个简单的示例,我生成了随机数据和标签,其中数据的形状为[num_samples, num_steps, num_features]
,每个样本都与整个事物相关联的单个标签:
data = np.random.rand(5000, 1000, 2)labels = np.random.randint(low=0, high=2, size=[5000])
然后我将我的标签转换为one-hot向量,并对它们进行平铺处理,使得生成的labels
张量与data
张量大小相同。
回答: