第6周


十一、应用机器学习的建议

11.1 决定下一步做什么

机器学习方法很多,一些人没有完全理解怎样运用这些算法,因此总是把时间浪费在毫无意义的尝试上。接下来学习怎样选择一条最合适、最正确的道路,将重点关注的问题是假如在开发一个机器学习系统,或者想试着改进一个机器学习系统的性能,应如何决定接下来应该选择哪条道路?

为了解释这一问题,仍然使用预测房价的学习例子,假如已经完成线性回归模型训练,如果发现在预测房价时产生了巨大的误差,现在如何改进这个算法?有很多方法可以选择

  1. 获得更多的训练样本——通常是有效的,但代价较大,下面的方法也可能有效,可考虑先采用下面的几种方法。

  2. 尝试减少特征的数量

  3. 尝试获得更多的特征

  4. 尝试增加多项式特征

  5. 尝试减少正则化程度 λ \lambda λ

  6. 尝试增加正则化程度 λ \lambda λ

大多数人的选择方法是随便从这些方法中选择一种,而在很长时间后遗憾地发现自己选择的是一条不归路。幸运的是,有一系列简单的方法能事半功倍,排除掉单子上的至少一半的方法,从而为你节省大量不必要花费的时间。我们下一步可以做什么?

运用一些机器学习诊断法来帮助我们知道上面哪些方法对算法是有效的。

11.2 评估一个假设

在这里插入图片描述

有人认为得到一个非常小的训练误差一定是一件好事,但学习了过拟合假设函数的例子,这推广到新的训练集上是不适用的。

那么,如何判断一个假设函数是过拟合的呢?为了检验算法是否过拟合,将数据分成训练集和测试集,通常用70%的数据作为训练集,用剩下30%的数据作为测试集。很重要的一点是训练集和测试集均要含有各种类型的数据,通常先对数据进行“洗牌”,然后再分成训练集和测试集。

在这里插入图片描述

测试集评估在通过训练集让我们的模型学习得出其参数后,对测试集运用该模型,计算误差。

11.3 模型选择和交叉验证集

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

在这里插入图片描述

显然越高次数的多项式模型越能够适应我们的训练数据集,但是适应训练数据集并不代表着能推广至一般情况,我们应该选择一个更能适应一般情况的模型。这时需要使用交叉验证集来帮助选择模型。

即:使用60%的数据作为训练集,使用 20%的数据作为交叉验证集,使用20%的数据作为测试集

在这里插入图片描述

模型选择的方法为:

  1. 使用训练集训练出10个模型

  2. 用10个模型分别对交叉验证集计算得出交叉验证误差(代价函数的值)

  3. 选取代价函数值最小的模型

  4. 用步骤3中选出的模型对测试集计算得出推广误差(代价函数的值)

    Train/validation/test error

    Training error:

J t r a i n ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J_{train}(\theta) = \frac{1}{2m}\sum\limits_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})^2 Jtrain​(θ)=2m1​i=1∑m​(hθ​(x(i))−y(i))2

Cross Validation error:

J c v ( θ ) = 1 2 m c v ∑ i = 1 m ( h θ ( x c v ( i ) ) − y c v ( i ) ) 2 J_{cv}(\theta) = \frac{1}{2m_{cv}}\sum\limits_{i=1}^{m}(h_{\theta}(x^{(i)}_{cv})-y^{(i)}_{cv})^2 Jcv​(θ)=2mcv​1​i=1∑m​(hθ​(xcv(i)​)−ycv(i)​)2

Test error:

J t e s t ( θ ) = 1 2 m t e s t ∑ i = 1 m t e s t ( h θ ( x c v ( i ) ) − y c v ( i ) ) 2 J_{test}(\theta)=\frac{1}{2m_{test}}\sum\limits_{i=1}^{m_{test}}(h_{\theta}(x^{(i)}_{cv})-y^{(i)}_{cv})^2 Jtest​(θ)=2mtest​1​i=1∑mtest​​(hθ​(xcv(i)​)−ycv(i)​)2

11.4 诊断偏差和方差

当运行一个学习算法时,如果这个算法的表现不理想,那么多半是出现两种情况:要么是欠拟合,要么是过拟合问题。那么这两种情况,哪个和偏差有关,哪个和方差有关,或者是不是和两个都有关?搞清楚这一点非常重要,因为能判断出现的情况是这两种情况中的哪一种。

在这里插入图片描述

我们通常会通过将训练集和交叉验证集的代价函数误差与多项式的次数绘制在同一张图表上来帮助分析:

在这里插入图片描述

Bias/variance

