打造实用的机器学习系统

应用机器学习算法的建议

这部分介绍如果改进机器学习系统性能的一些建议。

对一个线性回归模型,在得到学习参数后,如果要将假设函数放到一组新的房屋样本上测试。如果发现在预测房价时产生了巨大的误差,现在你的问题是要想改进这个算法,接下来应该怎么办?可能有如下办法:

  1. 一种办法是使用更多的训练样本
  2. 尝试选用更少的特征集
    • 如果你有一系列特征比如 x1,x2,x3 等等。也许可以从这些特征中仔细挑选一小部分来防止过拟合
  3. 尝试选用更多的特征
    • 也许目前的特征集,对你来讲并不是很有帮助
  4. 尝试增加多项式特征的方法
    • 比如 x1 的平方, x2 的平方, x1,x2 的乘积
  5. 减小正则化参数 λ 的值
  6. 增大正则化参数 λ 的值

不应该随机选择上面的某种方法来改进算法,而是运用一些机器学习诊断法来决定上面哪些方法对算法是有效的。

评估一个假设函数 Evaluating a Hypothesis

对于一个训练集,在计算算法的参数的时候,考虑的是选择参数以使训练误差(Cost function)最小化,有人认为得到一个非常小的训练误差一定是一件好事,但仅仅是因为这个假设具有很小的训练误差,并不能说明它是一个好的假设函数。尤其是考虑到过拟合的假设函数,所以这这个方法推广到新的训练集上是不适用的。

对于这个简单的例子,可以对假设函数 h(x) 进行画图,然后观察图形趋势,但对于特征变量不止一个的这种一般情况,还有像有很多特征变量的问题,想要通过画出假设函数来进行观察,就会变得很难甚至是不可能实现。

因此,需要另一种方法来评估假设函数过拟合检验。

为了检验算法是否过拟合,将数据分成训练集(Training set)和测试集(Test set),通常用70%的数据作为训练集,用剩下30%的数据作为测试集。

注意训练集和测试集均要含有各种类型的数据,通常要对数据进行“洗牌”(随机排序),然后再分成训练集和测试集。

测试集评估在通过训练集让模型学习得出其参数后,对测试集运用该模型,有两种方式计算误差:

  1. 对于线性回归模型,利用测试集数据计算代价函数 J:

  1. 对于逻辑回归模型:
    • 利用测试集数据计算代价函数 J

    • 计算对于每一个测试集样本的误分类的比率,然后求平均:

模型选择和交叉验证集 Model Selection

假设要在10个不同次数的二项式模型间选择:

显然越高次数的多项式模型越能够适应训练数据集,但也可能意味着过拟合(Overfitting),应该选择一个更能适应一般情况的模型。

这时需要使用交叉验证集(Cross-validation set)来帮助选择模型。​

模型选择方法:

  1. 使用训练集训练出10个模型
  2. 用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)
  3. 选取代价函数值最小的模型
  4. 用步骤3中选出的模型对测试集计算得出测试误差(代价函数的值)

训练误差(Training error):

交叉验证误差(Cross Validation error):

测试误差(Test error):

虽然现实中有人用测试集来计算交叉验证误差,并用同样的测试集来计算测试误差,但这并不是一个好的做法,除非有大量的训练数据.. Anyway,不推荐这种做法,还是将数据集分成训练数据、交叉验证数据和测试数据吧。

偏差(Bias)和方差(Variance)

如果一个机器学习算法表现不理想,多半出现两种情况:

例如下图,依次对应的是欠拟合、正常、过拟合:

为了分析模型性能,通常会将训练集和交叉验证集的代价函数误差与多项式的次数绘制在同一张图表上来帮助分析:

上图可看出:

根据上面的图表,还可以总结判断高方差、高偏差的方法:

正则化和偏差/方差

在训练模型时,一般会用正则化方法来防止过拟合。但是可能会正则化程度太高或太小,即在选择λ的值时也需要思考与此前选择多项式模型次数类似的问题。如下图是不同的 λ 对应不同拟合程度:

通常会尝试一系列的 λ 值,以测试最佳选择:

  1. 使用训练集训练出12个不同程度正则化的模型
  2. 用12个模型分别对交叉验证集计算的出交叉验证误差
  3. 选择得出交叉验证误差最小的模型
  4. 运用步骤3中选出模型对测试集计算得出推广误差

