机器学习应用

ch01_cats.jpg

本文是机器学习工程应用相关的笔记。主要参考吴恩达《机器学习训练秘籍》。

References

机器学习训练秘籍吴恩达) 面向工程应用的指南

ch04_03.png

开发与测试

三分原则

  • 训练集(training set)用于运行你的学习算法。
  • 开发集(development set)用于调整参数,选择特征,以及对学习算法作出其它决定。有时也称为留出交叉验证集(hold-out cross validation set)
  • 测试集(test set)用于评估算法的性能,但不会据此改变学习算法或参数。

开发集和测试集的选择

  • 被选择作为开发集和测试集的数据,应当与你未来计划获取并对其进行良好处理的数据有着相同的分布,而不一定和训练集的数据分布一致
  • 开发集和测试集的分布应当尽可能一致
  • 为你的团队选择一个单值评估指标进行优化。当需要考虑多项目标时,不妨将它们整合到一个表达式里(比如对多个误差指标取平均),或者设定满意度指标和优化指标。
  • 机器学习是一个高度迭代的过程:在出现最终令人满意的方案之前,你可能要尝试很多想法
  • 拥有开发集、测试集和单值评估指标可以帮助你快速评估一个算法,从而加速迭代进程。
  • 当你要探索一个全新的应用时,尽可能在一周内建立你的开发集、测试集和评估指标;而在已经相对成熟的应用上,可以考虑花费更长的时间来执行这些工作。
  • 传统的 70% / 30% 训练集/测试集划分对于大规模数据并不适用,实际上,开发集和测试集的比例会远低于 30%.
  • 开发集的规模应当大到能够检测出算法精度的细微改变,但也不需要太大;测试集的规模应该大到能够使你能对系统的最终性能作出一个充分的估计
  • 当开发集和评估指标对于团队已经不能提供一个正确的导向时,尽快修改它们:
    • (i) 如果算法在开发集上过拟合,则需要获取更多的开发集数据。
    • (ii) 如果开发集与测试集的数据分布和实际数据分布不同,则需要获取新的开发集和测试集。
    • (iii) 如果评估指标无法对最重要的任务目标进行度量,则需要修改评估指标。

误差分析

误差分析并不会产生一个明确的数学公式来告诉你什么任务的优先级最高。你还需要考虑在不同类别上的预期进展以及解决每个类别所需的工作量。

必须要明确最严重的问题。分析Badcase

误标注清洗

当误标注样本占到整体比例的20%~30%时,可以认为对精度估计造成了显著的影响。

项目初始阶段容许一些误标注的开发集/测试集样本并不罕见,你可以选择在系统改进到一定程度时再来考虑被误标注的样本,因为这些误差在整体误差中的占比会逐渐增大

检查误分类样本更加容易。因为在高性能的模型中,其规模相对较小。

由于在实际操作中,检查误分类样本较为容易,这就导致了开发集会衍生出一定的偏差。如果你只对开发产品和应用感兴趣,如此程度的偏差是可以接受的。但如果你计划在学术论文中引用此结果,可能就需要完全无偏地度量测试集的精度,此时这样做就会出现问题。

开发集拆分

将开发集进一步拆分为:

  • Eyeball开发集(10%)
    • 进行人工误差分析
    • Eyeball 开发集应该大到能够让你对算法的主要错误类别有所察觉
    • 如果你正在处理一项,实际情况中人类也无法很好完成的任务,那么检查 Eyeball 开发集将不会有大的帮助,因为很难找出算法不能正确分类一个样本的原因。
  • Blackbox开发集(90%)
    • 对比,若产生Eyeball上的过拟合,则更新Eyeball

