项目场景:
最近在做一个用简单的lstm预测时序数据分类的模型,在训练过程中,出现了loss在持续减小,而acc和val_acc始终不变的情况,经过不断的调参,找到了其中的问题,在此记录下:
问题描述:
具体情况如下:
Epoch 00002: val_acc did not improve from 0.44288
Epoch 3/60
94790/94790 [==============================] - 26s 272us/step - loss: 1.0569 - acc: 0.4529 - val_loss: 1.0849 - val_acc: 0.4429
Epoch 00003: val_acc did not improve from 0.44288
Epoch 4/60
94790/94790 [==============================] - 26s 273us/step - loss: 1.0550 - acc: 0.4520 - val_loss: 1.0843 - val_acc: 0.4429
Epoch 00004: val_acc did not improve from 0.44288
Epoch 5/60
94790/94790 [==============================] - 26s 273us/step - loss: 1.0530 - acc: 0.4514 - val_loss: 1.0838 - val_acc: 0.4429
Epoch 00005: val_acc did not improve from 0.44288
Epoch 6/60
94790/94790 [==============================] - 26s 272us/step - loss: 1.0520 - acc: 0.4530 - val_loss: 1.0840 - val_acc: 0.4429
Epoch 00006: val_acc did not improve from 0.44288
Epoch 7/60
94790/94790 [==============================] - 26s 275us/step - loss: 1.0520 - acc: 0.4533 - val_loss: 1.0834 - val_acc: 0.4429
loss和acc实在是恢复不出当时的效果了,大家请以val_loss和val_acc的变化为参考(打脸嫌疑...)
原因分析:
遇到loss减小,而acc不变的情况,基本上就是因为梯度减小方向是局部极小值造成的。 例如:对于一个2分类问题来讲。真实值是(0,1),而预测值1是(0.7, 0)、预测值2是(0.5,0),显然预测值2要比预测值1的loss小,因为预测值2与真实值更接近。可是对于acc的计算来讲,这两个预测值都是错的(两个预测值的最终分类相同),因此他们的准确率都是0。 所以我们的目标不是希望在错误的维度上越来越小,而是应该在正确的维度上越来越大。比如预测值(0.5, 0)和(0, 0.5),同样的loss,但是acc却不一样。
解决方案:
1.调整学习率,这种情况下一般都是学习率太小造成的,可以适当的增加学习率。一个好的学习率,在前几个epoch时是可以看到loss和acc明显的改善的。
2.选择适当的激活函数。在我的实验中,对于Keras中的Dense层activation,当我把relu改成sigmoid后,有了一些好转。
3.选择适当的优化函数,并做好调参工作。在优化函数中,除了学习率还有很多其他参数可调,并且不是默认参数就是最好的,所以建议多尝试不同的参数值。
4.这里是个小建议:如果再遇到这类问题,就把预测值全部打印出来,就可以更直观的看出问题出在哪里了。