也可以同时将训练集和交叉验证集模型的代价函数误差与λ的值绘制在一张图表上(如下图),可以看出训练集误差和 λ 的关系如下:

总结:

学习曲线

学习曲线是用来判断某一个学习算法是否处于偏差、方差问题,它是学习算法的一个很好的合理检验sanity check)。

学习曲线是将训练集误差和交叉验证集误差作为训练集样本数量( m )的函数绘制的图表。

例如,如果有100行数据,从1行数据开始,逐渐学习更多行。 思想是:当训练较少数据时,训练模型将能非常完美地适应较少的训练数据,但是训练的模型不能很好地适应交叉验证集或测试集。

如何利用学习曲线识别高偏差/欠拟合

如何利用学习曲线识别高方差/过拟合

总结:决定下一步做什么

  1. 增加训练样本数 m ——解决高方差
  2. 减少特征的数量 n ——解决高方差
  3. 获得更多的特征 n ——解决高偏差
  4. 增加多项式特征 n ——解决高偏差
  5. 减少正则化程度 λ ——解决高偏差
  6. 增加正则化程度 λ ——解决高方差

神经网络的方差和偏差:

神经网络神经元个数选择:

神经网络隐藏层层数的选择:

机器学习系统设计

误差分析 Error Analysis

Andrew说他开始研究一个机器学习问题时,最多只会花一天的时间试图很快得出结果,即便效果不好。 也就是刚开始根本不用复杂的系统,只是很快的得到结果。即便运行的不完美,但也它运行一遍,最后通过交叉验证来检验数据。

之后通过画学习曲线,以及检验误差,找出算法是否有高偏差和高方差的问题,或者其他问题。 之后,再来决定用更多的数据训练,或者加入更多的特征变量是否有用。

这么做的原因: 在刚接触机器学习问题时,并不能提前知道是否需要复杂的特征变量,或者需要更多的数据,还是别的。 因为你缺少证据,缺少学习曲线。 因此,很难知道该如何提高算法性能。 但当你实践一个非常简单即便不完美的方法时,可以通过画出学习曲线来做出进一步的选择。 可以用这种方式避免类似电脑编程里的过早优化问题。

理念是:必须用证据来指引决策。 包括怎样分配自己的时间来优化算法,而不是仅仅凭直觉,而凭直觉一般都是错误的。 除了画出学习曲线之外,另外是做误差分析。

比如在构造垃圾邮件分类器时,会看一看交叉验证数据集,然后看看哪些邮件被算法错误地分类。 通过被算法错误分类的垃圾邮件与非垃圾邮件,可以发现某些系统性的规律:什么类型的邮件总是被错误分类。 经常地这样做之后,这个过程能启发你构造新的特征变量,或者告诉你:现在这个系统的短处,然后启发你如何去提高它。

构建一个学习算法的推荐方法为:

  1. 从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试这个算法
  2. 绘制学习曲线,决定是增加更多数据,或者添加更多特征,还是其他选择
  3. 进行误差分析:人工检查交叉验证集中算法中产生预测误差的样本,看看这些样本是否有某种系统化的趋势

以垃圾邮件过滤器为例:

误差分析并不总能帮助判断应该如何改进。有时需要尝试不同的模型,然后比较,在模型比较时,用数值来判断哪一个模型更好更有效,通常是看交叉验证集的误差。

因此,当在构造学习算法的时候,你会尝试很多新想法,实现很多版本的学习算法。 如果每一次实践新想法时,你都要手动地检测这些例子,去看是表现差还是表现好,那么这很难让你做出决定。到底是否使用词干提取,是否区分大小写。

但是通过一个量化的数值评估,你可以看这个数字,误差是变大还是变小了。你可以通过它更快地实践你的新想法,它基本上非常直观地告诉你:你的想法是提高了算法表现,还是让它变得更坏,这会提高实践算法的速度。 所以强烈推荐在交叉验证集上实施误差分析,而不是在测试集上。但是,还是有一些人会在测试集上来做误差分析。

总结一下:

类偏斜的误差度量

前面介绍了误差分析,以及设定误差度量值的重要性。有了算法的评估和误差度量值。还有一件重要的事情是使用一个合适的误差度量值,这有时会对于学习算法造成非常微妙的影响,这件重要的事情就是偏斜类(Skewed classes)的问题。类偏斜情况表现为训练集中有非常多的同一种类的样本,只有很少或没有其他类的样本。

