【问题标题】:Why does recognition rate drop after multiple online training epochs?为什么在多个在线训练 epoch 后识别率会下降?
【发布时间】:2017-08-01 21:14:54
【问题描述】:

我正在使用 tensorflow 对 MNIST 数据集进行图像识别。在每个训练 epoch 中,我随机选取 10,000 张图像,以 1 的批大小进行在线训练。前几个 epoch 的识别率提高了,但是在几个 epoch 之后,识别率开始大幅下降。 (在前 20 个 epoch 中,识别率上升到 ~94%。之后,识别率从 90->50->40->30->20 上升)。这是什么原因?

此外,批量大小为 1 时,性能比批量大小为 100 时更差(最大识别率 94% 对 96%)。我查看了几个参考资料,但对于小批量还是大批量是否能获得更好的性能似乎存在矛盾的结果。在这种情况下会是什么情况?

编辑:我还加了一张训练数据集和测试数据集的识别率图。Recognition rate vs. epoch

我附上了下面的代码副本。感谢您的帮助!

import tensorflow as tf
import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot = True)

#parameters
n_nodes_hl1 = 500
n_nodes_hl2 = 500
n_nodes_hl3 = 500
n_classes = 10
batch_size = 1
x = tf.placeholder('float', [None, 784])
y = tf.placeholder('float')

#model of neural network
def neural_network_model(data):
    hidden_1_layer = {'weights':tf.Variable(tf.random_normal([784, n_nodes_hl1])               , name='l1_w'),
                      'biases': tf.Variable(tf.random_normal([n_nodes_hl1])                    , name='l1_b')}

    hidden_2_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])       , name='l2_w'),
                      'biases' :tf.Variable(tf.random_normal([n_nodes_hl2])                    , name='l2_b')}

    hidden_3_layer = {'weights':tf.Variable(tf.random_normal([n_nodes_hl2, n_nodes_hl3])       , name='l3_w'),
                      'biases' :tf.Variable(tf.random_normal([n_nodes_hl3])                    , name='l3_b')}

    output_layer   = {'weights':tf.Variable(tf.random_normal([n_nodes_hl3, n_classes])     , name='lo_w'),
                      'biases' :tf.Variable(tf.random_normal([n_classes])                   , name='lo_b')}

    l1 = tf.add(tf.matmul(data,hidden_1_layer['weights']), hidden_1_layer['biases'])
    l1 = tf.nn.relu(l1) 
    l2 = tf.add(tf.matmul(l1,hidden_2_layer['weights']), hidden_2_layer['biases'])
    l2 = tf.nn.relu(l2)     
    l3 = tf.add(tf.matmul(l2,hidden_3_layer['weights']), hidden_3_layer['biases'])
    l3 = tf.nn.relu(l3)
    output = tf.matmul(l3,output_layer['weights']) + output_layer['biases']    
return output

#train neural network
def train_neural_network(x):
    prediction = neural_network_model(x)
    cost = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(logits=prediction, labels=y))
    optimizer = tf.train.AdamOptimizer().minimize(cost)
    hm_epoches = 100
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for epoch in range(hm_epoches):
            epoch_loss=0
            for batch in range (10000):
                epoch_x, epoch_y=mnist.train.next_batch(batch_size)                
                _,c =sess.run([optimizer, cost], feed_dict = {x:epoch_x, y:epoch_y})
                epoch_loss += c
            correct = tf.equal(tf.argmax(prediction, 1), tf.argmax(y,1))
            accuracy = tf.reduce_mean(tf.cast(correct, 'float'))
            print(epoch_loss)
            print('Accuracy_test:', accuracy.eval({x:mnist.test.images, y:mnist.test.labels}))
            print('Accuracy_train:', accuracy.eval({x:mnist.train.images, y:mnist.train.labels}))

train_neural_network(x)

【问题讨论】:

  • 训练误差线和测试误差线如此紧密地相互跟踪,这很奇怪;你确定这些集合不重叠吗?
  • @Ray 是的,根据tensorflow函数(mnist.train.next_batch),只挑选训练集中的数据。我认为这种现象的主要原因(训练数据集识别率紧跟测试数据集)是对于每个时期,我不使用整个训练数据集进行训练,而是使用训练集的一个子集(10k 个随机数据点) .使用相同的数据集进行训练和测试会产生什么结果?会不会导致这种认可度下降?
  • 不,不会导致识别率下降;它只会使结果变得毫无用处,因为如果您不需要泛化到看不见的数据,那么在训练集上获得 100% 的识别是微不足道的(对于某些微不足道的值)。