小结

  • 当你开始一个新项目,尤其是在一个你不擅长的领域开展项目时,很难正确预判出最有前景的方向。
  • 所以,不要在一开始就试图设计和构建一个完美的系统。相反,应尽可能快(例如在短短几天内)地构建和训练一个系统雏形。然后使用误差分析法去帮助你识别出最有前景的方向,并据此不断迭代改进你的算法。
  • 通过手动检查约 100 个被算法错误分类的开发集样本来执行误差分析,并计算主要的错误类别。使用这些信息来确定优先修正哪种类型的错误。
  • 考虑将开发集分为人为检查的 Eyeball 开发集和非人为检查的 Blackbox 开发集。如果在 Eyeball 开发集上的性能比在 Blackbox 开发集上好很多,说明你已过拟合 Eyeball 开发集,下一步应该考虑为其获取更多数据。
  • Eyeball 开发集应该足够大,以便于算法有足够多的错误分类样本供你分析。对大多数应用来说,含有1000-10000个样本的 Blackbox 开发集已足够。
  • 如果你的开发集不够大,无法按照这种方式进行拆分,那么就使用 Eyeball 开发集来执行人工误差分析、模型选择和调超参。

偏差和方差

假设你的算法在开发集上有 16% 的错误率(84% 精度),我们将这 16% 的错误率分为两部分:

  • 第一部分是算法在训练集上的错误率。在本例中,它是 15%。我们非正式地将它作为算法的偏差(bias)
    • 高偏差(high bias)$\longrightarrow$欠拟合(underfitting
  • 第二部分指的是算法在开发集(或测试集)上的表现比训练集上差多少。在本例中,开发集表现比训练集差 1%。我们非正式地将它作为算法的方差(variance)
    • 高方差(high variance)$\longrightarrow$过拟合(overfitting

粗略地说,偏差指的是算法在大型训练集上的错误率;方差指的是算法在测试集上的表现低于训练集的程度。当你使用均方误差(MSE)作为误差度量指标时,你可以写下偏差和方差对应的两个公式,并且证明总误差=偏差+方差。但在处理机器学习问题时,此处给出的偏差和方差的非正式定义已经足够。

完全可以同时发生过拟合和欠拟合。

一些学习算法的优化能解决误差来源的第一个部分——偏差,并且提高算法在训练集上的性能;而另一些优化能解决第二个部分——方差,并帮助算法从训练集到开发/测试集上更好地泛化。为了选择最有成效的改变方向,了解二者哪一方更需解决是很有用的。

还有一些方法能够对系统架构做出较大改变,同时减少偏差和方差。但是这些方法往往难以鉴定和实现。

建立对偏差和方差的良好直觉将帮助你为算法选择出有效的改进策略。

最优错误率

存在一个理想错误率,达到如此之低的错误率以后,我们不应该期望还能继续降低错误率。

假设你正在构建一个语音识别系统,并发现 14% 的音频片段背景噪声太多,或者十分难以理解,导致即使是人类也无法识别出所说的内容。在这种情况下,即使是“最优”的语音识别系统也可能约有 14% 的误差

假设在这个语音识别问题上,你的算法达到:

  • 训练错误率 = 15%
  • 开发错误率 = 30%

算法在训练集上的表现已经接近最优错误率 14%,因此在偏差上或者说在训练集表现上没有太大的提升空间。然而,算法没有很好地泛化到开发集上,在方差造成的误差上还有很大的提升空间。

对于最佳错误率远超零的状况,有一个对算法误差更详细的分解。继续使用上述语音识别的例子,可以将 30% 的总开发集误差分解如下(类似的分析可以应用于测试集误差):

  • 最优错误率(“不可避免偏差”):14%。假设我们决定,即使是世界上最好的语音系统,仍会有 14% 的误差。我们可以将其认为是学习算法的偏差“不可避免”的部分。
  • 可避免偏差:1%。即训练错误率和最优误差率之间的差值。
  • 方差:15%。即开发错误和训练错误之间的差值。

在统计学上,最优错误率也被称为贝叶斯错误率(Bayes error rate),或贝叶斯率。

处理措施

最简单的形式:

  • 如果具有较高的可避免偏差,那么加大模型的规模(例如通过添加层/神经元数量来增加神经网络的大小)。
    • 增加方差和过拟合的风险,但可以使用正则化技术来避免
  • 如果具有较高的方差,那么增加训练集的数据量
  • 采用不同的模型架构(例如不同的神经网络架构),获得不同的偏差/方差值。
    • 如果你选择了一个非常契合任务的模型架构,那么你也可以同时减少偏差和方差。
      • 只是选择这样的架构可能有点难度。

减少可避免偏差

如果你的学习算法存在着很高的可避免偏差,你可能会尝试以下方法:

  • 根据误差分析结果修改输入特征:假设误差分析结果鼓励你增加额外的特征,从而帮助算法消除某个特定类别的误差。(我们会在接下来的章节深入讨论这个话题。)这些新的特征对处理偏差和方差都有所帮助。理论上,添加更多的特征将增大方差;当这种情况发生时,你可以加入正则化来抵消方差的增加。
  • 减少或者去除正则化(L2 正则化,L1 正则化,dropout):这将减少可避免偏差,但会增大方差。
  • 修改模型架构(比如神经网络架构)使之更适用于你的问题:这将同时影响偏差和方差。
  • 加大模型规模(例如神经元/层的数量):这项技术能够使算法更好地拟合训练集,从而减少偏差。当你发现这样做会增大方差时,通过加入正则化可以抵消方差的增加。

减少方差

如果你的学习算法存在着高方差问题,可以考虑尝试下面的技术:

  • 根据误差分析结果修改输入特征:假设误差分析的结果鼓励你创建额外的特征,从而帮助算法消除某个特定类别的误差。这些新的特征对处理偏差和方差都有所帮助。理论上,添加更多的特征将增大方差;当这种情况发生时,加入正则化,这可以消除方差的增加。
  • 加入正则化(L2 正则化,L1 正则化,dropout):这项技术可以降低方差,但却增大了偏差。
    • 加入提前终止(例如根据开发集误差提前终止梯度下降):这项技术可以降低方差但却增大了偏差。提前终止(Early stopping)有点像正则化理论,一些学者认为它是正则化技术之一。
  • 通过特征选择减少输入特征的数量和种类:这种技术或许有助于解决方差问题,但也可能增加偏差。稍微减少特征的数量(比如从 1000 个特征减少到 900 个)也许不会对偏差产生很大的影响,但显著地减少它们(比如从 1000 个特征减少到 100 个,10 倍地降低)则很有可能产生很大的影响,你也许排除了太多有用的特征。在现代深度学习研究过程中,当数据充足时,特征选择的比重需要做些调整,现在我们更可能将拥有的所有特征提供给算法,并让算法根据数据来确定哪些特征可以使用。而当你的训练集很小的时候,特征选择是非常有用的。
  • 添加更多的训练数据:这是最简单最可靠的一种处理方差的策略,只要你有大量的数据和对应的计算能力来处理他们。
  • 减小模型规模(比如神经元/层的数量):谨慎使用。这种技术可以减少方差,同时可能增加偏差。然而我不推荐这种处理方差的方法,添加正则化通常能更好的提升分类性能。 减少模型规模的好处是降低了计算成本,从而加快了你训练模型的速度。如果加速模型训练是有用的,那么无论如何都要考虑减少模型的规模。但如果你的目标是减少方差,且不关心计算成本,那么考虑添加正则化会更好。
  • 修改模型架构(比如神经网络架构)使之更适用于你的问题:这项策略将同时影响偏差和方差。

正则化与特征选择

L1 Norm Regularization and Sparsity Explained for Dummies - Medium

【直观详解】什么是正则化

l1 相比于 l2 为什么容易获得稀疏解?

Sparsity and Some Basics of L1 Regularization

有约束转无约束,拉格朗日松弛观点下的L1正则化稀疏性探讨

A Closer Look at Sparse Regression Ryan Tibshirani … - CMU Statistics

Variable Selection LASSO: Sparse Regression - University of …

L2正则化和L1正则化。如下图:

正则化

目标函数(误差函数)就是求蓝圈+红圈的和的最小值(回想等高线的概念并参照3式),而这个值通在很多情况下是两个曲面相交的地方

L1正则化系数可以让原本较小的w分量为0,原本较大的w分量有限;让原本不太重要的输入不起作用了,让原本比较重要的输入的系数其作用的强度限制在有限值。

特殊要说明的是用L1正则化来降维和PCA降维是不同的,可以理解为L1正则化是用了数据的标签来做的,而PCA无需数据的标签。所以L1正则化实际上是带有监督学习性质的降维方法


“small , large problem”与Overfitting

n(数据量)$\ll$m(数据维度)的时候,从概率上来说,过拟合就无法避免了。(摘自《机器学习进阶》)

1547752453147

因为我们通常认为数据在维度上总是饱满的,这样而言,实界就极其庞大

正规方程

引例:(线性回归正规方程解法)

推导和拓展:(摘自《机器学习指南》)

  • 之前的偏导方程组写成向量形式为(矩阵求导

  • 注意:(当X可逆能推出)$X\theta=y$。

    • 也就是说,我们实际上是在尝试求解一个广义线性方程组。(普通线性方程组并不一定有惟一解,More
    • 在上述算法中求解条件弱化到只须$X^TX$可逆
      • 若我们考虑伪逆,则求解条件进一步弱化对任意的$X$,我们均能求得惟一解

什么时候会出现$X^TX$不可逆的现象

  • 冗余的特征(线性相关)
    • 比如仅单位不同:x1 = size in feet^2, x2 =size in m^2​。
  • 过多的特征,$m\leq n$(训练样本数甚至没有特征多)

拉格朗日松弛

如何理解拉格朗日松弛技术?

非凸转成凸、约束转无约-运筹学和支持向量机中的拉格朗日松弛法

注:如果深入研究,则需要一点凸优化的知识。不展开。

岭回归 Ridge Regression L2正则

等价于约束问题,

LASSO回归 L1正则

同理,

这样就解释了最开始的图的原理:

1553055522456

你可以想象一个带有棱角的正方形和球分别落向(较平坦的)地面,那么它们随机地与地面最先接触的那一部分,就是上图中的极值点。


深入

正交设计(orthonormal design):$\cfrac{1}{n}X^TX=I$。(实际上是要求特征之间相互正交)

正交设计已经预设了X阵是可逆的。可以通过对数据进行 PCA 以及模长 normalize 来实现。

通过正交设计,可以化简正规方程的解:(${\color{red}{w} }$是全局最优解

同时对Lasso回归有,

img

总结

场景 解决手段
高方差 样本++
高方差 特征数- -
高方差 正则因子 λ++
高偏差 特征数++
高偏差 正则因子 λ- -
高偏差 多项式次数++
高偏差 模型复杂度++

学习曲线

随着训练集数据量的增加:开发误差训练误差期望性能

ch29_01.jpg

解读学习曲线:高偏差

ch30_02.jpg

解读学习曲线:高方差

ch31_01.jpg

蓝色训练误差曲线相对较低,红色的开发误差曲线比蓝色训练误差高得多。因此,偏差很小,但方差很大。添加更多的训练数据可能有助于缩小开发误差和训练误差之间的差距。

解读学习曲线:高偏差+高方差

ch31_02.jpg

最后提一点,绘制一个学习曲线的成本可能非常高:例如,你可能需要训练 10 个模型,其中样本规模可以是 1000 个,然后是 2000 个,一直到
10000 个。使用小数据集训练模型比使用大型数据集要快得多。因此,你可以用 1000、2000、4000、6000 和 10000
个样本来训练模型,而不是像上面那样将训练集的大小均匀地间隔在一个线性的范围内。这仍然可以让你对学习曲线的变化趋势有一个清晰的认识。当然,这种技术只有在训练所有额外模型所需的计算成本很重要时才有意义。

与人类表现对比

有许多理由表明在处理人类擅长的任务时,构建一个机器学习系统会更加简单:

  1. 易于从人为标签中获取数据。举个例子,由于人类可以很好地识别图片中的猫,因此让人们为你的学习算法提供高精度的带标签数据也很方便。
  2. 基于人类直觉进行误差分析。假设某个语音识别系统的表现要低于人类的表现水平。比如错误地将音频片段 “This recipe calls for a pear of apples” 中的 “pair” 认为是 “pear”. 此时你可以利用人类的直觉来尝试理解,普通人会利用何种信息来获取正确的转录内容,并且试着修改你的学习算法,使它在相同的知识点上有着更好的表现。
  3. 使用人类表现水平来估计最优错误率,并设置可达到的“期望错误率”。 假设你的算法在某个任务上达到了 10% 的误差,但普通人所能达到的误差是 2% . 由此我们就可以知道最优错误率是 2% 或更低,这也表明可避免偏差至少是 8% . 所以你应当尝试一下降低偏差的技术。更一般地说,有一个合理可实现的“期望错误率”可以帮助你去估计学习算法的可避免偏差。这反过来也帮你决定是否使用误差降低技术。

连人类都不擅长的任务也是存在的。比如向你推荐一本书,或者在某个网站上选择向用户展示的广告,或者对股票市场进行预测。如今计算机在此类任务上的表现已经远超过人类。对于这些应用,我们主要面临着下面的问题:

  • 获取标签数据很难。 比如很难去获取用户数据库,并要求人工标记者使用“最优”的书籍标签对数据库进行注释,从而向用户推荐书籍。如果你正在负责一个书籍销售网站或者是 APP 的运营,你可以通过向用户展示书籍并查看他们的购买记录来获取数据。可当你没有这样一个网站时,就需要去找到一些更具创意的方法来获取数据了。
  • 人类的直觉难以依靠。例如,几乎没有人能准确地预测股票市场。因此当我们的股票预测算法比随机猜测的表现还要差时,很难弄清楚要如何去改进它。
  • 最优错误率和合理的期望错误率难以确定。假设你已经有了一个很好的图书推荐系统。如果没有人类水平作为参考,你怎么知道它还能改善多少呢?

资源管理

模型表示能力资源

https://accepteddoge.com/machine-learning-yearning-cn/docs/ch37/

添加额外的 20000 张图片会产生以下影响:

  1. 它给你的神经网络提供了更多关于猫咪外貌的样本。这是很有帮助的,因为互联网图片和用户上传的移动应用图片确实有一些相似之处。你的神经网络可以将从互联网图像中获得的一些知识应用到移动应用图像中。
  2. 迫使神经网络花费部分容量来学习网络图像的特定属性(比如更高的分辨率,不同画面结构图像的分布等等)。如果这些属性与移动应用图像有很大的不同,那么它将“耗尽”神经网络的一些表征能力,导致从移动应用图像的分布识别数据的能力就会降低,而这正是你真正关心的东西。从理论上讲,这可能会损害算法的性能。

数据计算资源

https://accepteddoge.com/machine-learning-yearning-cn/docs/ch39/

在实际操作中,拥有 40 倍的网络图像可能意味着,相比只使用 5000 张图片,你需要花费 40 倍(或更多)的计算资源来对两者进行建模。

如果你没有巨大的计算资源,你可以给互联网图片一个较低的权重作为妥协。

例如,假设优化目标是平方误差(对于分类任务来说这不是一个好的选择,但它将简化解释过程)。因此,我们的学习算法试图优化:

上面的第一个项是对 5000 个移动应用图像误差求和,第二项对 20 万个互联网图像误差求和。你可以使用一个额外的参数 𝛽 进行优化

如果你设置 𝛽 = 1/40,这个算法会对 5000 个移动图像和 20 万个互联网图像给予同等的权重。你还可以将参数 𝛽 设置为其他值,也可以类似地对开发集进行调优。

通过对额外的网络图像赋予更少的权重,你不需要构建一个庞大的神经网络来确保算法在这两种类型的任务上都能很好地完成。只有当你怀疑这些额外的数据(网络图像)与开发/测试集分布不一致,或者额外的数据规模比与相同分布的开发/测试集(手机图像)数据规模大得多时,这种类型的权重加权才需要

泛化能力资源

https://accepteddoge.com/machine-learning-yearning-cn/docs/ch40/

假设你正在将机器学习应用于不同分布的训练集和开发/测试集上。例如,训练集包含了互联网图像+移动应用图像,而开发/测试集只包含移动应用图像。然而,该算法运行得不太好:它的开发/测试集误差比想要的要高得多。以下是一些可能出现问题的情况:

  1. 它在训练集上表现不佳,这属于训练集分布上的高(可避免)偏差的问题。
  2. 它在训练集上做得很好,但是不能很好地泛化到与训练集分布相同的未知数据,这是高方差问题。
  3. 它能够很好地泛化到与训练集相同分布的未知数据,但不能很好地泛化到与开发/测试集相同分布的未知数据。我们将这种情况称之为数据不匹配(上下采样喵喵喵???),因为训练集的数据与开发/测试集的数据匹配得相当地糟糕。

例如,假设人类在猫识别任务上取得近乎完美的表现。你的算法实现了:

  • 1% 的训练集误差
  • 1.5% 的与训练集分布相同的未知数据上的误差
  • 10% 的开发集误差

在这种情况下,显然存在着数据不匹配问题。为了解决这个问题,你可能会尝试使训练数据更类似于开发/测试数据

为了诊断一个算法在上面 1 到 3 个问题受到了多大程度的影响,存在另一个数据集将是很有用的。具体地说,与其给算法提供所有可用的训练数据,你还可以把它分成两个子集:算法将进行训练的实际训练集,以及一个单独的集合,我们称之为“训练开发”集,我们将不会对它进行训练。

你现在有四个数据子集:

  • 训练集:这是算法将学习的数据(例如,互联网图像+移动应用图像)。这并不需要我们从与真正关心的相同分布(开发/测试集分布)的数据中提取。
  • 训练开发集:这些数据来自与训练集相同的分布(例如,互联网图像+移动应用图像)。它通常比训练集要小;它只需要足够大到来评估和跟踪我们的学习算法的进展。
  • 开发集:这是从与测试集相同分布的数据中抽取出来的,它反映了我们最终关心的数据的分布(例如,移动应用图像) 。
  • 测试集:这是从与开发集相同分布的数据中抽取出来的(例如,移动应用图像)。

有了这四个独立的数据集,你现在可以评估:

  • 训练误差,对训练集进行评估。
  • 该算法能够泛化到与训练集相同分布数据的能力,并对训练开发集进行评估。
  • 算法在你实际关心的任务上的性能,通过对开发集 和/或 测试集评估。

数据合成

你的语音系统需要更多的数据,它们听起来就像是从车里录制得到的。与其在开车的时候收集大量的数据,不如通过人工合成数据来获取这些数据。

假设你获得了大量的汽车/道路噪音的音频剪辑。你可以从几个网站下载这些数据。假设你也有一群在安静的房间里说话的人。如果你把一个人的音频片段“添加”到一个汽车/道路噪音的音频片段,你会得到一个音频剪辑,听起来就好像那个人在嘈杂的汽车里说话一样。使用这个过程,你可以“合成”大量的数据,听起来就像是在汽车里收集的。

请记住,人工数据合成存在一定的挑战:有时候创建一个对人而言真实的合成数据比创建对计算机而言真实的数据要容易得多。例如,假设你有 1000 小时的语音训练数据,但只有 1 小时的汽车噪音。如果你反复使用相同的 1 小时的汽车噪音,从最初的 1000 小时的训练数据中,你将会得到一个合成的数据集,然而同样的汽车噪音会不断重复。听这段音频的人可能无法分辨——所有的汽车噪音对我们大多数人来说都是一样的——但是某种学习算法可能会“过拟合”一小时的汽车噪音。因此,它可能无法很好地泛化到一个新的音频剪辑片段,里面汽车的噪音听起来是不同的。

算法验证测试

优化验证测试

https://accepteddoge.com/machine-learning-yearning-cn/docs/ch44/

假设有一个音频片段记录着某人说的:“我爱机器学习。”但你的系统输出的却是不正确的 “我爱机器人。”,它没能够输出正确的转录。造成该误差的可能原因有两种:

  1. 搜索算法存在问题。 近似搜索算法没能够找到最大化 Score(S) 的那个 S .
  2. 目标(得分函数)存在问题。 我们对 Score(S) = P(S|A) 的估计并不准确。尤其在此例中,我们的得分函数没能辨认出 “我爱机器学习” 是正确的转录。

对应不同的失败原因,你需要优先考虑的工作方向也将很不一样。如果原因 1 导致了问题,你应该改进搜索算法。如果原因 2 导致了问题,你应该在评估学习算法的函数上面多花些心思。

1553746821819

端到端学习

组件误差分析

0%