我正在尝试在Linux RedHat 7.3上的TensorFlow v1.0.1中训练动态RNN(问题也出现在Windows 7上),无论我尝试什么,我都会在每个时代获得完全相同的训练和验证错误,即我的体重没有更新。
感谢您提供的任何帮助。
我试图将此减少到显示我的问题的最小示例,但最小的例子仍然非常大。我的网络结构主要基于this gist。
import functools
import numpy as np
import tensorflow as tf
def 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 wrapper
class MyNetwork:
"""
Class defining an RNN for labeling a time series.
"""
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() # create weight and bias tensors
self.prediction
self.error
self.optimize
@lazy_property
def prediction(self):
"""Defines the recurrent neural network prediction scheme."""
# Dynamic LSTM.
network = tf.contrib.rnn.BasicLSTMCell(self._num_hidden)
output, _ = tf.nn.dynamic_rnn(network, data, dtype=tf.float32)
# Flatten and apply same weights to all time steps.
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):
"""Defines the cost function for the network."""
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):
"""Defines the optimization scheme."""
learning_rate = 0.003
optimizer = tf.train.RMSPropOptimizer(learning_rate)
return optimizer.minimize(self.cost)
@lazy_property
def error(self):
"""Defines a measure of prediction error."""
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):
"""Returns appropriately sized weight and bias tensors for the output layer."""
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('Training the model...')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print('Initialized.')
for epoch in range(3):
print('Epoch {} |'.format(epoch), end='', flush=True)
for step in range(all_data.train_size // BATCH_SIZE):
# Generate the next training batch and train.
d = all_data.train.next()
t = all_data.train_labels.next()
sess.run(model.optimize,
feed_dict={data: d, target: t})
# Update the user periodically.
if step % summary_frequency == 0:
print('.', end='', flush=True)
# Show training and validation error at the end of each 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('Training error: {}%'.format(100 * train_error))
print('Validation error: {}%'.format(100 * valid_error))
# Check testing error after everything.
test_error = sess.run(model.error,
feed_dict={
data: all_data.test,
target: all_data.test_labels
})
print('Testing error after {} epochs: {}%'.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])
然后我将我的标签转换为单热矢量并平铺它们,以便生成的labels
张量与data
张量相同。
无论我做什么,我都会得到这样的结果:
Training the model...
Initialized.
Epoch 0 |.......................................................|
Training error: 56.25%
Validation error: 53.39999794960022%
Epoch 1 |.......................................................|
Training error: 56.25%
Validation error: 53.39999794960022%
Epoch 2 |.......................................................|
Training error: 56.25%
Validation error: 53.39999794960022%
Testing error after 3 epochs: 49.000000953674316%
我在每个时代都有完全相同的错误。即使我的体重随机走动,这应该改变。对于此处显示的示例,我使用随机数据随机标签,所以我不期望有太大的改进,但我确实期待一些变化,并且每个时期我都得到完全相同的结果。当我使用我的实际数据集执行此操作时,我会得到相同的行为。
我毫不犹豫地将其包含在以防被证明是红鲱鱼的情况下,但我相信我的优化器正在计算None
的成本函数梯度。当我尝试使用不同的优化器并尝试剪切渐变时,我继续使用tf.Print
来输出渐变。网络崩溃时出现tf.Print
无法处理无类型值的错误。
我尝试了以下方法,但问题仍然存在:
stddev
的不同值初始化我的权重。tf.zeros
)和不同的常量。prediction
方法中定义的权重和偏差,而不是类的成员变量,以及_weight_and_bias
中定义为@staticmethod
的{{1}}方法}}。prediction
函数中的logits而不是softmax预测,即predictions = tf.matmul(output, self.weights) + self.bias
,然后使用tf.nn.softmax_cross_entropy_with_logits
。这需要进行一些重塑,因为该方法需要使用形状[batch_size, num_classes]
给出标签和目标,因此cost
方法变为:(添加了一行以获取格式代码......)
@lazy_property
def cost(self):
"""Defines the cost function for the network."""
targs = tf.reshape(self.target, [-1, self._num_classes])
logits = tf.reshape(self.predictions, [-1, self._num_classes])
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=targs, logits=logits)
cross_entropy = tf.reduce_mean(cross_entropy)
return cross_entropy
None
的尺寸标注,这需要在网络定义中进行一些重写。基本上设置size = [all_data.batch_size, -1, all_data.num_features]
和size = [all_data.batch_size, -1, all_data.num_classes]
。tf.contrib.rnn.DropoutWrapper
并在培训中将dropout
值设置为0.5,在验证和测试中将其设置为1.0。答案 0 :(得分:1)
当我使用
时,问题就消失了output = tf.contrib.layers.flatten(output)
logits = tf.contrib.layers.fully_connected(output, some_size, activation_fn=None)
而不是展平我的网络输出,定义权重,以及手动执行tf.matmul(output, weight) + bias
。然后我使用
logits
(而不是问题中的predictions
)
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=target,
logits=logits)
如果您想获得网络预测,您仍需要执行prediction = tf.nn.softmax(logits)
。
我不知道为什么这会有所帮助,但在我做出这些改动之前,网络甚至不会对随机编造的数据进行训练。