我在训练卷积神经网络(CNN)时,注意到在MNIST数据集上经过X次迭代后,训练和验证的准确率出现了显著下降:
这个X似乎取决于学习率。修改 dropout 似乎对这种现象没有任何影响。我尝试了降低报告频率(每100批次报告一次),并注意到准确率下降得非常快。准确率在下降后没有恢复。
training_accuracy / validation_accuracy => 1.0000 / 1.0000 for step 10000training_accuracy / validation_accuracy => 0.9833 / 1.0000 for step 20000training_accuracy / validation_accuracy => 1.0000 / 1.0000 for step 30000training_accuracy / validation_accuracy => 1.0000 / 1.0000 for step 40000training_accuracy / validation_accuracy => 1.0000 / 1.0000 for step 50000training_accuracy / validation_accuracy => 0.1000 / 0.1000 for step 60000training_accuracy / validation_accuracy => 0.1000 / 0.1000 for step 69999
我的CNN是一个典型的CNN,从零开始训练。代码可在这里找到。数据集是标准的MNIST数据集,有两个特点:
- 我在图像中加入了非常低值的随机噪声
- 我随机地将图像向左和向右移动几个像素
这不是过拟合,因为训练准确率也下降了。
我注意到在准确率下降后,所有预测结果都是0
。因此准确率是1/10 = 0.1
(因为CNN总是预测0)
你知道这是什么现象吗?我很感激你的想法和反馈。
更新1:我注意到所有的tf权重和偏置都被填充为nan:
2017-06-10 13:06:34.814975: I tensorflow/core/kernels/logging_ops.cc:79] This is W_fc1: [[nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan]...]2017-06-10 13:06:34.830064: I tensorflow/core/kernels/logging_ops.cc:79] This is b_fc1: [nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan nan...]2017-06-10 13:06:34.840501: I tensorflow/core/kernels/logging_ops.cc:79] This is W_fc2: [[nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan][nan nan nan nan nan nan nan nan nan nan]...]2017-06-10 13:06:34.851325: I tensorflow/core/kernels/logging_ops.cc:79] This is b_fc2: [nan nan nan nan nan nan nan nan nan nan]
回答:
如果你使用交叉熵损失函数,那么一旦你的网络输出预测值为0.0,你的损失中就会包含log(0),这会导致nan。在Python中,任何对nan进行的操作也会是nan,所以这个nan会迅速通过整个网络反向传播。在将output
传递给损失函数之前,使用output = tf.clip_by_value(output, 10e-8, 1.-10e-8)
。你使用tf.log(y + small_constant)
的解决方案也同样有效。