例如希望用算法预测癌症是否是恶性的,在训练集中,只有0.5%的实例是恶性肿瘤。假设编写一个非学习算法,在所有情况下都预测肿瘤是良性的,那么误差只有0.5%。然而通过训练得到的神经网络算法却有1%的误差。这时,误差的大小是不能视为评判算法效果的依据的。

查准率Precision)和查全率Recall

将算法预测的结果分成四种情况:

  1. 正确肯定True Positive, TP):预测为真,实际为真
  2. 正确否定True Negative, TN):预测为假,实际为假
  3. 错误肯定False Positive, FP):预测为真,实际为假
  4. 错误否定False Negative, FN):预测为假,实际为真

查准率=TP/(TP+FP)

查全率=TP/(TP+FN)

这样,对于刚才那个总是预测病人肿瘤为良性的算法,其查全率是0。

可以对结果构建误差分析表格,也称作混淆矩阵(Confusion Matrix),如下:

    预测值  
    Positive Negtive
实际值 Positive TP FN
  Negtive FP TN

查准率和查全率之间的权衡

在分类问题中,会设定一个阈值( threshold ),当 hθ(x) ≥ gethreshold 时,预测输出1,否则输出0。

如何选择阀值:

原则是:选择得到更高 F1 值的阈值

机器学习的数据

有一项研究,尝试通过机器学习算法区分常见的易混淆的单词。研究者尝试了许多种不同的算法,并发现数据量非常大时,这些不同类型的算法效果都很好。

例子:

For breakfast I ate (to, two, too) eggs.

在这个例子中,(to, two, too) 是一个易混淆的单词子。于是研究员把诸如这样的机器学习问题,当做一类监督学习问题,并尝试将其分类,什么样的词,在一个英文句子特定的位置,才是合适的。

他们用了几种不同的学习算法,这些算法在(2001年进行的研究)当时都已经被公认是比较领先的:

什么时候会希望获得更多数据,而非修改算法? 他们改变训练数据集的大小,并尝试将这些算法用于不同大小训练集,结果如图:

图中趋势非常明显。

由于这项原始的研究非常具有影响力,因此已经系列不同的研究显示了类似的结果。 结果表明,许多不同的学习算法有时倾向于表现出非常相似的表现,但是真正能提高性能的,是能够给一个算法大量的训练数据。

像这样的结果,引起了一种在机器学习中的普遍共识:”取得成功的人不是拥有最好算法的人,而是拥有最多数据的人“。

那这种说法在什么时候是真,什么时候是假呢? 因为如果有一个学习算法,并且如果这种说法是真的,那么得到大量的数据通常是保证具有一个高性能算法的最佳方式,而不是去争辩应该用什么样的算法。

假如有这样一些假设,在这些假设下有大量认为有用的训练集,假设在机器学习问题中,特征值 x 包含了足够的信息,这些信息可以帮助准确地预测 y

来看一看,大量的数据有帮助的情况。

  1. 假设特征值有足够的信息来预测 y 值,假设使用一种需要大量参数的学习算法。
    • 比如有很多特征的逻辑回归或线性回归,或者用带有许多隐藏单元的神经网络。这些都是非常强大的学习算法,它们有很多参数,这些参数可以拟合非常复杂的函数。
    • 这些算法想象成低偏差算法,因为能够拟合非常复杂的函数,而且因为有非常强大的学习算法,这些学习算法能够拟合非常复杂的函数。很有可能,如果用这些数据运行这些算法,这种算法能很好地拟合训练集,因此,训练误差就会很低了。
  2. 现在假设使用了非常非常大的训练集,在这种情况下,尽管希望有很多参数,但是如果训练集比参数的数量还大,甚至是更多,那么这些算法就不太可能会过度拟合。也就是说训练误差有希望接近测试误差。

另一种考虑这个问题的角度是为了有一个高性能的学习算法,希望它不要有高的偏差和方差。

从根本上来说,这是一个关键的假设:

总结关键的检验标准:

如果都能得到肯定答案,那么你很可能可以得到一个性能很好的学习算法。

Jupyter Notebook编程练习

回到顶部