Python TensorFlow LSTM:为什么测试精度变低,而不是训练精度?

Python TensorFlow LSTM:为什么测试精度变低,而不是训练精度?,python,tensorflow,deep-learning,lstm,Python,Tensorflow,Deep Learning,Lstm,我尝试用TensorFlow建立LSTM模型。LSTM的训练似乎很好,获得了90%以上的准确率。困扰我的一个问题是“测试精度”非常低。所以,我认为这是因为过度装修?但增加训练批次或减少元素大小(从10到5)等尝试都是浪费我的努力,应用“辍学”也没有解决这一问题。我想要一些关于如何改进代码以获得高测试精度的指导。 以下是我的数据/参数摘要 Input variable is economic time series data standardized Output variable is cate

我尝试用TensorFlow建立LSTM模型。LSTM的训练似乎很好,获得了90%以上的准确率。困扰我的一个问题是“测试精度”非常低。所以,我认为这是因为过度装修?但增加训练批次或减少元素大小(从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模型,所以,这是第一次,因此我知道我做错了什么,但我不能指责它

那么,有人能提供帮助吗


    

如果训练准确度继续上升,但测试准确度下降,则说明您拟合过度。试着少跑几次或者使用较低的学习率。

在我进入更多细节之前:
我假设您在谈论
元素大小
时指的是
批量大小
?如果我的假设是错误的,请在这里纠正我

正如另一个答案所提到的,一个潜在的原因可能是过度拟合,即你试图“太过努力地使用你的训练数据”。解决这一问题的一种通用方法是使用保留的验证样本跟踪看不见的训练数据的性能。也就是说,您没有拆分两种方式(训练/测试),而是拥有第三个验证集(通常大小与测试数据大致相同),并在训练期间不时检查模型对该验证数据的执行情况

一个常见的观察结果是以下曲线: 正如您所看到的,该模型在训练数据上不断改进,但它确实这样做了,因为它牺牲了泛化到看不见数据的能力

通常,您会尝试在验证集上的错误最小的点停止训练-即使这不能保证训练数据的最佳结果。 我们期望它在(完全未知的)之前的测试集上表现最好

作为一个简短的补充说明,如果您在TensorFlow中这样做(我不是100%熟悉):通常,您必须“切换”您的模型,从培训到评估,以获得验证集上的实际结果(并且不要意外地在验证集上进行培训),但是您可以在网上找到大量实际的实现

此外,如果你有太多的神经元,过度拟合可能是一个问题!在你的例子中,你只有800个例子,但已经有80个神经元,这是一个太高的比例。你可以尝试使用较少的神经元,看看这是否会提高测试集的准确性,即使这可能会降低训练数据的准确性
最后,您希望有一个问题的紧凑描述,而不是一个“学习”识别每个训练实例的网络

此外,如果您确实使用小批量,您可以尝试进一步减少数量。我真的很喜欢,所以我也会在这里发布;-)
撇开玩笑不谈,小批量训练也能带来更好的泛化,尽管听起来很荒谬。大批量通常只有在您拥有大量训练集或在GPU上训练时才真正有用(因为从GPU到内存的复制非常昂贵,而小批量可以减少此类操作的数量),或者您需要很长时间才能达到收敛

由于您使用的是LSTM体系结构(由于其顺序性,在CPU和GPU上具有类似的性能,因为没有太多可并行化),因此大批量可能不会提高(计算)性能,但小批量可能会提高精度性能

最后,这就是我最初评论另一个答案的原因,我们可能完全偏离了这个解释,这可能是一个完全不同的原因

许多人往往忘记的是对测试/训练的划分做一些初步的探索性分析。如果在测试集中只有一个班级的代表,但在训练数据中几乎没有代表,那么结果可能不太好。同样,如果你只在30节课中的29节课上训练,网络将很难识别出30节课的任何样本

为了避免这种情况,请确保您有一个稍微均匀的划分(即在测试集和培训集中为每个类抽取一定数量的类),并检查这些类是否稍微均匀分布


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

我似乎根据信息丰富的Denninger的答案找到了答案。首先,我将训练数据分为六组(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%左右。我认为这是由于相同的CLA