TensorFlow LSTM:为什么测试精度会降低,但不能训练一个?

时间:2018-08-19 05:00:05

标签: python tensorflow deep-learning lstm

我尝试使用TensorFlow构建LSTM模型。 LSTM的训练似乎很好,获得了90%以上的准确性。困扰我的问题是“测试准确性”非常低。所以,我认为这是由于过度拟合吗?但是诸如增加培训数量或将element_size(从10减少到5)之类的尝试浪费了我的精力,而应用“辍学” 并没有解决它。我想要一些有关如何改进我的代码以获得高测试精度的指导。 以下是我的数据/参数的摘要

Input variable is economic time series data standardized
Output variable is categorical features (labels) converted by one-hot encoding

Sequence_length : 20
Element_size: 5
Hidden_layer : 80
Categories (labels): 30 
Training batch : 924
Test batch : 164
Learn rate is 0.0005 (Is it low?)

这是我构建的代码

#Split x_buch and y_batch
train_x,test_x=np.split(x_batch,[int(batch_size*0.85)])
train_y,test_y=np.split(y_batch,[int(batch_size*0.85)])
print('train_x shape: {0} and test_x shape: {1}'.format(train_x.shape,test_x.shape))
print('train_y shape: {0} and test_y shape: {1}'.format(train_y.shape,test_y.shape))

#Create placehold for inpt, labels
inputs=tf.placeholder(tf.float32,shape=[None,step_time,element_size],name='inputs')
y=tf.placeholder(tf.float32,shape=[None,label_num],name='y')

#Tensorflow  built-in functinon
with tf.variable_scope('lstm'):
    lstm_cell=tf.contrib.rnn.LSTMCell(hidden_layer,forget_bias=1.0)
    cell_drop=tf.contrib.rnn.DropoutWrapper(lstm_cell, output_keep_prob=0.7)
    outputs,states=tf.nn.dynamic_rnn(cell_drop,inputs,dtype=tf.float32) 
    print('outputs shape: {0}'.format(outputs.shape))

W1={'linear_layer':tf.Variable(tf.truncated_normal([hidden_layer,label_num],mean=0,stddev=.01))}
b1={'linear_layer':tf.Variable(tf.truncated_normal([label_num],mean=0,stddev=.01))}

#Extract the last relevant output and use in a linear layer
final_output=tf.matmul(outputs[:,-1,:],W1['linear_layer'])+b1['linear_layer']

with tf.name_scope('cross_entropy'):
    softmax=tf.nn.softmax_cross_entropy_with_logits(logits=final_output,labels=y)
    cross_entropy=tf.reduce_mean(softmax)

with tf.name_scope('train'):
    train_step=tf.train.AdamOptimizer(learn_rate,0.9).minimize(cross_entropy)

with tf.name_scope('accracy'):
    correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(final_output,1))
    accuracy=(tf.reduce_mean(tf.cast(correct_prediction,tf.float32)))*100

#Training
with tf.Session()as sess:
    sess.run(tf.global_variables_initializer())    
    for step in range(5000):
        sess.run(train_step,feed_dict={inputs:train_x,y:train_y})
        if step % 500 == 0:
            acc=sess.run(accuracy,feed_dict={inputs:train_x,y:train_y})
            loss=sess.run(cross_entropy,feed_dict={inputs:train_x,y:train_y})
            print('Inter'+str(step)+',Minibatch loss= '+'{:.6f}'.format(loss)+', Traning Accracy='+'{:.5f}'.format(acc))

# Test
    test_acc=sess.run(accuracy,feed_dict={inputs:test_x,y:test_y})
    print("Test Accuracy is {0}".format(test_acc))

其结果是

Input Shape: (21760, 5)
Output Shape: (21760, 30)
x_batch shape: (1088, 20, 5)
y_batch shape: (1088, 30)
train_x shape: (924, 20, 5) and test_x shape: (164, 20, 5)
train_y shape: (924, 30) and test_y shape: (164, 30)
outputs shape: (?, 20, 80)
Inter0,Minibatch loss= 3.398923, Traning Accracy=5.30303
Inter500,Minibatch loss= 2.027734, Traning Accracy=38.09524
Inter1000,Minibatch loss= 1.340760, Traning Accracy=61.79654
Inter1500,Minibatch loss= 1.010518, Traning Accracy=72.83550
Inter2000,Minibatch loss= 0.743997, Traning Accracy=79.76190
Inter2500,Minibatch loss= 0.687736, Traning Accracy=79.76190
Inter3000,Minibatch loss= 0.475408, Traning Accracy=85.17316
Inter3500,Minibatch loss= 0.430477, Traning Accracy=87.22944
Inter4000,Minibatch loss= 0.359262, Traning Accracy=89.17749
Inter4500,Minibatch loss= 0.274463, Traning Accracy=90.69264
Test Accuracy is 4.878048419952393

我从未使用过TensorFlow和LSTM模型,因此,这是第一次,因此我知道我做错了事,但不能指责

那么,有人可以提供帮助吗?

3 个答案:

答案 0 :(得分:1)

我似乎根据Dennlinger的答案得出了答案。很快,我将训练数据分为六组(x_1,x_2 ... x_6和y_1,y_2,... y_6),每组数据的大小均相同。我不确定将它用作您提到的第三个验证集,但请尝试应用它。而且,我检查了每个集合不包含的类,例如,y_1不包含11、16、21、22和25号类。