Training error: J t r a i n ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J_{train}(\theta) = \frac{1}{2m}\sum\limits_{i=1}^{m}(h_{\theta}(x^{(i)})-y^{(i)})^2 Jtrain​(θ)=2m1​i=1∑m​(hθ​(x(i))−y(i))2

Cross Validation error: J c v ( θ ) = 1 2 m c v ∑ i = 1 m ( h θ ( x c v ( i ) ) − y c v ( i ) ) 2 J_{cv}(\theta) = \frac{1}{2m_{cv}}\sum\limits_{i=1}^{m}(h_{\theta}(x^{(i)}_{cv})-y^{(i)}_{cv})^2 Jcv​(θ)=2mcv​1​i=1∑m​(hθ​(xcv(i)​)−ycv(i)​)2

在这里插入图片描述

对于训练集,当 d d d 较小时,模型拟合程度更低,误差较大;随着 d d d 的增长,拟合程度提高,误差减小。

对于交叉验证集,当 d d d 较小时,模型拟合程度低,误差较大;但是随着 d d d 的增长,误差呈现先减小后增大的趋势,转折点是我们的模型开始过拟合训练数据集的时候。

如果交叉验证集误差较大,如何判断是方差还是偏差呢?根据上面的图表,我们知道:

在这里插入图片描述

训练集误差和交叉验证集误差近似时:偏差/欠拟合

交叉验证集误差远大于训练集误差时:方差/过拟合

偏差是指模型预测值的期望与真实值之间的差距,反映了模型对训练数据的拟合能力。偏差大的模型通常过于简单,无法很好地捕捉数据的复杂模式,容易导致欠拟合。

方差是指模型预测值的变化范围,反映了模型对不同训练数据集的敏感程度。方差大的模型通常过于复杂,对训练数据的扰动非常敏感,容易导致过拟合。

11.5 正则化和偏差/方差

在训练模型的过程中,一般使用一些正则化方法来防止过拟合。但是可能会正则化的程度太高或太小了,即在选择λ的值时也需要思考与刚才选择多项式模型次数类似的问题。

在这里插入图片描述

我们选择一系列的想要测试的 λ \lambda λ 值,通常是 0-10之间的呈现2倍关系的值(如: 0 , 0.01 , 0.02 , 0.04 , 0.08 , 0.15 , 0.32 , 0.64 , 1.28 , 2.56 , 5.12 , 10 0,0.01,0.02,0.04,0.08,0.15,0.32,0.64,1.28,2.56,5.12,10 0,0.01,0.02,0.04,0.08,0.15,0.32,0.64,1.28,2.56,5.12,10共12个),同样把数据分为训练集、交叉验证集和测试集。

在这里插入图片描述

选择 λ \lambda λ的方法为:

  1. 使用训练集训练出12个不同程度正则化的模型
  2. 用12个模型分别对交叉验证集计算的出交叉验证误差
  3. 选择得出交叉验证误差最小的模型
  4. 运用步骤3中选出模型对测试集计算得出推广误差,也可以同时将训练集和交叉验证集模型的代价函数误差与λ的值绘制在一张图表上:

在这里插入图片描述

• 当 λ \lambda λ 较小时,训练集误差较小(过拟合)而交叉验证集误差较大

• 随着 λ \lambda λ 的增加,训练集误差不断增加(欠拟合),而交叉验证集误差则是先减小后增加

11.6 学习曲线

学习曲线是一种很好的工具来判断某一个学习算法是否处于偏差、方差问题。学习曲线是将训练集误差和交叉验证集误差作为训练集样本数量( m m m)的函数绘制的图表。

在这里插入图片描述
在这里插入图片描述

如何利用学习曲线识别高偏差/欠拟合:作为例子,尝试用一条直线来适应下面的数据,可以看出,无论训练集有多么大误差都不会有太大改观:

在这里插入图片描述

也就是说在高偏差/欠拟合的情况下,增加数据到训练集不一定能有帮助。

如何利用学习曲线识别高方差/过拟合:假设使用一个非常高次的多项式模型,并且正则化非常小,可以看出,当交叉验证集误差远大于训练集误差时,往训练集增加更多数据可以提高模型的效果。

在这里插入图片描述

也就是说在高方差/过拟合的情况下,增加更多数据到训练集可能可以提高算法效果。

11.7 决定下一步做什么

回顾 11.1 中提出的六种可选的下一步,来看一看在什么情况下应该怎样选择:

  1. 获得更多的训练样本——解决高方差(过拟合)

  2. 尝试减少特征的数量——解决高方差(过拟合)

  3. 尝试获得更多的特征——解决高偏差(欠拟合)

  4. 尝试增加多项式特征——解决高偏差(欠拟合)

  5. 尝试减少正则化程度λ——解决高偏差(欠拟合)

  6. 尝试增加正则化程度λ——解决高方差(过拟合)

