深度学习-误差分析
执行误差分析
引言:假设在进行一个猫分类的训练,目前已经达到了90%的正确率,经过查看发现错误的数据中有许多的关于狗的被识别错误,这里是否需要正对狗收集更多的图片?或设计一些只处理狗的算法功能?或做一个项目专门处理狗?
错误分析流程:
- 收集一些比如100个错误标记的验证集的例子
- 检查其中有多少个是狗
- 假如狗的概率是5%,则对应的100个中有5个是狗标记错误的,这样的话,如果采取上述一些比较耗费时间的措施,就有可能浪费了很多时间,但最多也只能将正确率从90%提升到90.5%,这个值也可以称为是改善算法性能的上限
- 假如狗的概率是50%,则这种情况下,花费一些时间去解决狗的问题可能效果就更好,可能就将正确率从90%提升到了95%
有时,在进行错误分析的同时,也可以并行评估几个问题:
以猫检测器为例:
- 或许可以改善针对狗的图片的性能
- 或许可以改善针对一些猫科动物如狮子、豹等的误识别问题
- 或许可以改善在模糊图像上的性能
综上可以使用表格进行记录如:
Image | 狗识别错误 | 猫科动物识别错误 | 模糊图像 | 备注 |
---|---|---|---|---|
1 | Y | 泰迪犬 | ||
2 | Y | |||
3 | Y | Y | 下雨天的大型猫科动物 | |
... | ... | ... | ... | ... |
总百分比 | 8% | 43% | 61% |
然后根据统计百分比,决定是否值得去处理每个不同的错误类型
清楚标注错误的数据
如果发现数据中有一些标记错误的例子,应该怎么办?
- 考虑训练集,事实证明,深度学习算法对于训练集中的随机错误是相当健壮的,只要标记出错 的例子离随机错误不太远,如果错误足够随机,那么放着这些错误不管可能也没问题,而不用花费时间去修复,只要数据集足够大,实际错误率一般不会太高
- 如果是验证集或测试集中有这些标记出错的例子,一般建议在错误分析时,添加一个额外的列,这样就可以进行统计了,如果这些标记错误严重影响了在开发集上评估算法的能力,就应该花时间去修正,但如果没有严重影响,可能就不应该浪费时间去修正,比较修正最大可能带来的正确率的提升是否足够多
修正验证集或测试集的错误样本:
- 无论怎样,都要同时作用到验证集和测试集上,从而确保他们来自相同分布
- 考虑同时检验算法判断正确和判断错误的例子
- 可能决定只修正开发集和测试集中的标签,因为它们通常比训练集小的多,这样其实是可以的,但需要进行一些步骤用于处理训练集分布和验证集、测试集不同的情况,但是验证集和测试集来自同一分布非常重要
快速搭建第一个系统,并进行迭代
以语音识别为例:
- 嘈杂的背景
- 咖啡厅噪音
- 汽车噪音
- ...
- 带口音的声音
- 远距离声音
- 儿童声音
- 口吃等类似的声音
- ...
一般来说,对于几乎所有的机器学习程序,都会有很多的不同方向可以选择前进,并且每个方向都是相对合理的,可以改善系统,但挑战在于,如何选择一个方向集中精力处理
- 设定验证集和测试集
- 迅速建立初始化系统
- 使用偏差/方差分析和错误分析等来确定下下一步优先做什么
在不同分布上训练和测试
eg: 假设需要开发一个识别猫的App,从网上找到的训练数据集往往是比较清楚的高清图片等,但用户可能会上传一些用手机拍摄的模糊照片。因此,有两个数据来源,一个是真正关心的数据分布,来自应用上传的数据,一般比较业余,另一个数据来源就是从网上获取的相对专业的猫图片,因此你可能会获取这样一些数据,大量的如200,000张清楚的图片,和少量的如10,000张模糊的图片,相当于它们并不来自同一分布,那么应该怎么做?
选择1:将这些图片合在一起,相当于有了210,000张照片,然后随机分配到训练、开发和测试集中,这样做好处在于:训练集、验证集和测试集都来自同一分布,更好管理;坏处在于:如果观察验证集则会发现这些图片中很多图片来自网上下载的高清图片,并不是真正关心的数据分布,真正要处理的是手机上传的图片,因此通常不建议使用这种方式
选择2:训练集是来自网上下载的200,000张图片,如果需要再加上5000张来自手机上传的图片,然后对于验证集和测试集,则都是手机上传的图片,这样划分的好处在于:现在验证集中针对的目标就是想要处理的目标;坏处在于:现在的训练集分布和验证集、测试集分布不一样,但事实证明这样划分,在长期能带来更好的性能
eg: 假设你需要实现一个语音激活后视镜,那么可能会从网上获取或购买一些各种语音数据,但不一定和你的目的相关,这些数据非常多(如500,000段语音),还会有一些语音激活后视镜的相关语间数据,而这些就相对比较少(如20,000段语音)
在这个例子中,可以这样划分数据集:
将500,000段语音作为训练集,然后对于验证集和测试集每个包括10,000段语音激活后视镜相关的语音,或510K+5K+5K划分
不匹配数据分布的偏差和方差
还是以猫分类器为例,假设人类错误率约为0%,因此贝叶斯错误率(或贝叶斯最优错误率)在这个问题中基本为0%,假设训练集错误率是1%,验证集错误率是10%
如果验证集和训练集来自同一分布,可能会认为这里存在很大的方差问题,算法不能很好的泛化;
但如果训练集和验证集来自不同的分布,就不能下定上述结论了,因为可能算法在验证集上做得不错,可能是因为训练集容易识别,因为训练集都是高清图上,而验证集则比较难识别,因此,可能算法并没有方差问题,这只是反映了验证集中包含更难分类的图片
因此,当训练集和验证集来自不同的分布时,再看训练错误和验证错误,有两件事情发生了变化 :
- 算法只使用了训练集数据,并没有使用验证集数据
- 验证集数据来自不同的分布
所以,很难确认这增加的9%的错误率有多少是因为算法没用到验证集的数据导致的
为了解决这种问题,定义一种新的数据集——训练-验证数据集是有必要的,它和训练集数据分布一样,但不用来训练,具体步骤是:随机打散一些训练集,然后分出一部分作为 训练-验证集,就像验证集和测试集一样,训练集和训练-验证集也来自同一分布,但不同的是,现在,只在训练集上训练神经网络,然后需要查看的是分类器在训练集上的错误、在训练-验证集上的错误、还有在验证集上的错误