标签: python machine-learning tensorflow mnist


【解决方案1】:

降低准确性

你过拟合了。这是当模型以牺牲重要特征为代价来学习特定于训练数据中图像伪影的错误特征时。任何应用程序的主要实验结果之一是确定最佳训练迭代次数。

例如,您的训练数据中可能有 80% 的 7碰巧在靠近词干底部的右侧有一点额外的倾斜,而 4 和 1 则没有。在太多训练之后,您的模型“决定”区分 7 和另一个数字的最佳方法是从那个额外的倾斜,尽管有任何其他功能。因此,一些 1 和 4 现在被归类为 7。

批量大小

同样,最佳批量大小是实验结果之一。通常,批量大小为 1 太小:这会使前几个输入图像对内核或感知器训练中的早期权重影响太大。这是过拟合的一个小例子:一个项目对模型有不当影响。但是,它足以将您的最佳结果改变 2%。

您需要平衡批量大小与其他超参数以找到模型的“最佳位置”,即最佳性能和最短训练时间。根据我的经验,最好增加批量大小,直到我每张图像的时间降级。我使用最多的模型(MNIST、CIFAR-10、AlexNet、GoogleNet、ResNet、VGG 等)一旦达到相当小的批量大小,精度损失就很小;从那里开始,训练速度通常是选择最佳使用可用 RAM 的批量大小的问题。

【讨论】:

  • 感谢您的回复。我原本以为这可能是过拟合的结果,但是当发生过拟合时,训练数据集的识别率一般应该很高。在我的实验中,训练数据集的识别率也下降到了~20%。我在问题中没有说清楚。有没有可能的原因?
  • 同意。当过拟合是罪魁祸首时,训练集率应该不断攀升。在任何情况下,对数据集进行洗牌都很重要;改变激活函数是个好主意。如果您有能力,还可以考虑插入一个 drop-out 层。
  • @Ray,您可以考虑删除这些 cmets 并写一个完整的答案。他们值得拥有更好的知名度。
  • @Prune 可能是个好主意。最初我只是提到验证集作为您答案的附录,但我的 cmets 似乎已经超越了这一点。
  • @Prune 我认为 tensorflow 确实对数据集进行了洗牌,所以我将更改激活函数并尝试 dropout 层。我编辑了问题以附上训练数据集和测试数据集的识别率图表。感谢您的建议!
【解决方案2】:

有几种可能性,但您需要进行一些实验才能确定是哪一种。

过拟合

Prune 很好地解释了这一点。我要补充一点,避免过度拟合的最简单方法是只删除 10-15% 的训练集,并在每几个 epoch 后评估这个验证集的识别率。如果你在训练集和验证集上绘制识别率的变化,你最终会在图上达到一个点,即训练误差持续下降但验证误差开始上升。此时停止训练;这就是过度拟合真正开始的地方。请注意,训练/验证/测试集之间没有重叠是很重要的。

在您提到训练误差并没有减少之前,这种情况更有可能发生,但有可能它过度拟合了训练集的相当均匀的部分,而牺牲了异常值或类似情况。尝试在每个 epoch 之后随机化训练集的顺序;如果它以牺牲其他部分为代价来适应集合的一部分,这可能会有所帮助。

附录:20 纪元左右质量的瞬间大幅下降使得这种可能性更小;这不是过度拟合的样子。

数值不稳定

如果您在具有大梯度的激活函数上的某个点上得到一个特别不正确的输入,那么最终可能会导致一个巨大的权重更新,从而搞砸到目前为止所学的所有内容。出于这个原因,通常对梯度幅度进行硬性限制。但是您使用的是 AdamOptimizer,它有一个用于避免不稳定的 epsilon 参数。我没有阅读它引用的论文,所以我不知道它是如何工作的,但它的存在使得不稳定的可能性降低。

饱和神经元

一些激活函数的区域具有非常小的梯度,所以如果你最终得到的权重使得函数几乎总是在那个区域中,你的梯度很小,因此无法有效地学习。 Sigmoid 和 Tanh 特别容易出现这种情况,因为它们在函数的两侧都有平坦的区域。 ReLU 在高端没有平坦区域,但在低端有。尝试用 Softplus 替换你的激活函数;这些类似于 ReLU,但具有连续的非零梯度。

【讨论】:

    猜你喜欢
    • 2018-04-18
    • 2021-05-04
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2023-01-10
    • 2012-10-09
    • 2018-04-02
    • 1970-01-01
    相关资源
    最近更新 更多