神经网络的方差和偏差:
在这里插入图片描述

使用较小的神经网络,类似于参数较少的情况,容易导致高偏差和欠拟合,但计算代价较小。使用较大的神经网络,类似于参数较多的情况,容易导致高方差和过拟合,虽然计算代价比较大,但是可以通过正则化手段来调整而更加适应数据。

通常选择较大的神经网络并采用正则化处理会比采用较小的神经网络效果要好。

对于神经网络中的隐藏层的层数的选择,通常从一层开始逐渐增加层数,为了更好地作选择,可以把数据分为训练集、交叉验证集和测试集,针对不同隐藏层层数的神经网络训练神经网络,
然后选择交叉验证集代价最小的神经网络。

十二、机器学习系统的设计(Machine Learning System Design)

12.1 首先要做什么

在设计复杂的机器学习系统时,将遇到很多问题。以一个垃圾邮件分类器算法为例进行讨论。为了构建这个分类器算法,可以做很多事,例如:

  1. 收集更多的数据,有更多的垃圾邮件和非垃圾邮件的样本

  2. 基于邮件的路由信息开发一系列复杂的特征

  3. 基于邮件的正文信息开发一系列复杂的特征,包括考虑截词的处理

  4. 为探测刻意的拼写错误(把watch 写成w4tch)开发复杂的算法

在上面这些选项中,非常难决定应该在哪一项上花费时间和精力,作出明智的选择,比随着感觉走要更好。

12.2 误差分析

构造机器学习应用程序,最好的实践方法不是建立一个非常复杂的系统,拥有多么复杂的变量;而是构建一个简单的算法,可以很快地实现它。

  1. 从一个简单的能快速实现的算法开始,实现该算法并用交叉验证集数据测试这个算法

  2. 绘制学习曲线,决定是增加更多数据,或者添加更多特征,还是其他选择

  3. 进行误差分析:人工检查交叉验证集中我们算法中产生预测误差的样本,看看这些样本是否有某种系统化的趋势

以垃圾邮件过滤器为例,误差分析要做的既是检验交叉验证集中算法产生错误预测的所有邮件,看:是否能将这些邮件按照类分组。例如医药品垃圾邮件,仿冒品垃圾邮件或者密码窃取邮件等。然后看分类器对哪一组邮件的预测误差最大,并着手优化。

​
思考怎样能改进分类器。例如,发现是否缺少某些特征,记下这些特征出现的次数。记录下错误拼写出现了多少次,异常的邮件路由情况出现了多少次等等,然后从出现次数最多的情况开始着手优化。
​
误差分析并不总能帮助我们判断应该采取怎样的行动。有时需要尝试不同的模型,然后进行比较,在模型比较时,用数值来判断哪一个模型更好更有效,通常看交叉验证集的误差。
​
强烈推荐在交叉验证集上来实施误差分析,而不是在测试集上。

12.3 分类问题评估

这是week4第七章的内容。

  1. True Positive,TP:预测为真,实际为真

  2. True Negative,TN:预测为假,实际为假

  3. False Positive,FP:预测为真,实际为假

  4. False Negative,FN:预测为假,实际为真

预测值
PositiveNegtive
实际值PositiveTPFN
NegtiveFPTN

12.5 机器学习的数据

下面探讨什么时候希望获得更多数据,而非修改算法。下图改变了训练数据集的大小,并尝试将各种学习算法用于不同大小的训练数据集中

在这里插入图片描述

这些趋势非常明显,首先大部分算法都具有相似的性能,其次,随着训练数据集的增大,在横轴上代表以百万为单位的训练集大小,从0.1个百万到1000百万,也就是到了10亿规模的训练集的样本,这些算法的性能也都对应地增强了。

事实上,如果选择任意一个算法,可能是一个"劣等的"算法,但是如果给这个劣等算法更多的数据,它看上去很有可能会比其他算法更好,甚至会比"优等算法"更好。像这样的结果,引起了一种在机器学习中的普遍共识:“取得成功的人不是拥有最好算法的人,而是拥有最多数据的人”。

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

首先,一个人类专家看到了特征值 x x x,能很有信心的预测出 y y y值吗?因为这可以证明 y y y 可以根据特征值 x x x被准确地预测出来,特征是有用的。其次,我们实际上能得到一组庞大的训练集,并且在这个训练集中训练一个有很多参数的学习算法吗?参数增加可以保证模型拟合的更好,同时大量数据多于参数量又能避免过拟合。如果你不能做到这两者,那么更多时候,会去选择一个性能很好的学习算法。

事实上,如果有大量的数据,而且训练了一种带有很多参数的学习算法,那么这将会是一个很好的方式来提供一个高性能的学习算法。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