深度学习笔记(17) 误差分析(二)
1. 使用来自不同分布的数据进行误差分析
越来越多的团队都用来自和开发集、测试集分布不同的数据来训练
这里有一些最佳做法来处理训练集和测试集存在差异的情况
假设在开发一个手机应用,用户会上传他们用手机拍摄的照片
想识别用户从应用中上传的图片是不是猫
现在有两个数据来源:
- 一个是真正关心的数据分布,来自应用上传的数据
这些照片一般更业余,取景不太好 - 一个数据来源就是用爬虫程序挖掘网页直接下载
就这个样本而言,可以下载很多取景专业、高分辨率的猫图
如果应用用户数还不多,也许只收集到10,000张用户上传的照片
但通过爬虫挖掘网页,可以下载到海量猫图
而真正关心的算法表现是
最终系统处理来自应用程序的这个图片分布时效果好不好
现在就陷入困境
因为有一个小的数据集,而一个大得多的数据集来自另一个分布,和真正想要处理的并不一样
但又不想直接用这10,000张图片,因为这样训练集就太小了
有一种选择,可以做的一件事是将两组数据合并在一起
这样就有21万张照片,把这21万张照片随机分配到训练、开发和测试集中
为了说明观点
假设已经确定开发集和测试集各包含2500个样本
所以训练集有205000个样本
这么设立数据集好处在于,训练集、开发集和测试集都来自同一分布,这样更好管理
但坏处在于如果观察开发集
看看这2500个样本其中很多图片都来自网页下载的图片
那并不是真正关心的数据分布,真正要处理的是来自手机的图片
所以对于这2500个样本,数学期望值是:2500×200k/210k=2381
有2381张图来自网页下载
但平均而言,只有119张图来自手机上传
要记住,设立开发集的目的是告诉团队去瞄准的目标
而大部分精力都用在优化来自网页下载的图片
所以不建议使用第一个选项
因为这样设立开发集就是告诉团队针对不同于实际关心的数据分布去优化
另外一条路,训练集还是205k张图片
其中来自网页下载的200k张图片,再加上5k张来自手机上传的图片
对于开发集和测试集都是2.5k张手机图
这样将数据分成训练集、开发集和测试集的好处在于,现在瞄准的目标就是想要处理的目标
缺点在于,现在训练集分布和开发集、测试集分布并不一样
但事实证明,这样把数据分成训练、开发和测试集,在长期能够带来更好的系统性能
来看另一个样本,假设正在开发一个全新的产品,一个语音激活汽车后视镜
这就是造一个后视镜,把这个小东西换掉,现在就可以和后视镜对话了
只需要说:“亲爱的后视镜,请帮我找找到最近的加油站的导航方向”
然后后视镜就会处理这个请求
那么怎么收集数据去训练这个产品语言识别模块呢?
也许有很多来自其他语音识别应用的数据,它们并不是来自语音激活后视镜的数据
对于训练集,可以将拥有的所有语音数据,从其他语音识别问题收集来的数据
比如这些年从各种语音识别数据供应商买来的数据
可以直接买到成 x, y 对的数据,其中x是音频剪辑,y是听写记录
或者研究过智能音箱,语音激活音箱
所以有一些数据,也许做过语音激活键盘的开发之类的
举例来说,也许从这些来源收集了500,000段录音
对于开发集和测试集也许数据集小得多
比如实际上来自语音激活后视镜的数据
因为用户要查询导航信息或试图找到通往各个地方的路线
这个数据集可能会有很多街道地址
“请帮我导航到这个街道地址”,或者“请帮助我导航到这个加油站”
所以这个数据的分布和左边大不一样
但这真的是关心的数据
因为这些数据是产品必须处理好的
所以就应该把它设成开发和测试集
在这个样本中,应该这样设立训练集,左边有500,000段语音
然后开发集和测试集,把它简写成 D和 T
可能每个集包含10,000段语音,是从实际的语音激活后视镜收集的
或者换种方式
如果觉得不需要将20,000段来自语音激活后视镜的录音全部放进开发和测试集
可以拿一半,把它放在训练集里,那么训练集是51万段语音
包括来自那里的50万段语音,还有来自后视镜的1万段语音
开发集和测试集也许各自有5000段语音
那是不是应该把收集到的数据都用掉?
不一定!
2. 数据分布不匹配时的偏差与方差
用猫分类器为例,人类在这个任务上能做到几乎完美
所以贝叶斯错误率或者说贝叶斯最优错误率几乎是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%
比如说在处理语音识别任务时发现这样
其中训练数据其实比开发集和测试集难识别得多
所以有时候如果开发测试集分布比应用实际处理的数据要容易得多
那么这些错误率可能真的会下降
所以如果看到这样的有趣的事情,可能需要比这个分析更普适的分析
就以语音激活后视镜为例
观察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%
训练-开发错误率和开发集错误率衡量了数据不匹配问题大小
当继续进行更多分析时,分析并不一定会指明一条前进道路
但有时候可能洞察到一些特征
比如比较 一般语音识别人类水平错误率 4% 和 人类对后视镜语言数据错误率 6%
对于人类来说,后视镜的语音数据实际上比一般语音识别更难
但看这个差值,就可以了解到偏差和方差,还有数据不匹配这些问题的不同程度
3. 处理数据不匹配问题
处理数据不匹配这个问题没有完全系统的解决方案
通常会亲自做错误分析,尝试了解训练集和开发测试集的具体差异
为了避免对测试集过拟合,要做错误分析,应该人工去看开发集而不是测试集
如果正在开发一个语音激活的后视镜应用
可能要听一下来自开发集的样本,尝试弄清楚开发集和训练集到底有什么不同
比如说可能会发现很多开发集样本噪音很多,有很多汽车噪音
这就是开发集和训练集差异之一
也许还会发现其他错误
比如它可能经常识别错误街道号码,很多导航请求都有街道地址
所以这个也很重要
当了解开发集误差的性质时,开发集可能跟训练集不同或者更难识别
那么尝试把训练数据变得更像开发集一点
比如说,如果发现车辆背景噪音是主要的错误来源
那么可以通过人工数据合成更多的模拟车辆噪声数据
参考:
相关推荐:
深度学习笔记(16) 误差分析(一)
深度学习笔记(15) 人的表现
深度学习笔记(14) 评估指标
深度学习笔记(13) Softmax分类
深度学习笔记(12) Batch归一化网络
谢谢!