详解数据分布不匹配时,偏差与方差的分析
估计学习算法的偏差和方差真的可以帮确定接下来应该优先做的方向,但是,当训练集来自和开发集、测试集不同分布时,分析偏差和方差的方式可能不一样,来看为什么。
继续用猫分类器为例,说人类在这个任务上能做到几乎完美,所以贝叶斯错误率或者说贝叶斯最优错误率,知道这个问题里几乎是0%。所以要进行错误率分析,通常需要看训练误差,也要看看开发集的误差。比如说,在这个样本中,训练集误差是1%,开发集误差是10%,如果开发集来自和训练集一样的分布,可能会说,这里存在很大的方差问题,算法不能很好的从训练集出发泛化,它处理训练集很好,但处理开发集就突然间效果很差了。
但如果训练数据和开发数据来自不同的分布,就不能再放心下这个结论了。特别是,也许算法在开发集上做得不错,可能因为训练集很容易识别,因为训练集都是高分辨率图片,很清晰的图像,但开发集要难以识别得多。所以也许软件没有方差问题,这只不过反映了开发集包含更难准确分类的图片。所以这个分析的问题在于,当看训练误差,再看开发误差,有两件事变了。首先算法只见过训练集数据,没见过开发集数据。第二,开发集数据来自不同的分布。而且因为同时改变了两件事情,很难确认这增加的9%误差率有多少是因为算法没看到开发集中的数据导致的,这是问题方差的部分,有多少是因为开发集数据就是不一样。
为了弄清楚哪个因素影响更大,如果完全不懂这两种影响到底是什么。但为了分辨清楚两个因素的影响,定义一组新的数据是有意义的,称之为训练-开发集,所以这是一个新的数据子集。应该从训练集的分布里挖出来,但不会用来训练网络。
意思是已经设立过这样的训练集、开发集和测试集了,并且开发集和测试集来自相同的分布,但训练集来自不同的分布。
要做的是随机打散训练集,然后分出一部分训练集作为训练-开发集(training-dev),就像开发集和测试集来自同一分布,训练集、训练-开发集也来自同一分布。
但不同的地方是,现在只在训练集训练神经网络,不会让神经网络在训练-开发集上跑后向传播。为了进行误差分析,应该做的是看看分类器在训练集上的误差,训练-开发集上的误差,还有开发集上的误差。
比如说这个样本中,训练误差是1%,说训练-开发集上的误差是9%,然后开发集误差是10%,和以前一样。就可以从这里得到结论,当从训练数据变到训练-开发集数据时,错误率真的上升了很多。而训练数据和训练-开发数据的差异在于,神经网络能看到第一部分数据并直接在上面做了训练,但没有在训练-开发集上直接训练,这就告诉,算法存在方差问题,因为训练-开发集的错误率是在和训练集来自同一分布的数据中测得的。所以知道,尽管神经网络在训练集中表现良好,但无法泛化到来自相同分布的训练-开发集里,它无法很好地泛化推广到来自同一分布,但以前没见过的数据中,所以在这个样本中确实有一个方差问题。
来看一个不同的样本,假设训练误差为1%,训练-开发误差为1.5%,但当开始处理开发集时,错误率上升到10%。现在方差问题就很小了,因为当从见过的训练数据转到训练-开发集数据,神经网络还没有看到的数据,错误率只上升了一点点。但当转到开发集时,错误率就大大上升了,所以这是数据不匹配的问题。因为学习算法没有直接在训练-开发集或者开发集训练过,但是这两个数据集来自不同的分布。但不管算法在学习什么,它在训练-开发集上做的很好,但开发集上做的不好,所以总之算法擅长处理和关心的数据不同的分布,称之为数据不匹配的问题。
再来看几个样本,因上面没空间了。所以训练误差、训练-开发误差、还有开发误差,说训练误差是10%,训练-开发误差是11%,开发误差为12%,要记住,人类水平对贝叶斯错误率的估计大概是0%,如果得到了这种等级的表现,那就真的存在偏差问题了。存在可避免偏差问题,因为算法做的比人类水平差很多,所以这里的偏差真的很高。
最后一个例子,如果训练集错误率是10%,训练-开发错误率是11%,开发错误率是20%,那么这其实有两个问题。第一,可避免偏差相当高,因为在训练集上都没有做得很好,而人类能做到接近0%错误率,但算法在训练集上错误率为10%。这里方差似乎很小,但数据不匹配问题很大。所以对于这个样本,如果有很大的偏差或者可避免偏差问题,还有数据不匹配问题。
写出一般的原则,要看的关键数据是人类水平错误率,训练集错误率,训练-开发集错误率,所以这分布和训练集一样,但没有直接在上面训练。根据这些错误率之间差距有多大,可以大概知道,可避免偏差、方差数据不匹配问题各自有多大。
说人类水平错误率是4%的话,训练错误率是7%,而训练-开发错误率是10%,而开发错误率是12%,这样就大概知道可避免偏差有多大。因为知道,希望算法至少要在训练集上的表现接近人类。而这大概表明了方差大小,所以从训练集泛化推广到训练-开发集时效果如何?而这告诉数据不匹配的问题大概有多大。技术上还可以再加入一个数字,就是测试集表现,写成测试集错误率,不应该在测试集上开发,因为不希望对测试集过拟合。但如果看看这个,那么这里的差距就说明对开发集过拟合的程度。所以如果开发集表现和测试集表现有很大差距,那么可能对开发集过拟合了,所以也许需要一个更大的开发集,对吧?要记住,开发集和测试集来自同一分布,所以这里存在很大差距的话。如果算法在开发集上做的很好,比测试集好得多,那么就可能对开发集过拟合了。如果是这种情况,那么可能要往回退一步,然后收集更多开发集数据。现在写出这些数字,这数字列表越往后数字越大。
这里还有个例子,其中数字并没有一直变大,也许人类的表现是4%,训练错误率是7%,训练-开发错误率是10%。但看看开发集,发现,很意外,算法在开发集上做的更好,也许是6%。所以如果见到这种现象,比如说在处理语音识别任务时发现这样,其中训练数据其实比开发集和测试集难识别得多。所以这两个(7%,10%)是从训练集分布评估的,而这两个(6%,6%)是从开发测试集分布评估的。所以有时候如果开发测试集分布比应用实际处理的数据要容易得多,那么这些错误率可能真的会下降。所以如果看到这样的有趣的事情,可能需要比这个分析更普适的分析。
所以,就以语音激活后视镜为例子,事实证明,一直写出的数字可以放到一张表里,在水平轴上,要放入不同的数据集。比如说,可能从一般语音识别任务里得到很多数据,所以可能会有一堆数据,来自小型智能音箱的语音识别问题的数据,购买的数据等等。然后收集了和后视镜有关的语音数据,在车里录的。所以这是表格的\(x\)轴,不同的数据集。在另一条轴上,要标记处理数据不同的方式或算法。
首先,人类水平,人类处理这些数据集时准确度是多少。然后这是神经网络训练过的数据集上达到的错误率,然后还有神经网络没有训练过的数据集上达到的错误率。所以结果是人类水平的错误率,数字填入这个单元格里(第二行第二列),人类对这一类数据处理得有多好,比如来自各种语音识别系统的数据,那些进入训练集的成千上万的语音片段,而例子是4%。这个数字(7%),可能是训练错误率,在例子中是7%。是的,如果学习算法见过这个样本,在这个样本上跑过梯度下降,这个样本来自训练集分布或一般的语音识别数据分布,算法在训练过的数据中表现如何呢?然后这就是训练-开发集错误率,通常来自这个分布的错误率会高一点,一般的语音识别数据,如果算法没在来自这个分布的样本上训练过,它的表现如何呢?这就是说的训练-开发集错误率。
如果移到右边去,这个单元格是开发集错误率,也可能是测试集错误,在刚刚的例子中是6%。而开发集和测试集,实际上是两个数字,但都可以放入这个单元格里。如果有来自后视镜的数据,来自从后视镜应用在车里实际录得的数据,但神经网络没有在这些数据上做过反向传播,那么错误率是多少呢?
分析是观察这两个数字之间的差异(Human level 4% 和Training error 7% ),还有这两个数字之间(Training error 7% 和Training-dev error 10% ),这两个数字之间(Training-dev error 10% 和Dev/Test dev 6% )。这个差距(Human level 4% 和Training error 7% )衡量了可避免偏差大小,这个差距Training error 7% 和Training-dev error 10% )衡量了方差大小,而这个差距(Training-dev error 10% 和Dev/Test dev 6%)衡量了数据不匹配问题的大小。
事实证明,把剩下的两个数字(rearview mirror speech data 6% 和Error on examples trained on 6%),也放到这个表格里也是有用的。如果结果这也是6%,那么获得这个数字的方式是让一些人自己标记他们的后视镜语音识别数据,看看人类在这个任务里能做多好,也许结果也是6%。做法就是,收集一些后视镜语音识别数据,把它放在训练集中,让神经网络去学习,然后测量那个数据子集上的错误率,但如果得到这样的结果,好吧,那就是说已经在后视镜语音数据上达到人类水平了,所以也许对那个数据分布做的已经不错了。
当继续进行更多分析时,分析并不一定会给指明一条前进道路,但有时候可能洞察到一些特征。比如比较这两个数字(General speech recognition Human level 4% 和rearview mirror speech data 6%),告诉对于人类来说,后视镜的语音数据实际上比一般语音识别更难,因为人类都有6%的错误,而不是4%的错误,但看看这个差值,就可以了解到偏差和方差,还有数据不匹配这些问题的不同程度。所以更一般的分析方法是,已经用过几次了。还没用过,但对于很多问题来说检查这个子集的条目,看看这些差值,已经足够让往相对有希望的方向前进了。但有时候填满整个表格,可能会洞察到更多特征。
最后,以前有过很多处理偏差的手段,讲过处理方差的手段,但怎么处理数据不匹配呢?特别是开发集、测试集和训练集数据来自不同分布时,这样可以用更多训练数据,真正帮提高学习算法性能。但是,如果问题不仅来自偏差和方差,现在又有了这个潜在的新问题,数据不匹配,有什么好办法可以处理数据不匹配的呢?实话说,并没有很通用,或者至少说是系统解决数据不匹配问题的方法,但可以做一些尝试,可能会有帮助。