巨大的差异。训练与测试之间的准确性:过度拟合还是我遗漏的明显事实?

时间:2017-03-08 16:30:25

标签: tensorflow deep-learning

我正在使用Tensorflow将Convolution和Pooling技术应用于与图像无关的深度学习项目,并使用简单的数字数据集作为输入。我意识到它有点苹果和橘子,但我非常喜欢“滑动一个窗口”在一组观察中并从中提取一组特征的方法,即使观察结果不是像素,所以我想要尝试一下。

到目前为止,我的测试准确性非常令人失望,而且我现在已经放弃了,除了训练准确度和损失似乎表现得相当好并且以合理的方式响应超参数的各种调整。

我很清楚过度拟合的可能性,但是真的可能真的那么糟糕,我会在训练中达到90%的准确率并且在测试中保持25%的准确率吗?我的数据有4个类,因此25%的测试准确性基本上是随机的结果。我想知道我是否只是错过了一些完全明显的东西?

我正在尝试分析TensorBoard中的Graph,据我所知,我没有看到训练和测试精度的计算有任何问题。我唯一不理解的是为什么训练和测试输入队列在侧面列出并且似乎没有与任何东西连接,但我可以看到从运行代码并从代码内部记录TF读取适当的批量培训和测试数据。

我的网络非常简单 - 1个卷积层+ 1个完全连接的层+ 1个读出层。每个输入行有480列,其思路是保持这种方式,而不是形成AxB矩阵。然后我用给定的步幅“滑动”一条30x1的窗口。我从卷积层中提取出50个特征,从完全连接的层中提取出100个特征。我将原始数据集80/20拆分为sklearn.cross_validation.train_test_split

进行培训和测试

我是否有太多的自由度,网络只是过度拟合和记忆训练数据,对测试数据仍然无用?或者我没有正确评估测试准确度?

测试准确度计算如下:

    dateLbl_batch, feature_batch, label_batch = sess.run([dateLblTest, featuresTest, labelsTest])

    acc, summary = sess.run([accuracyTest, summary_test], feed_dict={X: feature_batch, Y_: label_batch})

    i += 1
    summary_writer.add_summary(summary, i)

其中accuracyTest的定义如下:

with tf.name_scope('AccuracyTest'):
    accuracyTest = tf.reduce_mean(tf.cast(tf.equal(
        tf.argmax(Y, 1),
        tf.argmax(Y_, 1)), tf.float32))

和Y_是从Test数据集加载的标签,Y是读出层的输出:

Y = tf.matmul(h_fc1, W_fc2, name='ReadOut_Layer') + b_fc2

