本文首先会介绍loss曲线表现形式,过拟合,欠拟合等等。然后展示如何使用matplotlib绘制loss曲线。

一、Loss曲线

通常数据集会被划分成三部分,训练集(training dataset)、验证集(validation dataset)、测试集(test dataset)。我们在训练模型时也经常会根据训练集的loss和验证集loss来诊断模型,从而期望能够优化参数训练处一个更好的模型,这个更好指的是能在测试集上表现更好的模型,也就是泛化能力(generalization)强的模型。那怎么根据loss曲线去诊断模型呢?

首先根据模型的表现我们把它分成三类:

  1. Underfit(欠拟合)
  2. Overfit(过拟合)
  3. Good fit (完美拟合)

那我们目标肯定是得到一个good-fit模型,但是在训练过程中会出现Underfit和Overfit。那么我们需要做的就是首先根据loss曲线判断模型现在处于那种拟合情况,然后再对症下药,寻找应对之策。那我们先看看每种拟合的loss曲线是怎样的。

1.1 Underfit

Underfit指的是模型不能很好的学习训练集。

如下图所示,这就是一个Underfit的例子,仅根据training loss就可以判断。这个training loss下降的非常平缓以致于好像都没有下降,这说明模型根本没有从训练集学到什么东西嘛。

Example of Training Learning Curve Showing An Underfit Model That Does Not Have Sufficient Capacity

下图也是Underfit情况,这种情况的特点是在训练结束时候training loss还在继续下降,这说明还有学习空间,模型还没来得及学就结束了。

“可以开始训练了吗?”
“对不起,已经结束了”
“......”

Example of Training Learning Curve Showing an Underfit Model That Does Not Have Sufficient Capacity

1.2 Overfit

Overfit指的是模型把训练集学的有点过了,以致于把一些噪音(noise)和随机波动(random fluctuations)也学进来了。就好像抄别人卷子时候把别人的错别字也照抄一样。这也是我们在训练中最经常出现的问题,overfit有时候是因为训练太久造成的。那Overfit的loss曲线长什么样呢?

如下图所示,overffit时候training loss一直在不断地下降,而validation loss在某个点开始不再下降反而开始上升了,这就说明overfit,我们应该在这个拐点处停止训练。

Example of Train and Validation Learning Curves Showing an Overfit Model

1.3 Good fit

Good git是我们的目标,它在loss曲线上的特点是training loss和validation loss都已经收敛并且之间相差很小很小。如下图所示,模型在20轮过后,两个loss曲线都开始收敛,而且两者之间并没有肉眼的差距。 通常traing loss会更小,这样他们之间就会有个gap,这个gap叫做generalization gap。

Example of Train and Validation Learning Curves Showing a Good Fit

 

二、绘制Loss曲线

完整代码

这里展示如何使用matplotlib这个模块为一个CNN模型绘制loss曲线,首先引入模块,并使用egg作为后端

import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt

然后我们得有个模型,然后获取history这个对象,这个history存储了模型在训练中各种输出,其中就有loss 

# fit the model
history = model.fit(x_train, y_train, batch_size=batch_size,
          epochs=epochs, verbose=1, validation_data=(x_test, y_test))
scores = model.evaluate(x_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

 最后取出history中的loss,绘制成loss曲线

loss = history.history['loss']
val_loss = history.history['val_loss']
plt.plot(loss, label='loss')
plt.plot(val_loss, label='val_loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'valid'], loc='upper left')
plt.savefig('./loss.png')

三、不同Loss表现

完整代码

3.1 Underfit

我们使用随机梯度下降(SGD)优化器,学习率为0.01,训练10轮,代码如下

#underfit
epochs = 10
sgd = optimizers.sgd(lr=0.01)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])

然后我们就得到了一个Underfitting模型,如下图所示,在训练结束的时候training loss还在下降,这说明模型还未学习充分。

3.2 Overfit

然后我们使用sgd作为优化器时候,训练30轮

#overfit
epochs = 30
sgd = optimizers.sgd(lr=0.01)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])

结果出现了过拟合的情况,loss曲线如下图

Reference

https://machinelearningmastery.com/learning-curves-for-diagnosing-machine-learning-model-performance/

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