机器学习策略(二)
1 错误分析
1.1 进行错误分析
假设我们正在训练一个猫分类器,准确率达到为 80%,错误率则为 20%,显然还有很大的进步空间。那么我们应该从哪一个方向着手提升准确率呢?错误分析可以让我们很快地分析出哪些工作是值得我们优先做的。
具体来说,随机抽取开发集中 100 张分类错误的图片。首先,找出这些图片被错误分类的原因。例如 ,某些狗太像猫了所以被误判成了猫,一些图片模糊不清导致分类器不能正确的识别,或者一些图片经过了滤镜的处理迷惑了分类器。接着统计出每个原因导致的错误分类图片占这 100 张图片的比重,贴别的,可以为某些被错误分类的图片做一些详细批注。最后我们可以得到这样一张表格:
这样我们就可以计算出在由于每个错因造成的错误率:
模糊不清:
60
%
∗
20
%
=
12
%
60\% * 20\% = 12\%
60%∗20%=12%
滤镜:
40
%
∗
20
%
=
8
%
40\% * 20\% = 8\%
40%∗20%=8%
狗:
10
%
∗
20
%
=
2
%
10\% * 20\% = 2\%
10%∗20%=2%
所以,在“模糊不清”这一个错因上,我们的提升空间最大。也就是说,提高分类器在模糊图片上的表现对于提升分类器的准确率是最有价值的,理想情况下我们可以将分类器准确率从 80% 提升 12% 至 92%,而将错误率由 20% 降至 8%. 而在“狗”这个错因上,即使我们绞尽脑汁,花上几个月的时间也只能提升 2% 的准确率,所以相对于“模糊不清”和“滤镜”这两个错因,“狗”并不是一个值得优先考虑的选项。
1.2 清理错误标记的数据
如果发现个别样本被标记错误,应该如何处理?
例如,标记员把一只白色的狗错误地标记成了猫。只要这些错误不是那么偏离随机分布,而可能只是由标记的人偶然的疏忽造成的, 那么这些错误是属于随机错误的。
若是这些错误出现在训练集中,那么我们基本可以不管这些错误,也不用花费太多的时间去纠正它们。因为深度学习算法对训练集中的随机错误很稳健,但对系统错误就不那么稳健了。例如标记员总是把白色的狗错误地标记成猫,这是属于系统误差的。若训练集中出现了这种系统误差,那么分类器就会把所有白色的狗分类为猫。
我们已经讨论了如何处理在训练集中的被错误标记的数据。 那么,对于开发集和测试集中的数据呢?一个比较推荐的做法是,在错误分析的表格中,增加一列,用来统计标签 Y 错误的数量。假设经过统计后,在 100 张开发集分类结果错误的图片中共有 5 张标签被标记错误。
假设在开发集上总错误率为
20
%
20\%
20%,那么:
由标签错误造成的错误率:
20
%
∗
5
%
=
1
%
20\%*5\%=1\%
20%∗5%=1%
由其他原因造成的错误率:
20
%
−
1
%
=
19
%
20\%-1\%=19\%
20%−1%=19%
此时由标签错误造成的错误率只占整体错误率很小的一部分,所以纠正标签并不是当下最重要的事情。
假设你在这个问题上取得了重大进步,错误率降到了 3% 且其中依然有 1% 的错误率是由错误的标签引起的。1% 在整体 3% 的错误分类中的占比是很大的,因此,这一次更值得花时间去纠正这些开发集中错误的数据标签。
2 训练集与开发集/测试集分布不一致
2.1 训练集与开发集/测试集不同分布
第一个例子:实现能够识别猫的移动应用
假设你正在做一个移动应用,用户将从他们的手机上传图片,你想要识别这些图片是不是猫的图片。你现在有 2 个数据源。一个是你真正需要关心的数据,来自于移动应用用户上传的 10K 猫的图片,通常拍摄和构图都不怎么专业,甚至可能是糊的。另一个数据源是你通过在网页上爬取到的 200K 的猫的图片,拍摄很专业,构图专业且分辨率高。
由于你开发的是一款移动应用,那么你目标是使你的分类器在右边的图片上表现足够好。但是两难的是右边的数据集比较小,只有 10K 个样本。而另一个数据集虽然大得多,包含 200K 个样本,但是与你真正关心的目标数据的分布却不一致。
方案一:
将这些数据集放在一起,这样就有了 210K 个图片 然后将这 210K 个图片随机混合,再划分为训练 / 开发 / 测试集,包含样本数量分别为 205K / 2.5K / 2.5K.
方案一的训练/开发/测试集都来自于同一分布,易于管理,但是它也有一个很大的缺点:开发集有 2.5K 个样例,但大部分来自网页图片的分布而不是你真正关心的来自移动应用图片的分布。请记住,开发集是机器学习优化的目标,而方案一的开发集中大部分都是来自网页的猫的图片,也就是说正在花费大量的时间优化系统在网页图片上的性能。而你的目的是识别用户上传到移动应用的图片,所以这里不建议采用方案一,而是采取方案二。
方案二:
在 10K 来自移动应用的图片中,拿出 2.5K 作为开发集,再拿出 2.5K 作为测试集。将剩下的 5K 来自移动应用的图片与全部的 200K 来自网页的图片混合后随机打乱,作为训练集。
第二个例子:智能语音后视镜
假设:你正在打造一款可以识别语音的后视镜。你只收集到了少量的来自语音识别后视镜的数据,包含 20K 条话语样本。但你已经收集到大量(500K条话语样本)的来自其他语音识别应用的数据,比如,智能语音音箱的数据、来自语音输入法的数据。
你的目的是打造一个语音识别后视镜,所以你应该更加关心来自语音识别后视镜的数据,因为这才是你的产品在工作环境中经常接触到的数据。因此,应该由来自语音识别后视镜的数据来组成开发/测试集。所以我们可以按照以下的方式划分训练/开发/测试集。
方案一:
将 500K 条来自其他语音识别应用的话语样本设置为训练集。而开发集和测试集分别包含 10K 个来自语音激活后视镜的真实话语样本。
方案二:
开发/测试集分别包含 5K 个来自智能语音后视镜的话语样本。将另一半的来自智能语音后视镜的话语样本、以及来自其他语音识别产品的话语样本分给训练集,那么训练集将包含 510K 个话语样本。
这两个例子告诉我们:
第一:机器学习算法在特定的环境中工作,在开发集上的表现是机器学习算法提升性能的目标,所以开发集中的数据应该能反映真实的反映机器学习算法的工作环境。
第二:如果允许训练集和开发/测试集的数据来自不同的分布,那么你将拥有一个大得多的训练集,这样能使你的算法表现得更好。
2.2 偏差和方差与数据分布不匹配
通过估计学习算法的偏差和方差,能帮你确定下一步工作的优先级。但当你的训练集与开发集/测试集来自不同的分布时,偏差和方差的分析方法也会相应变化。
继续使用猫分类器的例子,假设人类在这个问题上有近乎完美的表现,即贝叶斯误差约等于0%. 假设在这个例子中训练集误差为 1%,开发集误差为 10%.
如果开发集和训练集数据,来自同一分布,那说明问题是方差过大,代表虽然算法的训练集表现好,但未能较好地泛化(generalize)到开发集。但如果训练集与开发集的数据来自不同分布的话,就未必能这样肯定地下结论了。我们很难判断这 9% 的误差有多少是因为过拟合造成的,又有多少是因为开发集的数据分布不同而造成的?
为了梳理出这两个影响,我们需要从原训练集中分出一小组数据,然后将这一组数据定义为训练-开发集(training-dev set) 。和开发集与测试集分布相同一样,训练-开发集与训练集也遵循相同分布。其次,不能直接拿训练-开发集来训练网络,而是用于做误差分析。
具体来说,一方面比较训练-开发误差与开发误差,这两者的差值可以体现出训练集与开发集数据分布不一致的严重程度,差值越大,数据分布不一致就越严重。另一方面,比较训练误差与训练-开发误差,这两者的差值可理解为算法的方差,即体现出算法是否对训练集过拟合。
根据上图的指导,给出以下四组误差,我们便可以轻松地找到各自算法存在的问题在哪。
找到症结所在后,我们便可以对症下药。上面四组误差从上到下数字都保持增长,这不是绝对的。例如在智能语音后视镜的例子中: 也许人类水平性能为4%,训练集误差为7%,训练-开发集误差为10%,再往下时,你惊讶的发现,开发集和测试集的误差要小得多,也许都是6%. 下面是这个任务的数据集分布以及各个数据集的误差图示。
常规的语音识别任务包含的场景是很多的,而智能语音后视镜应用则是单一场景的语音识别任务,因此前者比后者更难以被机器学习算法学习。在打造智能语音后视镜的过程中,训练集和训练-开发集中包含的是样本是来自常规语音识别任务的话语片段,或者说大部分来自常规语音识别任务的话语片段,开发集和测试集则全是由来自语音识别后视镜应用的数据组成。自然算法在训练集与训练-开发集上的误差要比开发/测试集上的误差高。
2.3 解决由于数据不匹配带来的问题
3 从多个任务中学习
3.1 迁移学习、与训练、微调
迁移学习:把在一个任务中神经网络学习到的东西,应用到另一个任务中去。
例 1:假若你已经训练好了一个语音识别系统来输出对应的文字。 现在假设你想要构建一个“唤醒词” 或者一个“触发词”检测系统。 就像我们说“hey, Siri”来唤醒苹果设备。为了实现这些功能, 你可以同样去除神经网络的最后一层, 然后重新创建一层或几层,接着用你的多组唤醒词数据来重新训练网络的一层或多层。例2:你想构建一个诊断 X 光扫描图像的神经网络。但是苦于没有足够的数据(假如少于 1K),你训练好的网络性能不太令人满意。这时你可以尝试着让神经网络学习去识别大量(假如100K+)的猫,然后用学习到的部分参数来帮助你更好地诊断 X 光扫描图像的反映出的病情。
通过上面两例可以看到,迁移学习就是运用在一个任务中学习到的参数到另外一个任务,从而减少另一个任务的学习成本。总的来说,迁移学习的整个过程可以概括为:
Step1:构建用于第一个任务的神经网络,并将其训练至一个不错的性能;
Step2:移除掉网络最后一层(输出层)以及其相关的权重,根据新任务的标签创建新的一层并随机初始化这一层的权重;
Step3:根据新任务数据集的样本数量来重新训练神经网络的一层或多层参数;
Step4:使训练好的神经网络来处理第二个任务。
第1步过程中在猫分类图数据上的训练叫做预训练(pre-training)。第3步过程中在 X 光扫描图像的数据上的训练叫做微调(fine tuning) 。
关于迁移学习,有一些现成的经验:
- 如果你有一个小规模的数据集, 那么就去重新训练输出层的神经网络, 或者也可以训练最后一到两层的神经网络。 但是如果你有大量的数据, 你或许可以对这个神经网络的所有参数都进行重新训练。
- 若果重新训练的结果不佳,也可以回到第 2 步,移除最后一层后我们也可以尝试重新创建几层而不是一层,然后继续第 3 步和第 4 步。
预训练的作用:
拿例 2 来说,从从大规模的图像识别数据集中学习到的边界检测,曲线检测,明暗对象检测等低层次的信息, 或许能够帮助你的学习算法更好地去进行放射扫描结果的诊断。也就是说,当神经网络学会了图像识别,意味着它可能学习到了不同图片的 点,线,曲面等等信息在不同图片中看起来是什么样子的。
什么时候迁移学习是适用的呢?
如果你尝试从任务A中学习到的信息迁移到某个任务B中, 那么必须满足以下 4 个条件:
- 必须是任务 A 比任务 B 有更多的数据。
- 任务 A 和任务 B 在有相同的输入。
- 任务 A 中的低层次特征会帮助任务 B 达成目标。
- 任务 A 中的任务做好时。
3.2 多任务学习
什么是多任务学习:
迁移学习是从任务 A 中学习,然后将其迁移到任务 B,此过程是有先后顺序的。 我们也可以让多个任务一起开始,也就是尝试让一个神经网络同时做几件事,然后每个任务将会帮助完成其他任务,这就是多任务学习 。
例如:你正在建造一辆自动驾驶汽车。 然后你的车将需要检测几个不同的事物,如行人、其他车辆、停车标志、还有交通信号灯。如下图,在给出的
X
i
X^{{i}}
Xi 中,没有行人,有一辆车,有一个停车标志,没有红绿灯。那么对应的
Y
i
Y^{{i}}
Yi 有四个标签,分别为
[
0
,
1
,
1
,
0
]
T
[0,1,1,0]^T
[0,1,1,0]T。如果数据集包含
m
m
m 个样本,那么所有样本的标签
Y
Y
Y 是一个
4
∗
m
4*m
4∗m 的矩阵。
构建多任务学习模型:
你现在需要做的是训练一个神经网络来预测 y。 你可以有一个神经网络以 x 作为输入和 输出为四维的 y。 请注意输出层,应该有 4 个节点,第一个节点检测是否有行人,第二个输出是否检测到车辆,第三个输出是否检测到停车标志,第四个输出是否检测到交通信号灯。
训练多个完全独立的神经网络也可以实现同样的结果,但在多任务学习中,神经网络前面几层的权值对每个任务都是可以共享的,进而前面几层网络学习到的特征也是可以共享的。所以,训练一个神经网络做 4 件事的结果比训练 4 个完全独立的神经网络要省时省力得多。
为了训练这个神经网络,你需要定义这个神经网络的损失函数与代价函数:
这里的 L 是普通的逻辑斯蒂损失函数,与单任务分类相比,主要的区别是现在是将
j
j
j 从 0 到 3 相加,因为一个样本包含 4 个标签。还应将多任务学习与 softmax 多元分类区别开。softmax 多元分类是将单个标签分配给单个样本,输出的结果是图像是行人、汽车、停车标志、交通信号灯中的那一类。而在多任务学习中,一个样本包含多个样本,它输出的结果是图像中是否有行人、汽车、停车标志、交通信号灯。
那么什么时候进行多任务学习才有意义?
- 一是你要训练一系列的任务可以共享一些低层次的特征。在自动驾驶的例子中,在识别交通灯、汽车和行人时,都有相似的特征,这可以帮你识别停车标志,因为他们都是道路特征。
- 每个单项任务数据量大概相等。(不是硬性要求)假设 ,你通过多任务学习,在同一时间内试图识别 10 个类别。每个任务中你有1000个样本。对于当中的某个任务,如果训练一个单独的网络来完成这个任务,那么这个任务只有相对较少的 1000 个样本,在此基础上训练好的网络性能可能并不会令人满意。 而在多任务学习中,这 1 个任务与其他 99 个任务一起进行训练,则会增加 9.9 万个样本,这对当前的任务来说是一个很大的推动, 它们可以给很多的信息来增强。 同样地,其余99个任务也有同样的数据也能得到其他任务信息来帮助训练。
- 训练一个足够大的神经网络来使所有任务都有很好的表现。如果神经网络不够大,多任务学习的准确率可能比单项训练的准确率低一些。 但如果你训练足够大的神经网络,它实际上能够提高性能。
多任务学习与迁移学习:
在计算机视觉领域有很多多任务学习的应用,比如目标检测,一个神经网络可以同时检测到一大堆对象,这比多个不同的神经网络单独地检测物体好。实际上多任务学习要比迁移学习用得少得多,一般在你有大量任务要完成,你可以同时训练所有这些任务。 很多迁移学习的应用,通过一个小数量的数据来解决问题。 你首先找一个有大量数据的相关问题来学习,然后再转移到这个新的问题。