提升性能表现方法: a) 训练大型神经网络。 b) 利用更海量数据。 c) 优化神经网络架构及其他细节。
建立开发集和测试集
机器学习中通常定义: a) 训练集(Training set)用于运行学习算法。 b) 开发集(Dev set)用于调整参数,选择特征,对学习算法作出其它决定。有时也称为留出交叉验证集(hold-out cross validation set)。 c) 测试集(Test set)用于评估算法的性能,但不会据此改变学习算法或参数。
整合到一个表达式里(比如对多个误差指标取平均值或者加权平均值)是将多个指标合并为一个指标的最常用方法之一,例如将查准率(Precision,又译作精度)和查全率(Recall,又译作召回率)的调和平均数F1 score作为单值评估指标。
F
1
=
(
r
e
c
a
l
l
−
1
+
p
r
e
c
i
s
i
o
n
−
1
2
)
−
1
F_1 = \left(\frac{\mathrm{recall}^{-1} + \mathrm{precision}^{-1}}{2}\right)^{-1}
F1=(2recall−1+precision−1)−1 另一种方法是将某一种指标作为优化指标,其余指标作为“满意度指标”,要求算法在满意度指标满足一定的值或范围的情况下再去比较优化指标。
当开发集和评估指标对于团队已经不能提供一个正确的导向时,尽快修改它们: a) 如果算法在开发集上过拟合,则需要获取更多的开发集数据。 b) 如果开发集与测试集的数据分布和实际数据分布不同,则需要获取新的开发集和测试集。 c) 如果评估指标无法对最重要的任务目标进行度量,则需要修改评估指标。
简单处理方法: a) 高可避免偏差,加大模型的规模(例如通过添加层/神经元数量来增加神经网络的大小),风险是可能增加方差甚至过拟合。但若使用了 L2 正则化和 dropout 等正则化技术,并且设置了在开发集上表现最好的正则化参数,这种风险会降低,此时算力问题将会更凸显。 b) 高方差,增加训练集数据量,这种方法对于偏差没有明显影响,缺点是可能会遇到算力和数据获取问题。 c) 尝试新的模型架构,缺点是结果难以预测。
减少可避免偏差的技术: a) 加大模型规模(例如神经元/层的数量):这项技术能够使算法更好地拟合训练集,从而减少偏差。当你发现这样做会增大方差时,通过加入正则化可以抵消方差的增加。 b) 根据误差分析结果修改输入特征:假设误差分析结果鼓励你增加额外的特征,从而帮助算法消除某个特定类别的误差。这些新的特征对处理偏差和方差都有所帮助。理论上,添加更多的特征将增大方差;当这种情况发生时,你可以加入正则化来抵消方差的增加。 c) 减少或者去除正则化(L2 正则化,L1 正则化,dropout):这将减少可避免偏差,但会增大方差。 d) 修改模型架构(比如神经网络架构)使之更适用于你的问题:这将同时影响偏差和方差。
减少方差的技术: a) 添加更多的训练数据:这是最简单最可靠的一种处理方差的策略,只要你有大量的数据和对应的计算能力来处理他们。 b) 加入正则化(L2正则化,L1正则化,dropout):这项技术可以降低方差,但却增大了偏差。 c) 加入提前终止(例如根据开发集误差提前终止梯度下降):这项技术可以降低方差但却增大了偏差。提前终止(Early stopping)有点像正则化理论,一些学者认为它是正则化技术之一。 d) 通过特征选择减少输入特征的数量和种类:这种技术或许有助于解决方差问题,但也可能增加偏差。稍微减少特征的数量(比如从 1000 个特征减少到900个)也许不会对偏差产生很大的影响,但显著地减少它们(比如从1000个特征减少到100个,10倍地降低)则很有可能产生很大的影响,你也许排除了太多有用的特征。在现代深度学习研究过程中,当数据充足时,特征选择的比重需要做些调整,现在我们更可能将拥有的所有特征提供给算法,并让算法根据数据来确定哪些特征可以使用。而当你的训练集很小的时候,特征选择是非常有用的。 e) 减小模型规模(比如神经元/层的数量):谨慎使用。这种技术可以减少方差,同时可能增加偏差。然而我不推荐这种处理方差的方法,添加正则化通常能更好的提升分类性能。 f) 减少模型规模的好处是降低了计算成本,从而加快了你训练模型的速度。如果加速模型训练是有用的,那么无论如何都要考虑减少模型的规模。但如果你的目标是减少方差,且不关心计算成本,那么考虑添加正则化会更好。 g) 根据误差分析结果修改输入特征:假设误差分析的结果鼓励你创建额外的特征,从而帮助算法消除某个特定类别的误差。这些新的特征对处理偏差和方差都有所帮助。理论上,添加更多的特征将增大方差;当这种情况发生时,加入正则化,这可以消除方差的增加。 h) 修改模型架构(比如神经网络架构)使之更适用于你的问题:这项策略将同时影响偏差和方差。
如果你觉得额外数据的分布,与开发/测试集同分布数据的分布之间区别太大,或者额外数据的规模远远大于开发/测试集同分布数据的规模时,则有必要对数据加权重,以确保在有限计算资源下,算法在两种数据上都训练得很好(理论上在足够大的网络上训练足够久的情况下,并不需要这种处理)。在上面的例子中,如果优化目标是
min
θ
∑
(
x
,
y
)
∈
M
o
b
i
l
e
I
m
g
(
h
θ
(
x
)
−
y
)
2
+
∑
(
x
,
y
)
∈
I
n
t
e
r
n
e
t
I
m
g
(
h
θ
(
x
)
−
y
)
2
\min_{\theta}\sum_{(x,y)\in MobileImg}(h_{\theta}(x)-y)^2 +\sum_{(x,y)\in InternetImg}(h_{\theta}(x)-y)^2
θmin(x,y)∈MobileImg∑(hθ(x)−y)2+(x,y)∈InternetImg∑(hθ(x)−y)2可使用一个额外的权重参数
β
\beta
β改为
min
θ
∑
(
x
,
y
)
∈
M
o
b
i
l
e
I
m
g
(
h
θ
(
x
)
−
y
)
2
+
β
∑
(
x
,
y
)
∈
I
n
t
e
r
n
e
t
I
m
g
(
h
θ
(
x
)
−
y
)
2
\min_{\theta}\sum_{(x,y)\in MobileImg}(h_{\theta}(x)-y)^2 +\beta\sum_{(x,y)\in InternetImg}(h_{\theta}(x)-y)^2
θmin(x,y)∈MobileImg∑(hθ(x)−y)2+β(x,y)∈InternetImg∑(hθ(x)−y)2这个权重参数如设置为
β
=
1
40
\beta=\frac{1}{40}
β=401则这个算法会对 5000 个移动图像和 20 万个互联网图像给予同等的权重,也可以设置为其他值类似地对开发集进行调优。
在上述这种训练集含有与开发/测试集不同分布的数据的情况下,需要建立一个训练开发集(Training dev set),来帮助我们分辨高偏差问题及数据不匹配问题分别对算法造成的影响。具体来说,需要把原来的训练集抽取拆分出一个小子集不做实际训练,而作为训练开发集。它的数据自然来自与训练集相同的分布;它通常比训练集要小,只需要足够大到来评估和跟踪我们的学习算法的进展。如果开发集误差比训练开发集的误差相对大很多,则非常可能是出现了数据不匹配问题。
分析举例
算法编号
训练集错误率
开发集错误率
训练开发集错误率
最优错误率
可避免偏差
开发集方差
训练开发集方差
备注
1
1%
5%
5%
0%
1%
4%
4%
高方差低偏差:过拟合
2
10%
12%
11%
0%
10%
2%
1%
高偏差低方差:欠拟合
3
10%
20%
11%
0%
10%
10%
1%
高偏差数据不匹配
4
1%
10%
1.5%
0%
1%
9%
0.5%
数据不匹配
试图解决数据不匹配问题你需要: a) 通过误差分析尝试理解训练集分布和开发集分布之间数据属性之间的差异, b) 尝试获取更多与开发集出错样本性质有更好匹配性的训练数据,尤其是当你发现同样分布的那部分数据在测试集表现很好,而开发集很糟的时候。
优化验证测试(Optimization Verification test)是用于解决如下问题时使用的技术:给定输入
x
x
x,可以通过算法的目标(得分)函数
Score
x
(
y
)
\text{Score}_x (y)
Scorex(y)来获取标签
y
y
y的得分,但有时候没办法直接使用最大化函数
argmax
y
\text{argmax}_y
argmaxy精确找到最大得分对应的标签(例如搜索空间太大),而是采用近似搜索方法,这些方法不保证得到最大化得分标签。此时如何分析造成误差的原因是来自目标得分函数,还是近似搜索算法呢?
优化验证测试:假设
y
∗
y^*
y∗是“正确的”标签(即最大化得分的标签),但是算法输出了
y
o
u
t
y_{out}
yout。计算不等式
Score
x
(
y
∗
)
≥
Score
x
(
y
o
u
t
)
\text{Score}_x(y^*)\ge\text{Score}_x(y_{out})
Scorex(y∗)≥Scorex(yout)。如果该不等式成立,我们便可以将误差归咎于最大化近似搜索算法。否则,我们将误差归咎于目标函数
Score
x
(
y
)
\text{Score}_x (y)
Scorex(y)的计算方式。因此,优化验证测试能够反映改进学习算法与改进得分函数之间哪一个更具前途。
误差归因于流水线的特定组件的一般步骤: 假设在流水线中有三个步骤 A,B 和 C,其中 A 直接输出到 B,B直接输出到 C。对于系统在开发集上存在的每个错误样本,遵循 DAG(有向无环图) 顺序: a) 尝试人为修改 A 的输出为 “完美” 输出(例如,待检测目标的 “完美” 边界框),并在此输出上运行流水线其余的 B,C 部分。 如果算法现在给出了正确的输出,那么这表明,只要 A 给出了更好的输出,那么整个算法的输出就是正确的;因此,你可以将此误差归因于组件 A. 否则,请继续执行步骤 b)。 b) 尝试人为修改 B 的输出为 “完美” 输出。如果算法现在给出正确的输出,则将误差归因于组件 B。 否则,继续执行步骤 c)。 c) 将误差归因于组件 C。