假设上述问题中的训练集错误率是1%,训练-验证集错误率是9%,验证集错误率是10%,则说明算法存在方差问题;
同样假设上述问题中的训练集错误率是1%,训练-验证集错误率是1.5%,验证集错误是10%,则说明存在数据不匹配问题

处理数据不匹配
- 如果发现有严重的数据不匹配问题,通常会做错误分析,了解训练集和验证、测试集的具体差异
- 可以尝试将训练集数据变得更像验证集,或收集更多类似验证集和测试集的数据
- 人工合成数据
迁移学习
神经网络可以从一个任务中学习,并将这些学习的内容应用到另一个独立的任务中
假设有一个已经训练好的图像识别神经网络,有输入图像x和识别对象y,将这个神经网络拿出进行迁移,如放射性诊断,可以做的是将神经网络最后的输出层拿走,然后将进入最后一层的权重删掉,然后为最后一层重新赋予随机权重,然后让它在放射诊断数据上训练
即要实现迁移学习,要做的就是将数据集换成新的x和y,x就是上述的放射性诊断图,y是诊断结果,然后将最后一层的权重随机初始化,然后在这个新数据集上重新训练网络。如果新数据集很小,你可能只需要重新训练最后一层的权重,并保持其它参数不变;但如果有足够多的数据,可以重新训练神经网络中剩下的所有层
规则通常是:如果有一个小数据集,就只训练输出层前的最后一层或两层,如果有大量数据,则可以重新训练网络中的所有参数
如果重新训练网络中的所有参数,那么这个在图像识别数据的初期训练阶段(称为预训练),如果以后更新所有权重,然后在新数据上训练,这个过程也称为微调
为什么会有这样的效果呢?
有很多低层次特征如边缘检测、曲线检测、阳性对象检测等,从大的图像识别数据库中学习的这些能力,可能有助于算法在新数据诊断中做得更好
迁移学习,通常迁移来源问题中有很多数据,但迁移目标问题中通常数据相对较少,而反过来往往是不可行的。
总结:什么时候迁移学习是有意义的?
想提高任务B的性能
任务A和任务B有一样类型的输入
任务A的数据比任务B的数据多
任务A的低层次特征对任务B有帮助
多任务学习
在迁移学习中,步骤是串行的,从任务A学习,然后迁移到任务B
而在多任务学习中,是现时开始学习的,尝试让单个神经网络同时做几件事情,然后希望让每个任务都能帮到其它任务
以自动驾驶为例:
神经网络的输入x是一张图片,输出y是一个四维向量,对应的是预测图中有没有行人、有没有车、有没有停车标志、有没有交通灯
对应的损失函数:\(\frac{1}{m} \sum_{i=1}^m \sum_{j=1}^4 L(\hat y_j^{(i)},y_j^{(i)}) \ (此处L使用的是Logistic \ loss)\)
与softmax回归不同的是,softmax将单个标签分配给单个样本,而这里这张图可以有很多不同的标签
如果训练一个神经网络,试图最小化这个代价函数,进行的就是多任务学习,因为现在做是建立单个神经网络,观察每张图,然后解决四个问题,此外,也可以训练四个不同的神经网络,但神经网络的一些早期特征在识别不同物体时都会用到,然后就会发现,训练一个神经网络做四件事会比训练四个完全独立的神经网络分别做四件事性能要更好。
多任务学习什么时候有意义?
- 训练的一组任务可以共用低层次特征
- 通常每个任务的数据量很接近
- 可以训练一个足够大的神经网络同时做好所有的工作
通常迁移学习的使用频率比多任务学习更高
什么是端到端学习
简而言之,以前有一些数据处理系统或学习系统,它们需要多个阶段的处理,而端到端深度学习,就是忽略所有这些不同的阶段,用单个神经网络代替。
以语音识别为例:
目标是对于输入音频x,映射一个输出对应文本y
传统上,语音识别需要很多阶段的处理,首先提取一些特征,然后使用机器学习算法找到"音素"(phoneme:声音的基本单位),再将单位串在一起构成独立的词,最后将词串起来构成文本
而端到端深度学习做的是,训练一个巨大的神经网络,输入是一个音频x,输出是文本y,直接绕过了中间步骤,训练出一个从x到y的映射
而端到端深度学习的的一个挑战是可能需要大量的数据,才能让训练结果变得足够好
以身份验证系统为例:
一种做法是,将获取的图片作为输入x,而输出y则是对应的身份,但由于人站位不同、距离不同等,拍摄的图片可能会各种各样
因此,迄今为止最好的做法是:使用多步方法,首先使用一个算法进行人脸检测,检测到人脸,然后放大对应的部分,并裁剪图像,使人脸居中显示,然后再输入到神经网络中,通常神经网络判别身份,结果显示,这种将任务分成两个更简单的任务,通常在整体上得到的表现更好。
为什么分成两步更好呢?
- 解决的两个问题,每个问题实际上要简单得多
- 两个子任务的训练数据都很多;对于人脸检测的数据,网络上有许多,而对于第二步,可看作是检测两张图片上的人是否是同一个,对就的网络上数据也有很多,而对于原始的一步方法对应的输入输出对应的数据,则相对很少了
是否使用端到端学习
端到端学习的优点:
- 只让数据说话;只要有足够多的数据,不用关注中间繁琐的其它步骤
- 所需手动设计的组件更少
缺点:
- 可能需要大量的数据(有时如果没有大量数据,可以尝试将任务拆分成可能收集到大量数据的子任务)
- 排除了可能有用的手动设计的组件
因此,是否使用端到端学习的关键的问题在于:
是否有足够的数据能够直接学习复杂的从x映射到y的函数?