DL(三)
Structuring Machine Learning Projects
ML Strategy (1)
Why ML Strategy(机器学习策略)
什么是机器学习策略?
假设我们正在调试🐱分类器,经过一段时间调试,系统的准确率达到了90%,但还有不少能提升准确率的方法,在下图中我们列出一部分
上述的诸多想法我们都可以进行测试,但问题在于,如果做出了错误的选择,可能会浪费大量时间,朝错误的方向前进(同时注意不到错误),因此我们需要一些策略,来判断哪些方法是值得一试的,哪些是可以舍弃的,或者提出新的方法
Orthogonaization(正交化)
搭建机器学习模型时所面临的一个重要的问题是:可以尝试和改变的东西太多了
以这台老电视机为例。当我们要调整图像时,需要调整旋钮,我们可以很简单的知道,如果有一个旋钮集成了图像的长、宽、色度等信息时,我们要对图像进行合适的调整其实是很麻烦的,因此,电视的设计者将旋钮分为多个,每一个都对应着不同的属性,这即是正交化的思想(正交即为互成90度)
我们将其放在机器学习中思考
对于一个监督学习系统。通常需要调整系统的“旋钮”,确保四件事:
- 系统在训练集上的效果不错
- 系统在开发集上有良好表现
- 系统在测试集上表现良好
- 真实结果反馈
对于“旋钮”,当算法在成本函数上不能很好的拟合训练集,这个旋钮就意味着“训练更大的网络”或者“选择更好的算法”;
当算法对开发集的拟合很差,那么应该有一组独立的“旋钮”去调试;
对于开发集,有“正则化”和“增大训练集”等“旋钮”;
对于测试集,“旋钮“可能是”更大的开发集”<这种情况有可能是对开发集过拟合了>;
对于反馈,”旋钮“就有可能是”改变开发集“或”成本函数“<错误可能是开发集分布设置不正确或是成本函数测量的指标不对>
Single number evaluation metric(单一数字评估指标)
对于下面的应用
上面两列分别是它的查准率和查全率,但当我们想判断选择哪个时,问题来了?这两者孰优孰劣?
我们引入F1分数(两者的调和平均数)进行比较,这种方法有助于快速迭代
通过它进行判断,我们最终选择了A
Satisficing and Optimizing Metric
要把顾及到的所有事物组合成单实数评估指标,有时并不容易,因此,在一些情况下,设立满足与优化指标是很有用的
下图为例
假设我们最看重的是准确度,但同时我们也应该注意到识别图像所花费的时间,因此我们可以将准确度与运行时间组合成一个整体评估指标
我们可以选择对两个数值加权求和,但通常,选择一个 ”定义优化 && 满足指标“ 的分类器应该更为合适
Train/Dev/Test Distributions
本节主题:如何设立开发集和测试集?
- 开发集与测试集应来自于同一分布(可以取同一分布内的数据随机分布)
- 开发集与测试集的结果应该是符合预期的
Size of the Dev and Test Sets
怎样确定开发集与测试集的规模?
Old
Model
怎样选择测试集的规模呢?
我们知道,测试集的目的是完成开发之后,测试集用来评估其性能,因此,方针就是,让测试集尽可能大,能够以高置信度评估性能
When to Change Dev/Test Sets and Metrics?(什么时候改变开发/测试集与指标)
假设正在创建一个猫分类器,试图找到很多猫的照片,算法A与B分别有3%与5%的错误率,这样看来,算法A似乎表现得很好
但是当实际应用时,算法A错把XX图像当成猫图,尽管它推送了更多猫图,但是与需求(only 🐱!)发生了冲突,而B,5%的错误率使分类器得到较少的图像,但是并没有传进XX图,因此从实际出发,算法B实际上是一个更好的算法
在上述事件中,发生的就是,事件A在评估指标上做的更好,但从需求的角度出发,它无疑是一个比较糟糕的算法
在这种情况下,评估指标加上开发集都倾向于选择A,但需求制定者更偏向于B,因此当你的评估指标无法正确衡量算法之间的优劣排序时,在这种情况下,原来的指标错误的预测算法A是更好的算法,这就发出了信号,你应该改变评估指标或者开发集/测试集了!
此时使用的分类错误率指标
$Error\,=\,\frac{1}{m_{dev}}\,\sum^{m_{dev}}_{i=1}I\{y^{(i)}_pred\,+\,y^{(i)}\}$其中一个修改评估指标的方法是:添加权重项
$Error\,=\,\frac{1}{m_{dev}}\,\sum^{m_{dev}}_{i=1}w^{(i)}I\{y^{(i)}_pred\,+\,y^{(i)}\}$通过这个公式。我们给予不符合预期的图片更大的权重,以此让它们迅速变大
从上面的例子我们可以得出一个粗浅的结论:如果评估指标无法正确评估好算法的排名,我们需要改变它
Why Human-level Performance?
机器学习往往擅长模仿人能做的事
可以发现,一旦超过人类的水平,增长的明显变缓,最终贴近于上面的那条线 — 贝叶斯最优错误率
Avoidable Bias
在计算机视觉上,人类达到的误差与贝叶斯错误率相差不多,这时候我们将它们近似,在这种情况下,具有同样的训练错误率与开发错误率,我们决定于减少偏差(方差)的策略,而训练错误率与开发错误率之间的偏差,就大概说明了算法在方差问题上的改善空间,可以运用正则化等手段
我们将贝叶斯错误率的估计与训练错误率之间的差值,称为可避免偏差,这一概念,说明了有一些别的偏差,或错误率有个无法超越的最低水平
由此,对于上述情况
左边适合调整可避免偏差,而右边调整方差
因此,不同的场景,有不同的策略
Understanding Human-level Performance
思考人类水平错误率的方式之一,是将其作为贝叶斯错误率的替代或估计(这时我们往往将其看作多数人考虑后的错误率,而非个人)
在定义人类水平错误率时,要清楚目标所在,如果要表明可以超过单个人类,那么就有理由在某些场合部署你的系统
Improving your Model Performance(改善模型表现)
总结:正交化 设立开发集与测试集 用人类水平错误率估计贝叶斯错误率 估计可避免偏差与方差
想让一个监督学习算法达到实用,基本上需要完成2件事:
首先,算法对训练集的拟合很好,这可以看作可避免偏差很低
其次,在训练集中效果优良,然后推广到开发集和测试集也很好,这就是说方差不是太大
在正交化精神下,我们模拟出了”旋钮”,可以修正可偏差问题(训练更大的网络/训练更久),还有一套独立的“旋钮”可以用来处理方差问题(正则化/收集更多训练数据)
总结一下前几解的步骤,若想提高机器学习系统的性能,可以看训练错误率与贝叶斯估计值之间的距离,从而判断可避免偏差的大小(对训练集大小的优化还有多少空间),然后看开发错误率与训练错误率之间的距离,从而判断方差问题的大小(应该做多少努力,使算法表现能够从训练集推广到开发集)
当目标在减少可避免偏差时,可以尝试:
- 使用规模更大的模型
- 训练更久
- 使用更好的优化算法(加入momentum/RMSprop)/算法(Adam)
- 寻找更好的新神经网络架构
- 一组更好的超参数
当目标在改变方差时,可以尝试:
- 收集更多数据训练(可以更好的推广到系统看不到的开发集数据)
- 正则化
- 数据扩增
- 寻找更好的新神经网络架构(超参数搜索)
ML Strategy (2)
Carrying Out Error Analysis(误差分析)
我们以下面的情况为例
对于已经大致训练好的🐱图分类器,它的错误率为90%,但是它对一些🐕图仍束手无策
这种情况下,我们难道还需要专门做一个项目去处理🐕?这样值得吗?
这里提供一套错误分析流程,去帮助判断这个方向是否值得努力
- 收集部分带有错误标记的开发集例子
- 挨个观察标记中有多少是🐕
- 查看🐕在错误标记中所占的比例,判断对其进行更改的效果是否值得
人工统计在一些时候,确实能节省大量时间
使用表格判断方法是极为可取的
Cleaning up Incorrectly labeled data
当观察数据时,发现某些输出标签Y是错的,是否值得花时间去修正呢?
首先去考虑训练集,深度学习算法对于训练集中的随机错误是相当健壮的,即如果错误项离随机错误项不太远,
若错误足够随机,那么不管这些错误可能也没问题,而并不需要花太多时间去修复它们
深度学习对随机错误比较健壮,但对系统性的错误相对就没那么健壮了
而当开发集与测试集标记出现问题时该怎么办呢?
当你担心上述问题时,一般推荐在进行错误分析时,添加一个额外的列,统计它们的错误例子数
对于极少数例子数,你的分类器输出和标签不同,是因为标签出错,而非分类器出错
同时,你也可以统计因为标签错误所占的百分比
现在面临的问题是:是否值得修正6%标记出错的例子
建议是:如果错误非常严重,很大程度上影响了你在开发集上评估算法的能力,那么就应该去花时间修正错误的标签,但当它们没有严重影响到用开发集评估成本偏差的能力,那么处理的必要就相对较轻了
这里再提示一下设立开发集的主要目的:用它来从两个分类器A和B中选择一个
我们有时无法直观的从开发集中选择一个分类器,因为它无法体现哪个分类器比较好,标记出错产生的错误率即是其原因,这是就有充分的理由去修正开发集里的错误标签
我们这时就可以对上图右方开发集的错误标签动手,因为其标记出错 ,对算法错误的整体评估标准有严重的影响;而在左边的开发集中,标记错误对算法影响的百分比还是相对较小的
而再修改开发集数据之前,手动重新检查标签,并尝试修正一些标签,还有一些额外的方针与原则需要考虑
- 不管用何种修正手段,都要同时作用在开发集与测试集上(开发集是一个目标,当你命中目标之后,希望算法能够推广到测试集上,这样能够更高效的在来自同一分布的开发集和测试集上迭代)
- 同时检验算法判断正确和错误的例子,错误的可能还有正确的,反之同理,若是只修改正确的,对算法的偏差可能会变大
上述的两种注意事项实现较麻烦,因此也通常不会这么做,原因是:如果分类器很准确,那么判断错的次数比判断正确的次数要少得多
亲自花时间去检验错误是非常值得的
Training and testing on different distributions
深度学习对训练数据的“胃口”很大,当你收集到足够多带标签的数据构成训练集时,算法效果最好,即便它们都来自于和开发集与测试集不同的数据来训练,这里有一些做法可以来处理训练集与测试集存在差异的状况
以下题为例:
对于来自于web与app的🐱图
我们要通过上面的数据,划分数据,给出以下两种方案:
Option1
Option2
我们的需求是建立一个系统,令其在处理手机上传图片分布时效果良好,因此我们选择第二种,因为它精确的“对准”了目标
缺点在于训练集分布和开发集、测试集分布并不一样
Bias and Variance with mismatched data distributions
估计学习算法的偏差和方差来确定接下来的优先方向,但是当训练集和开发、测试集来自于不同分布时,分析偏差和方差的方式可能不同
通过对人类水平错误率、训练集错误率、训练 - 开发集错误率、开发集错误率进行分析,可以推断出可避免方差、方差、、数据不匹配问题各自多大
Addressing data mismatch(定位数据不匹配)
对来自不同分布的训练集与开发测试集,错误分析显示存在数据不匹配问题的状况,没有完全系统的解决方案,但可以尝试以下方案:
- 亲自进行错误分析,尝试了解训练集与开发集的具体差异
- 收集更多类似开发集和测试集的数据(包括人工合成)
Transfer learning(迁移学习)
神经网络从一个任务中习得知识,并将只是应用到另一个独立的任务中,即为迁移学习
假设已经训练好一个图像识别神经网络
可以是判断🐱🐕,我们想将其用于X光诊断,做法是,将最后一层以及进入最后一层的权重删掉,然后为最后一层重新赋予权重,让后将其放在放射诊断数据上训练
什么时候迁移学习是有意义的?
若你想从任务A学习,并迁移一些新知识到任务B,那么
- 当A与B都有同样的输入x时,迁移学习是有意义的,
- 当任务A的数据比任务B多得多时,迁移学习的意义更大(在想提高任务B的性能,因为B的每个数据更有价值 )
- 任务A的低层次特征可以帮助B的学习,那么迁移学习更有意义一些
Multi-task learning(多任务学习)
在迁移学习中,步骤是串行的,只是从任务A学习,然后迁移到任务B,而在多任务学习中,步骤是并行的,即试图让单个神经网络同时做多件事,希望每个任务都能帮助到其他所有任务
以上图为例,我们想同时辨别图片中的车、警示牌、行人、路灯等,因此对于输入图像$x^{(i)}$,那么将不再是一个标签(label)$y^{(i)}$,而是有四个标签
因此,$y^{(i)}$是个$4*1$向量
与之对应的$Y$,及如上所示
与softmax回归的主要区别在于,softmax将单个标签分配给单个样本,而这张图可以存在很多不同标签
训练一个神经网络,试图最小化函数,就需要多任务学习,因为现在的需求是建立单个神经网络,观察每张图,解决4个问题
同时,多任务学习也可以处理只有部分物体被标记的情况
多任务学习什么时候有意义?
- 训练的一组任务可以共用低层次特征
- 通常情况下,每个任务的数据量都相当大
- 多任务学习往往在以下场合更有意义:
- 可以训练一个足够大的网络去完成所有任务
- 因此多任务学习的替代方法是,为每个任务训练一个单独的神经网络
End-to-end deep learning(端到端深度学习)
举以下例子,
目标是输入x,比如说一段音频,然后将其映射到一个输出y(即这段音频的听写文本),
传统上,语音识别需要很多桥段的处理,首先会提取一些特征(MFCC),提取出一些低层次特征之后,可以应用机器学习算法,在音频片段中找到音位(声音的基本单位),将音位串在一起构成独立的词,然后将词串起来构成音频片段的听写文本,输出即是听写文本
端到端则是输入音频,直接输出听写文本
注意的是,端到端的方法适用于大规模数据进行训练,而较小规模的数据在传统流水线上效果反而更优秀 ,而如果是中间规模的数据,也可以使用中间件的方法,输入的依然还是音频,然后绕过特征提取,直接尝试从神经网络输出音位
比如人脸识别系统,当人接近传感器时,会先捕捉整体图像(中间件),再通过裁剪获取局部的人脸信息,再进行辨别
在数据对直接进行端到端学习有困难,而能较好地解决子问题时,通过解决子问题再回归到一端其实更为适合
端到端的优点:
- 数据说话
- 所需的手工设计的组件更少
端到端的缺点:
- 需要大量数据
- 排除了可能有用的手工组件
学习算法有两个数据来源,一个是数据,另一个是手工设计的组件、功能······
当尝试使用端到端深度学习构建深度学习系统时,关键问题在于数据量的多少,已有数据能否支持直接学到从x映射到y