32. 绘制学习曲线

假设你有一个非常小的训练集(100个样例)。你可以使用随机挑选的10个样本组成的子集,然后是20个样本组成的子集,然后是30个……一直到100个样本的集合来训练算法——以10的间隔递增。然后用这10个数据点来绘制学习曲线,你可能就会发现,在小的训练集下,曲线看起来波动很大(意思是这些值比预期值要高/或者低)。

当只对10个随机选择的样本进行训练时,脸黑的时候你可能会随机出了一个垃圾训练集——有很多模糊/标记错误的样本。或许,你很幸运的得到了一个很好的训练集。一个很小的训练集意味着开发误差和训练误差会很容易出现随机的波动。

如果你的机器学习应用严重偏好于某一类(比如在猫咪分类任务中,反例的分数比正例的要大的多),或者如果训练任务中需要识别大量的类(例如识别100种不同的动物种类),那么选择出那种特别“不具代表性”或者是坏的训练集的机会也更大。例如,如果你的总样本中有80%都是负例样本(y=0),而只有20%是正例样本(y=1),那么很有可能随机抽样出来的那10个样本组成的子集里边只包含了负例样本,这样的话算法很难学习出一些有意义的东西来。

如果训练曲线中因为噪声的原因使得我们很难观察到真实的变化趋势,这里提供两个解决方案:

  • 放弃使用在10个样本的数据集上训练一个模型的方法,取而代之 [1] 的是从100个原始集合中随机抽样几个(3-10)由10个样本组成的数据子集作为训练集。然后在每个训练子集上训练出模型来,并计算出每个模型的训练误差和开发误差。最后计算并绘制它们的平均训练误差和平均开发误差。
  • 如果你的训练集偏向某一类,或者是如果有很多类别,请选择一个“均衡”一点的子集,而不是简单的从100个样本中随机抽取10个。举例子来说,如果你切确知道你的样本中那个20%是正例样本,80%是反例样本,合理的做法就是,你应该尽量保证每个类的样本所占的比例尽可能接近原始训练集的整体比例。

[1]:这里的采样和替换的意思是:你从100个样本中随机挑选10个样本组成第一个训练子集。然后为了组成第二套训练子集,重新挑选10个样本(依旧从100个样本中挑)。因此,一个例子可能同时出现在第一和第二套训练子集里边。相比之下,如果你没有使用替换去采样,第二套训练子集则从第一套抽样完之后剩余的90个中挑选。当然,在实际操作中,两种方法并不会有太多差异,但前者是常见的做法。

除非你已经尝试去画了学习曲线,并且认为画出来的线波动过大以至于没办法观察到本质的变化趋势,否则我不会去为这些技术烦恼。如果你的训练集很大——10000个样本——并且你的类别分布比较均衡,那么上述的技术你可能用不上。

最后,绘制学习曲线的计算成本可能很高:例如,假设你可能需要训练10个模型出来——从1000个,然后是2000个……一直到10000个样本。因为使用小数据集训练要比使用大数据集训练快得多,所以,实际上并不是像上面那样均匀地将训练集大小按照线性步长来划分,更通用的是将训练集划分为1000个、2000个、4000个、6000个和10000个样本的集合,然后训练它们得到对应的模型参数。这应该仍然能够让你清楚的了解学习曲线的趋势。当然,只有在训练模型的计算成本很大的时候,这种技术才有意义。