train_y
[]
y_1
[11, 16, 21, 22, 25]
y_2
[11, 14, 16, 23]
y_3
[11, 19, 21, 23]
y_4
[14, 21, 23]
y_5
[16, 21, 22, 23]
y_6
[11, 21, 22, 23]
test_y
[11, 21, 22, 23]

首先检查(验证)是对x_1 / y_1集进行训练并计算测试数据的准确性。尽管我在每一步都停止了训练,但性能并未得到改善,但结果几乎相同。

Stop at step 1000
Inter500,Minibatch loss= 1.976426, Traning Accracy=46.01227
Test Accuracy is 7.317072868347168
Stop at step1500
Inter1000,Minibatch loss= 1.098709, Traning Accracy=66.25767
Test Accuracy is 4.2682929039001465
Stop at step 2000
Inter1500,Minibatch loss= 0.906059, Traning Accracy=74.23312
Test Accuracy is 6.097560882568359
Stop at step 2500
Inter2000,Minibatch loss= 0.946361, Traning Accracy=76.07362
Test Accuracy is 6.707317352294922

接下来,我尝试检查几种组合的效果,结果如下

Train on x_6/y_6 sets and test on test data
Inter2500,Minibatch loss= 0.752621, Traning Accracy=79.77941
Test Accuracy is 78.65853881835938

Train on x_6/y_6 sets and test on x_5/y_5 sets
Inter2500,Minibatch loss= 0.772954, Traning Accracy=78.67647
Test Accuracy is 3.658536434173584

Train on training data and test on x_4/y_4 sets
Inter3000,Minibatch loss= 1.980538, Traning Accracy=41.01731
Test Accuracy is 37.42331314086914
有趣的是,在x_6 / y_6集上训练并在测试数据上进行测试的组合可能比以前的组合表现更好,后者的测试精度提高到了约78%。我假设这是由于类相同,这意味着y_6包含测试数据的所有类(请参见上文)以及大小相同。因此,本次展示必须考虑哪些数据集合适,并尝试在各种条件下验证LSTM模型,这一点非常重要。

另一方面,CHG减少了神经元(从80个减少到10个或5个)和批次,根本没有改善性能。

答案 1 :(得分:0)

如果训练精度继续提高,但测试精度下降,则说明您过拟合。尝试减少运行时间或降低学习速度。

答案 2 :(得分:0)

在我详细介绍之前:
我假设您在谈论batch_size时是指element_size吗?如果我的假设不对,请在这里更正。

正如提到的另一个答案,一个潜在的原因可能是过拟合的,即您正在尝试“对训练数据太过努力”。解决此问题的一种通用方法是使用保留的验证样本跟踪看不见的训练数据的性能。也就是说,您没有第三个验证(训练/测试),而是拥有第三个验证集(通常具有相同大小的测试数据),并在训练过程中时不时地检查模型对验证数据的表现。< / p>

常见的观察结果如下曲线: enter image description here 如您所见,该模型在训练数据上不断改进,但确实如此,因为它牺牲了泛化不可见数据的能力

通常,您尝试在验证集上的误差最小的位置上停止训练-即使这不能保证训练数据的最佳结果。 我们希望它能在(完全未知的)先前测试集上发挥最佳性能。

作为一个简短的说明,如果您在TensorFlow(我不是100%熟悉)中进行此操作:通常,您必须将模型从训练“转换”为评估,以在验证集上获得实际结果(并且也不会无意地对它们进行培训),但是您可以在网上找到许多实际的实现方式。

此外,如果神经元过多,过度拟合可能会成为问题!在您的情况下,您只有800个示例,但已经有80个神经元,这与IMO的比率过高有关。您可以尝试使用较少的神经元,看看这是否可以提高测试集的准确性,即使这也可能会降低训练数据的准确性。
最后,您想要的是问题的紧凑描述符,而不是一个“学习”以识别每个训练实例的网络。

此外,如果您实际使用小型批次,则可以尝试进一步减少数量。我真的很喜欢this one tweet from Yann LeCun,所以我也将它发布在这里;-)
除了开玩笑,以较小的批次进行培训也可以导致更好的泛化,尽管听起来很荒谬。通常,只有在拥有大量训练集或在GPU上进行训练时,大批量才真正有用(因为从GPU到内存的复制非常昂贵,而小批量会减少此类操作的次数),或者您需要很长时间才能达到收敛。

由于您使用的是LSTM架构(由于其顺序性,因此在CPU和GPU上具有类似的性能,因为没有太多要并行化的特性),因此大批量处理可能不会提高您的(计算)性能,但批量较小可以提高准确性。

最后,这就是为什么我最初对另一个答案发表评论的原因,我们在这里的解释可能会完全不对,毕竟这可能是完全不同的原因。

许多人容易忘记的是,对您的测试/训练对进行初步的探索性分析。如果您的测试集中只有一个班级的代表,而培训数据中几乎没有任何代表,那么结果可能会不好。同样,如果您只训练30个班级中的29个班级,则网络将很难识别第30个班级的任何样本。

为避免这种情况,请确保您进行了平均分配(即在测试和训练集中为每个班级抽样一定数量的班级),然后检查班级是否均匀分布

这样做可能会在以后为您节省很多痛苦,并且通常还有助于改善全新训练数据的性能。永远记住-深度学习并不能神奇地解决您在预测分析中遇到的所有问题,它只是为您提供了一个非常强大的工具来解决特定的子问题。