以下是我的代码中相关的部分:

    TS = 480
    TL = 4

    def weight_variable(shape):
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)
    def bias_variable(shape):
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)
    def conv2d(x, W, sX, sY):
        return tf.nn.conv2d(x, W, strides=[1, sX, sY, 1], padding='SAME')
    def pool_fn(x, kX, kY, sX, sY):
        return tf.nn.max_pool(x, ksize=[1, kX, kY, 1], strides=[1, sX, sY, 1], padding='SAME')

    Y_ = tf.placeholder(tf.float32, [None, TL], name='pl_labels')
    X = tf.placeholder(tf.float32, [None, TS], name='pl_x')

    # Convolution Parameters
    frame_x = 480
    frame_y = 1
    wnd_x = 30
    wnd_y = 1
    features_l1 = 50
    features_lFC = 100
    conv_stride_x = 1
    conv_stride_y = 1
    pool_krn_x = 2
    pool_krn_y = 1
    pool_stride_x = 2
    pool_stride_y = 1
    fc_x = int(frame_x / pool_krn_x)
    fc_y = int(frame_y / pool_krn_y)

    # 1st Layer
    x_conv = tf.reshape(X, [-1,frame_x,frame_y,1])
    W_conv1 = weight_variable([wnd_x, wnd_y, 1, features_l1])
    b_conv1 = bias_variable([features_l1])
    h_conv1 = tf.nn.relu(conv2d(x_conv, W_conv1, conv_stride_x, conv_stride_y) + b_conv1)
    h_pool1 = pool_fn(h_conv1, pool_krn_x, pool_krn_y, pool_stride_x, pool_stride_y)

    # Fully Connected Layer
    W_fc1 = weight_variable([fc_x * fc_y * features_l1, features_lFC])
    b_fc1 = bias_variable([features_lFC])
    h_pool2_flat = tf.reshape(h_pool1, [-1, fc_x*fc_y*features_l1])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

    # Readout Layer
    W_fc2 = weight_variable([features_lFC, TL])
    b_fc2 = bias_variable([TL])
    Y = tf.matmul(h_fc1, W_fc2, name='ReadOut_Layer') + b_fc2

    dateLbl, features, labels = input_pipeline(fileNameTrain, batch_size, try_epochs)
    dateLblTest, featuresTest, labelsTest = input_pipeline(fileNameTest, batch_size, 1)

    with tf.name_scope('SoftMaxModel'):
        myModel = tf.nn.softmax_cross_entropy_with_logits(labels=Y_, logits=Y, name='SoftMaxModel')
    with tf.name_scope('LossFn'):
        lossFn = tf.reduce_mean(myModel, name = 'LossFn')
    with tf.name_scope('Optimizer'):
         train_step = tf.train.AdamOptimizer(1e-4, name='AdamConst').minimize(lossFn, name='MinimizeLossFn')
    with tf.name_scope('AccuracyTrain'):
        accuracyTrain = tf.reduce_mean(tf.cast(tf.equal(
            tf.argmax(Y, 1),
            tf.argmax(Y_, 1)), tf.float32))
    with tf.name_scope('AccuracyTest'):
        accuracyTest = tf.reduce_mean(tf.cast(tf.equal(
            tf.argmax(Y, 1),
            tf.argmax(Y_, 1)), tf.float32))

    a1 = tf.summary.histogram("Model", myModel)
    a2 = tf.summary.scalar("Loss", lossFn)
    a3 = tf.summary.scalar("AccuracyTrain", accuracyTrain)
    a4 = tf.summary.scalar("AccuracyTest", accuracyTest)

    summary_train = tf.summary.merge([a1, a2, a3])
    summary_test = tf.summary.merge([a4])

    with tf.Session() as sess:
        summary_writer = tf.summary.FileWriter(logs_path, sess.graph)

        gInit = tf.global_variables_initializer().run()
        lInit = tf.local_variables_initializer().run()

        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(coord=coord)

        ############################ TRAINING ############################
        try:
            i = 0
            acCumTrain = 0

            while not coord.should_stop():
                dateLbl_batch, feature_batch, label_batch = sess.run([dateLbl, features, labels])

                _, acc, summary = sess.run([train_step, accuracyTrain, summary_train], feed_dict={X: feature_batch, Y_: label_batch})

                i += 1
                summary_writer.add_summary(summary, i)
                acCumTrain += acc

        except tf.errors.OutOfRangeError:
            acCumTrain /= i
            print('-------------- Finished Training ---------------')

        finally:
            coord.request_stop()

        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(coord=coord)

        ############################ TESTING ############################
        try:

            i = 0
            acCumTest = 0

            while not coord.should_stop():

                dateLbl_batch, feature_batch, label_batch = sess.run([dateLblTest, featuresTest, labelsTest])

                acc, summary = sess.run([accuracyTest, summary_test], feed_dict={X: feature_batch, Y_: label_batch})

                i += 1
                summary_writer.add_summary(summary, i)
                acCumTest += acc

        except tf.errors.OutOfRangeError:
            acCumTest /= i
            print('-------------- Finished Testing  ---------------')
        finally:
            coord.request_stop()

        print('Training Accuracy: {:.2f} Testing Accuracy: {:.2f}'.format(acCumTrain, acCumTest))
        coord.join(threads)

以下是来自TensorBoard的培训和测试准确性的屏幕截图 - 在培训中看起来很有前途,但在测试中只是随机噪音!

Training/Testing Accuracy and Loss

以下是整体图表: Full Graph

以下是图表的缩放,显示了如何计算训练和测试准确度: Graph Fragment

2 个答案:

答案 0 :(得分:0)

看起来对我来说太过分了。尝试添加辍学和体重衰减,看看有什么变化。甚至可以通过添加更多层来增加容量,同时应用正则化。如果这没有帮助,你应该看看数据。也许你的训练/测试组太不一样了。然后扩充可能会有所帮助。

答案 1 :(得分:0)

你在评论中给出的数字让我觉得它肯定过度拟合了。例如,MNIST的功能是您的两倍,但训练样例的数量是其中的35倍。

我认为了解你拥有多少重量(参数)也很有用 - 当我开始使用CNN时,这让我感到惊讶。你的第一个转换层有30 * 50个特征= 1500,这不是那么糟糕。但是,对于完全连接的层,您有50 * 480/2 = 12000 INPUTS,这将转换为FC中的48000个功能。对于你的问题,这是一个非常大的矩阵。

通过添加一个或多个转换层以及池图层,您实际上可以使参数空间更小。

使参数空间更小的其他方法:将conv-filter的大小从50减小到10,或使用降维技术(如PCA)。

最后,不要忘记实际上有一个更适合您使用的Conv1d功能。