Advice for Applying Machine Learning

 

我这里想做的是,确保大家在设计机器学习系统时,能够明白怎样选择一条最合适、最正确的路径。因此,接下来我们要讨论一些实用的建议和指导,帮助大家明白怎样进行选择。

具体来说,我们将重点关注的问题是,加入我们正在开发一个机器学习系统,或者想试着改进一个机器学习系统的性能,我们应该如何决定接下来应该要做的事情。

 

Evaluating a Learning Algorithm[评估一个学习算法]

Deciding What to Try Next[决定下一步]

为了解释这种情况,让我们继续关注预测房价的线性回归的例子。

假如,我们已经完成了正则化的线性回归,也就是最小化代价函数J。再假设,当我们学习得到了模型参数以后,如果我们将对应的假设函数应用到一组新的房子样本上时,假设出现了超级大的、难以接受的误差。那么我们就需要改进算法,但改进算法我们接下来应该要做些什么呢?

为了提高算法的性能,实际上有非常多的可以做的事情。其中一种办法是,使用更多的训练样本,具体来说,比如你可以通过编写爬虫从互联网上抓取更多的样本,甚至电话调查或者上门调查。但是遗憾的是,在实际中,有很多人耗费了非常多的时间想收集更多的训练样本,他们总是认为,如果我有更多的训练样本,比如两倍甚至十倍的训练样本,那就一定会解决问题,是吧。但是有的时候,获取更多的训练样本实际上却并没有什么作用。在接下来的内容中我们将会说明为什么会出现这种情况。我们也将会了解到,怎样避免把过多的时间浪费在收集更多的训练数据上,这实际上是无济于事的。

另一种可能的办法是,尝试使用更少的特征,因此如果我们有很多特征,比如x1, x2, x3等等,我们可以非常小心细致地挑选一些特征来做训练,并期望能够防止过拟合。

或者也有可能我们需要更多的特征,也许目前的特征集合对我们的问题而言并不是很有用。我们希望从获取更多特征的角度,来收集更多的数据。同样的,我们可以把这个问题扩展为一个很大的项目,如果抓取不能够解决更多特征的需求,那么可能就需要电话调查甚至实地勘察。这种情况可能会带来非常昂贵的代价,但并不是说不能做,只是前提在于我们希望提前预知这么做确实对改进算法有帮助,而且最好能够评估出帮助到底有多大。

另外,我们还可以增加多项式项特征,比如x1^2,x2^2,x1x2等等。我们可以花很多时间来思考究竟应该增加哪些多项式项。

当然,我们也可以考虑其他类似减小λ,增大λ这样的办法。

我们列出的这个清单,其中任何一项可能在实际中都会扩展成一个半年或者更长时间的项目。但是遗憾的是,很多人用来选择这些方法的标准是凭感觉,也就是说很多人的选择方法是,随机从这些方法中选择一种。比如说,他们会说,“好吧,我们来多找点数据吧“,然后花上半年时间,不管是抓取也好,还是其他方法也好,收集了一大堆的数据。然后也许另一个人会说,”也许我们应该寻找更多的特征来描述样本“。但是,确实有很多人花了一个季度、半年的时间来完成他们随便选择的一种方法,然而在半年或者更长的时间后,他们很不幸地发现自己选择的是一条错误的路。

不过幸运的是,有一系列简单的方法能让我们事半功倍,可以排除掉这个清单上的至少一半的方法,留下那些实际上大概率会有帮助的方法。同时,也有一种很简单的方法,只要我们运行,就可以很轻松地排除掉很多选择。从而为我们节省大量不必要花费的时间。

所以,在接下来的课程中,我们将讨论怎样评估机器学习算法的性能,以及怎样对机器学习算法进行诊断。

机器学习算法的诊断,我们指的是,一种测试方法,我们可以通过使用这些测试,能够深入了解学习算法到底是否正常工作,而且通常也能告诉我们,要想改进算法的效果,怎样的尝试能够最大概率地提升算法的性能。我们接下来会具体地介绍一系列的诊断方法,不过我们提前说一下,这些诊断的执行和实现,是需要额外花些时间的,有时候可能需要花费不少时间,不过这样做我觉得还是值得的,因为通过它我们可以确认我们把时间花在了刀刃上,因为这些测试可以帮助我们切实地了解学习算法的状态,帮助我们有的放矢地进行下一步调优,避免耗费数月时间在不必要的工作上。

 

Evaluating a Hypothesis[评估一个假设]

 

现在让我们来讨论下,如何评估一个假设函数。这也是后面我们讨论如何解决过拟合和欠拟合问题的基础。

当我们确定学习算法的参数时,我们的目标是选择参数来使训练误差最小化。有人认为,得到一个非常小的训练误差一定是一件好事。但我们已经知道,仅仅是因为这个假设具有很小的训练误差,并不能说明它一定是一个好的假设。我们也学习了过拟合的例子。这时,推广到新的样本上就不那么有效了。那么我们怎样才能判断一个假设函数是否过拟合了呢?

对于这个简单的例子,我们可以画出假设函数hθx,然后观察是否可能存在过拟合。但对于更加一般的情况,特征很可能不止一个,就像我们房子的特征其实就会有非常多。在这种情况下,想通过画出假设函数的图形来人为观察,就变得很难甚至是不可能的了。因此,我们需要另一种评估假设函数的方法。

这里我们介绍一种评估假设函数的标准方法。

假设我们有这样一组数据,在这里我们只展示了20组训练样本,当然我们通常可以有成百上千组训练样本。为了确保我们可以评价我们的假设函数,我们要做的是,将这些数据分成两部分,第一部分就是我们的训练集,第二部分就是我们的测试集。一种典型地划分方法是,按照大约7:3的比例切分,将70%的数据作为训练集,另外30%的数据作为测试集。

因此,现在如果我们有某个数据集,我们只用其中的70%作为我们的训练集,而剩下的那部分数据将被用作测试集,对于测试集,我们使用m下标test来表示测试样本的总数。 因此,所有的下标test表示样本来自测试集。

最后,还有一个细节是,在这里我们选择了前70%的数据作为训练集,后30%的数据作为测试集,但如果这组数据具有某种规律或者顺序的话,那么最好是,随机选择70%作为训练集,剩下的30%作为测试集。当然了,如果我们的数据已经是随机分布的了,那么我们就可以直接选择前70%的数据作为训练集,剩下的30%作为测试集。但是如果数据不是随机排列的,那么最好还是先打乱下顺序,然后再分别取70%和30%作为训练集和测试集。

接下来,这里展示了一种典型的方法,我们可以按照这些步骤训练和测试学习算法。比如线性回归算法。

首先,我们需要对训练集进行学习,以得到参数θ。所以具体而言,我们就是最小化训练误差J(θ),而这里的J(θ)是使用那70%的数据计算的,也就是仅仅使用训练集。

接下来,我们需要计算出测试误差,我们将用J下标test来表示测试误差。那么我们要做的就是使用在训练集上学习到的模型参数θ,然后用它来在测试集的数据上计算J,这样就可以得到测试误差。这实际上就是测试集中样本的均方误差。

当然,这只是当我们使用线性回归和均方误差时的测试误差。

那么,如果是分类问题呢?比如说如果我们在使用的是逻辑回归呢? 

 

当我们使用逻辑回归时,与之前所说的非常相似。

首先,我们要从训练集也就是所有数据的70%的数据中学习得到模型的参数θ。然后用如下的计算方式计算得到测试误差。这和我们一直做的逻辑回归的目标函数是一样的。唯一的区别在于,我们现在用的数据是m test个测试样本。这里的测试误差J test θ,其实并不难理解。不过还有另一种指标对于分类问题而言更加容易理解,那就是错分率,有时它也被称为0/1错分率。其中0/1表示我们预测的正确或错误样本的情况。具体地讲,可以这样定义一次预测的误差,当y=0且h θ x>=0.5时,误差是1. 或者y=1且h θ x<0.5时,误差也是1. 这两种情况其实都是分类错误的情况。否则的话,我们定义误差为0. 这种时候,我们的假设函数能够正确地对样本进行分类。

Model Selection and Train/Validation/Test Sets[模型选择和训练、验证、测试集]

我们假设一种情况,就是我们需要决定使用怎样的多项式项来拟合数据。其实也就是我们怎样选用合适的特征来构造学习算法。或者假如我们需要使用λ来控制正则化的程度,我们有应该怎么调节它呢?

这些问题实际上被称为模型选择问题。在我们对于这些问题的讨论中,我们将不仅仅讨论把数据集切分成训练集、测试集,而且会讨论将数据集再划分出一个被称为”验证集”的集合。基于此,我们会讨论如何利用它进行模型选择。

在前面的学习中,我们已经多次接触到过拟合现象,它指的是学习算法对训练集的数据拟合的很好,但这并不能表明得到的假设函数是完美的。更一般的说,训练集上的误差对于衡量一个学习算法而言,并不是一个很好的指标。具体而言,如果我们学习得到了模型参数,比如θ0, θ1, θ2等,它们很好的拟合了训练集中的数据,但这并不意味着这些参数定义的假设函数可以在新的、未见过的样本上也能有同样好的拟合效果。而更加普遍的规律是,只要我们的参数非常拟合某个数据集,那么基于同样这个数据集的误差往往并不是一个好的,对泛化误差的估计。也就是说,这个误差并不能表达模型对于未见过样本的拟合能力。

现在,我们来考虑模型选择问题。假设,现在我们试图选择多项式项的度以便得到一个最优的模型。换句话说,我们应该选择一次函数,二次函数还是三次函数等等,一直到十次函数呢?所以,似乎在算法里应该有这样一个参数,这里我们使用d来表示我们应该选择的多项式的度。所以,它就像是对θ参数的补充,它是额外的一个参数,是需要我们基于数据集确定的另一个参数。

所以,第一种选择就是d等于1,也就是表示线性方程。我们也可以选择d=2或者d=3等等,一直到d=10. 因此,我们想确定这个多出来的参数d最适当的取值应该是多少。具体地说,比如说我们想要选择一个模型,那就是,从这10个模型中选择一个最适当的多项式次数(度),并且用这个模型进行估计,我们的假设函数是否能很好地推广到新的样本上。那么我们可以这样做,首先我们使用第一个模型,然后力求最小化训练误差,这样我们就会得到一个参数向量θ。然后再选择第二个模型,二次函数模型,进行同样的过程,这样我们就会得到另一个参数向量θ。为了区别这些不同的参数向量θ,我们可以使用上标(1),上标(2)等来进行区分。比如,θ上标(1)表示的是我们是使用[第一个式子下划线]这个模型学习得到的参数,同样的,θ上标(2)表示的是我们是使用这个模型学习得到的参数。通过使用一个三次模型,我们可以得到θ(3)。这样一直下去,我们还可以得到θ(10)。

在这样的基础上,我们可以做的是,使用这些参数,我们去计算它们各自对应的测试误差。因此,我们可以计算出J test(θ(1)),J test(θ(2))等等,最后得到j test(θ(10))。也就是对于每一个模型对应的假设,都计算出其作用于测试集的表现如何。那么接下来为了确定选择哪一个模型最好,我们要做的是,看看哪个模型具有最小的测试集误差。

那么,假设,对于我们这个例子,最终选择了五次多项式模型。所以到目前为止,这个过程看起来还比较合理。但现在,我们确定了使用这个五次函数模型。然后我们想要知道,这个模型的泛化能力到底如何?对此,我们可以做的一件事情是,直接使用J test(θ5). 但问题在于,这样做仍然不能公平地说明我们的假设推广到其他新样本时的效果。 这个问题的原因在于,我们做的事情是使用了测试集来挑选这个额外的d参数,也就是说我们选择了一个能够最好地拟合测试集数据的参数d的值。因此,我们的参数向量θ(5)在拟合测试集时的结果,非常可能是对泛化误差的一个非常乐观的估计。因为,我们是找了一个最能拟合测试集的参数d,因此我们的假设很可能在这个测试集上表现良好,但对于新的样本可能就未必了。所以,我们其实更加关心对新样本的拟合效果。

所以,简单回顾一下,我们利用了训练集数据来学习得到参数θ,因此训练误差并不能很好地描述模型的一般泛化能力,训练误差对于模型而言是泛化能力的非常乐观的估计,如果使用了它作为模型的衡量指标,那么实际上是认为不会有新的样本,所有的可能样本都已经在训练集中出现过了。同样的现在,我们使用了测试集来选择参数d,那么这也会使得测试误差对于模型而言也是非常乐观的估计。因为对于已经被用于参数确定的数据,它们对模型而言都不是什么新数据,都算是见过的数据,因此并不能作为模型泛化的衡量指标。

为了解决这个问题,当面临模型选择问题时,我们通常会采用这样的方法来解决。

给定一个数据集,我们不再将它们直接切分成训练集和测试集,而是将它切分成三份。第一部分和之前一样,也是训练集。然后第二部分数据,我们将之称为交叉验证集,有时我们也称交叉验证集为CV集。然后最后这部分数据我们依然称之为测试集。那么最典型的三者比例是,6:2:2。这个比例可以有一些变化,不过这个比例一般还是比较典型的。

因此,现在我们的训练集就是大约60%的总数据,我们的交叉验证集或者CV集,大约有20%的数据,我们可以使用m下标cv来表示。最后,我们同样有一个测试集,m下标test个测试样本。

所以,这样我们就定义了训练集、交叉验证集和测试集。同样我们也可以定义训练误差、交叉验证误差和测试误差。因此训练误差可以这样定义,这里我们将训练误差写作J下标train (θ),这和我们前面定义的J(θ)几乎完全是一个意思,只不过训练误差是在训练集数据上计算得到的。然后J下标cv (θ)表示的就是验证集误差。那么最后就是测试集误差,和之前的定义也是一致的。

因此,在考虑像这样的模型选择问题时,我们不再使用测试集来进行模型选择,而是使用交叉验证集来进行模型选择

因此,这就是模型选择问题,包括应该如何将数据切分成训练集、交叉验证集以及测试集,并使用交叉验证集来进行模型选择,而使用测试集误差来衡量模型泛化能力。

最后我们需要说明的一点是,在如今的机器学习应用中,很少有人做我们前面说的这些事情。实际上使用测试集来选择模型,并使用测试误差来衡量泛化能力,确实不是合适的做法。尽管这样做,的确能得到一个很理想的泛化误差。但很遗憾的是,确实有很多人就是这样做的。虽然实际中有很多人都这么做,但是从合理的角度来说,还是建议大家能按照我们讨论的这种方式来做。

 

Bias vs. Variance[偏差和方差]

Diagnosing Bias vs. Variance[确定偏差和方差]

 

如果我们运行一个学习算法,倘若它的表现不佳,那么多半是遇到了两类问题:要么是有很大的bias,也就是在训练集上表现的就很糟糕,专业的术语就是欠拟合;要么是很高的variance,也就是虽然在训练集上表现良好,但在测试集上却表现很差,对应的专业术语叫做过拟合。那么这种时候,对于我们而言,非常重要的就是要弄清我们究竟遇到了高bias问题还是高variance问题,甚至我们同时面临这两类问题。因为一旦判断出,究竟出了什么问题,那么它实际上就是一个很好的指示器,能够让我们有的放矢地去改进我们的算法。

在接下来,我们将深入地讨论下bias和variance问题,希望大家能够对它们有一个更加深入的理解,并且也能弄清楚怎样评价一个学习算法,能够判断一个算法是有bias问题还是有variance问题,因为这对于如何改进学习算法的效果至关重要。

 

这里的图大家应该已经见过好几次了。[第一个图,线性拟合]如果我们使用一条直线来拟合这些数据,那么是不足以很好的拟合这组数据的,表现出欠拟合,也就是有很大的偏差,因此我们说它有较大的bias。[第三个图,过拟合]如果我们使用复杂的模型来拟合数据,那么对于训练集而言,会拟合得很好,但它又过于完美,无法在训练集以外的数据上泛化,从而出现过拟合现象,也就是我们说的高variance。[第二个图,正好]而如果像这样使用一个二次曲线来拟合数据,那么看上去就刚刚好,模型不是那么复杂,对训练集数据拟合的还不错,同时在非训练集的样本上也泛化的不错。

现在,我们其实已经掌握了训练集、验证集和测试集的概念。我们就能更好的理解bias问题和variance问题。

具体来讲,我们沿用之前所定义的训练误差和交叉验证误差,也就是均方误差,分别在训练集和交叉验证集上计算得到的误差

那么现在让我们画一下这样的示意图,横轴是多项式的度,因此越向右,我们模型使用的多项式的次数就越高,所以比如左侧的这个图,d=1,我们使用非常简单的函数来对数据进行拟合,而在右图我们使用更加复杂的函数来对数据进行拟合。现在让我们看看它们分别对应的训练误差和交叉验证误差。

我们先来看看训练误差,随着我们增加模型的复杂度,也就是增加多项式的度,我们会发现我们的模型对训练集的数据拟合的越来越好,所以,如果d=1,我们的训练误差可能比较大,但如果d比较大,那么我们的训练误差可能就比较小,甚至是0. 所以当我们不断增加多项式的次数,我们不难发现,训练误差将越来越小。

现在我们再继续看看交叉验证误差。所以,我们知道,如果d=1的话,意味着我们使用了一个非常简单的函数来拟合我们的数据,也就是说我们很容易出现欠拟合,那么如果我们采用了一个较为合理的复杂度,那么我们的交叉验证误差就能小一些。不过如果我们的d太大了,我们又容易出现过拟合的问题,这会造成交叉验证误差又变得很大了。所以如果我们多试一些d的取值的话,我们把它们对应的交叉验证误差平滑地画出来,大概会得到这么一条曲线。

所以,类似这样地图,可以帮助我们更好地理解bias和variance概念。

具体来说,假设我们得到了一个学习算法,而它的表现不如预期,所以如果交叉验证误差很大,那么我们如何判断此时的学习算法正处于高bias问题还是高variance问题呢?

在图上我们可以看到,交叉验证误差很大。那么,左侧这个区域,实际上是高bias问题,也就是我们使用过于简单的模型比如线性模型来拟合非线性的数据。而在右侧这个区域,它对应的则是高variance问题,这意味着d的取值太大了,模型过于复杂了。

这幅图也提示了我们如何区分这两种情况。具体地说,高bias的情况,对应着欠拟合,我们会发现它的交叉验证误差和训练误差都比很大。所以,如果我们遇到了高bias问题,那么我们的训练误差会很高,同时交叉验证误差也会很高,而且可能和训练误差很接近。另一种情况呢,如果我们的算法遇到了高variance问题,我们会发现,训练误差会比较小,即我们对训练集数据拟合得很好,但交叉验证误差却很高,会比训练误差高非常多。所以,如果我们发现了这种情况,那么这预示着,学习算法可能正处于高variance,过拟合的状态。

区分这两种情况的关键点在于,如果是高bias问题,则训练集误差也会很大,而如果是高variance问题,则训练集误差则不会很大,而且相较于交叉验证误差会小很多。

所以,以上内容希望能够帮助大家更加深入地理解bias和variance问题。

 

Regularization and Bias/Variance[正则化和偏差/方差]

现在我们已经知道正则化可以帮助我们防止过拟合。但它又是怎样影响一个学习算法的bias和variance呢?

那么现在我们就来讨论下bias和variance之间具体是什么关系,已经正则化与它们的关系又是怎样的。

假设,我们要使用这样一个高阶多项式的模型,不过为了避免过拟合,我们采用了这样的正则化。让我们考虑如下三种情况。

第一种情况是,采用非常大的正则化因子λ,比如我们的λ取值是1万,那么在这种情况下,所有的这些参数,包括θ1,θ2,θ3等等将会被极大地进行惩罚,那么最终就会造成大部分θ几乎等于0,那么我们的假设函数或者说模型就差不多是hθx≈θ0。所以,我们的拟合曲线几乎就是一条水平线。所以,这种情况下,我们的模型就会产生欠拟合,也就是高bias。因为这样的一条简单的水平线根本不足以拟合我们这里的这些数据。

而另一个极端是,我们使用了一个非常小的正则化因子λ,比如λ=0. 在这种情况下,如果我们要拟合一个高阶多项式的话,这通常就会造成过拟合,或者说是高variance。

而只有在我们采用了一个比较适中的λ的时候,我们才会得到一组合理的、能够对数据进行良好拟合的θ参数。

那么,如何自动地选择出一个最合适的正则化因子λ呢?

我们回顾一下,[第一个式子]是我们的模型,[第二个式子]是我们的目标函数,也就是最小化的目标函数。

关于这个主题的最后一件我们需要讨论的事情是,在λ取不同的值的时候,我们的训练误差和交叉验证误差是怎样变化的。

[第一个式子]是我们学习算法的最小化目标函数。为了表达我们要讨论的目标,我们保持训练误差和交叉验证误差还是原来的计算方法,也就是不包括正则化项,其实这也理解,因此我们在做优化求解θ的时候我们需要同时兼顾对数据拟合的能力和模型的复杂度。但在衡量误差时,我们就不需要再考虑模型的复杂度了。

那么,我们这里要做的其实就是,根据λ的取值,来绘制出训练误差和交叉验证误差,这样这个图形就能表达我们在使用不同的正则化因子λ的时候对训练误差和交叉验证误差会造成怎样的影响。

就像我们之前说的,如果λ如果很小,那么就几乎没什么正则化的作用,那么我们就有可能出现过拟合的情况,而如果λ很大,那么我们就有可能出现欠拟合的情况。所以,如果我们绘制J train和J cv,对于小λ,我们相对而言可以很好地拟合训练集,因为我们没怎么使用正则化,而如果λ很大时,那么我们就可能处于高bias的境地,无法对训练集拟合得很好。所以J train会随着λ的增加而不断变大。

而对于交叉训练集误差,如果λ很大,我们会处于欠拟合状态,因此j cv也会很大,而如果λ很小,我们则会处于过拟合状态,因此j cv也会很大。

所以,这就是在我们修改正则化因子λ的时候,训练集误差和交叉验证集误差将会怎样变化的情况。所以,正正好的λ其实就是位于这样的位置,λ值不大不小,j cv比较小,j train也不怎么大。当然,我们这里画的图可能过于理想化了,对于真实的数据,如果绘制这样的图,可能它会表现得比较凌乱,不过还是应该会有这样的趋势。所以,如果尝试不同的λ,得到不同的j train和j cv,我们就可以人工地或者写一个小程序来选择j cv最小的那么λ。

好了,以上就是关于正则化因子λ的内容了,希望能够帮助大家更加深入地理解正则化,以及它对于学习算法的bias和variance的影响。

Learning Curves[学习曲线]

如果检查程序是否正确运行或者希望改进算法的效果,那么绘制学习曲线,经常会非常有用。实际上,学习曲线是一个很好的用于判断一个学习算法是否处于bias或者variance问题的工具。

绘制学习曲线,一般我们可以线绘制训练集误差,也就是j train。我们这里绘制时,使用的自变量或者横轴是训练集的样本数m。比如我们的训练集有100个样本,我们这里要做的是限制自己使用的样本数,比如10个,20个,30个,40个,然后绘制出训练集误差,以及交叉验证集误差j cv。

假设我们只有一个训练样本,比如第一幅图中的这种情况,假如我们使用二次函数作为模型来拟合。那么由于我们只有一个训练样本,拟合出的效果会非常好,我们的训练误差一定会是0. 而如果有两个训练样本的话,二次函数也可以拟合得很好,即使使用了正则化,我们大概率也会拟合出很好的结果。而如果我们有三个训练样本的话,看起来依然能够很好地用二次函数来拟合。也就是说m=1, m=2, m=3,在训练集上得到的误差都将是0或者接近于0.

所以,我们总结一下,我们到现在已经看到,当样本量很少时,训练误差也会很小。那么现在,如果m=4,二次方程似乎也可以很好地对数据进行拟合,那么继续看m=5的情况,这时候再使用二次函数来拟合,好像效果有所下降了,不过仍然不算坏。而当我们的训练集合变得越来越大,我们的训练误差也会变得越来越大。

简单回顾一下,当样本量很少的时候,模型可以很容易地拟合到很好,所以训练误差也会很小,而反过来如果训练样本很多的话,那么相对每一个训练样本都拟合到很好,就显得很困难了,所以训练误差就会变得越来越大。

那么,交叉验证集误差j cv又是怎样的情况呢?实际上,交叉验证误差,是对完全陌生的交叉验证集的样本进行预测得到的误差,那么我们知道,当训练集很小的时候,泛化能力不会很好,也就是不太能很好地对新的样本进行预测,比如我们右侧的前几幅图。只有当训练集更大的时候,我们才可能得到一个更好拟合数据的可能的假设。因此,交叉验证集误差很可能会随着训练集不断增大而变得越来越小,这是因为拥有了更多数据,就拥有了更强的泛化能力,也就是对新样本数据的预测能力。

 

那么接下来,我们来看看如果学习算法陷入高bias或者高variance问题时,学习曲线又会是怎样。

如果我们的假设有高bias的问题,比如我们右上角的这个数据集,我们如果使用一个线性函数来拟合它,那么我们就会出现高bias的问题,也就是我们的假设函数无法很好的拟合这些数据,出现了所谓的欠拟合情况,表现为在训练集上的误差都很大。

现在我们来试着想一想,如果我们增加训练样本会出现什么情况呢?所以,我们的样本数会变得更多,而不仅仅只有右上角的五个样本而已,比如我们增加样本以后得到了右下角的这个样本集,那么保持我们的假设函数不变,仍然还是线性假设,也就是继续使用直线来拟合它们,我们不难想象,我们仍然会拟合出一条差不多的直线。刚才少量样本,线性假设无法很好的拟合那些数据,而现在数据多了,线性假设仍然不能很好地拟合我们地样本。因为我们假设函数的性质没有变,无论如何它都是线性的,对于我们这些显然非线性的数据,必然无法取得更好的效果。

所以,如果我们绘制出交叉验证集的误差,应该大约是这样。最左端表示训练集样本很少,比如只有一个样本,那么表现当然很不好,而随着我们增大训练样本集,当达到某个值的时候,我们就会找到那条最能拟合这组数据的直线,那么此后再怎么增加训练样本也不会有什么改观了,因为我们基本上还是会得到一条差不多的直线。因此,交叉验证集误差将会很快变得水平而不再变化。那么训练集误差又是怎样呢?同样,训练误差一开始会很小,而在高bias的情况下,我们会发现训练集误差会逐渐增大,一直接近于交叉验证集误差。这是因为,我们只有这么点参数,而当m很大时,也就是训练数据很多时,这时假设函数或者模型,在训练集和交叉验证集上的预测效果几乎就没什么差异。

所以,这就是当学习算法处于高bias的时候,学习曲线的大致走向。所以,在这种情形下,训练集误差和交叉验证集误差都会很大。这也导出了一个有意思的结论,那就是:如果学习算法出现了高bias的问题,那么增加训练样本是无济于事的。正如我们右侧两幅图所展现的,上图仅有五个训练样本,然后我们学习得到了这条直线,随后我们增加了更多的训练样本,但我们仍然得到了几乎一样的直线,因此学习算法处于高bias时,无论再提供多少训练样本,对我们的算法性能改进而言也是一点用处都没有的。

所以,一旦明白了这些,当我们真的遇到这种问题的时候,就不会再想着花费时间和精力取获取更多的训练样本了,因为即使获取了更多的数据对我们改进算法也是没有意义的。

接下来,我们再来看看高variance的情况,学习曲线又会是怎样的呢?

首先,我们来看看训练误差。如果我们的训练样本很少的话,比如就像这里只有五个训练样本,而如果我们使用一百次方的多项式特征来拟合这组数据,而且我们把λ设置的很小,那么显然,我们将会对这些数据完美拟合,所以这个假设函数对这个问题出现了过拟合的问题。所以,训练样本很少时,我们的训练误差J train将会很小,而随着训练集样本增多,可能这个假设函数对数据或多或少有一点过拟合,但很明显此时要对数据很好的拟合显得更加困难了,所以随着样本量的增加,我们会发现J train会随之增大,因为当训练样本越多的时候,我们就越难对训练集数据更好地拟合,但总的来说训练集误差还是比较小的。

那么交叉验证集误差呢?其实,在高variance的情况下,假设函数对数据过拟合,因此交叉验证误差将会一直都很大,如果画出来,那么可能就是这个样子。

所以,算法如果处于高variance的情况下,最明显的特征就是,训练误差和交叉验证误差之间存在很大的差距。

所以通过观察这个学习曲线的图,如果我们增加训练样本的话,我们可以预期,这两条学习曲线会逐渐的相互靠近。那么如果我们不断地向右延伸,那么训练误差将会继续增大,而交叉验证集误差将会持续下降。当然,我们最关心的还是交叉验证集误差。所以,对于高variance情况,增加训练样本将对学习算法的改进具有积极的意义。

不过大家要注意到,我们绘制的学习曲线都是很理想化的,如果针对一个实际的学习算法,绘制学习曲线的话,有时我们会看到基本类似的结果,就像我们这里画的一样,不过有时我们也会看到带有一点噪声或干扰的曲线。但总的来说,像这样画出学习曲线,确实能帮助我们看清我们的学习算法是否处于高bias或者高variance的情况。所以,当我们想要改进一个学习算法的时候,我们通常应该进行的一项工作就是绘制这些学习曲线。一般而言,这会使我们更轻松地看出bias或variance方面的问题。

Deciding What to Do Next Revisited[再次复习下一步要做什么]

我们已经讨论了怎样评价一个学习算法、如何选择模型、bias和variance问题。那么这些诊断法则怎样帮助我们弄清哪些方法有助于改进学习算法的效果,而哪些方法又是徒劳的呢?让我们再次回到最开始的例子,看看对于不同的问题,应该采用怎样的方法。

那么这就是我们最开始的例子,我们试图使用正则化的线性回归模型拟合数据,并评价算法是否达到预期效果。我们提出了如下的一些选择。那么,到底有没有某种方法能够明确指出以上哪些方法有效呢?

第一个选项是,使用更多的训练集数据。这种方法对于高variance的情况,是有帮助的。这也就是说,如果我们的模型不是处于高variance的情况,那么增加更多的训练样本不会有什么显著的帮助。判断高variance的情况就像之前说的,训练误差较小,但交叉验证误差比较大,在学习曲线上的表现就是j train和j test之间有一个明显的差距。

那么第二种办法,使用更少的特征呢?这同样是对高variance有效。换句话说,如果我们通过学习曲线或者其他什么办法,看出我们的模型有高bias问题,那么请一定注意,千万不要浪费时间试图从已有的特征中挑选出一小部分来使用。因为我们已经发现了高bias问题了,使用更少的特征仍然无济于事,因为更少的特征意味着更加简单的模型,而高bias本身就已经说明目前的模型对于需要拟合的数据而言过于简单了,所以继续把模型变得简单,对于解决高bias问题不会有任何效果,甚至适得其反。反过来讲,如果我们确定遇到了高variance问题,那么花些时间来挑选一部分更加合适的特征将会对提升模型的效果有积极地帮助。

那么第三个方法呢?增加更多额外的特征。虽然不是所有时候都适用,但增加特征一般都是解决高bias问题的法宝。所以,如果我们增加额外的特征,这就使得我们的模型更加复杂,那么它对数据的拟合能力就越强,这样就能期望解决高bias的问题。

类似地,增加多项式特征也有类似的效果,这实际上也属于增加特征,增加模型的复杂度,因此也是用于解决高bias问题的方法。

最后,调节正则化因子λ,这种方法尝试起来相较前几种更加方便,不至于花费太久的时间。不过减小λ,我们已经知道是对高bias问题是一种解决办法;而增加λ则是可以解决高variance。

这里的信息量其实已经有些大了,我建议大家可以暂停下视频,然后在脑中针对每一条稍微思考一下,让自己切实地理解这些方法所能解决的问题。特别是,不需要大家硬生生地记住这些办法,而是通过理解底层逻辑,能够自行推导出这些手段所能达到的效果。虽然我说了推导这个词,但如果大家真的理解了底层的逻辑,这其实都是非常直观、容易的推理,而不是需要使用高深的数学知识来推导。

最后,我们回顾一下,这几节课学习的内容,并且看看它们和神经网络的联系。我们这里想要讲的,其实主要还是因为神经网络这种模型结构跟线性回归、逻辑回归这种相对容易理解的模型之间存在着一些理解上的差异。

所以,对于神经网络,其实我们介绍的评估模型的方法、模型选择的方法以及过拟合和欠拟的解决方案都是通用的。只是,对于神经网络,因为它的特殊形式,在理解上可能存在着一些障碍。不过,一种理解方式,是将神经网络完全看作是非常复杂的复合函数,那么从这种视角,就很容易将我们最近介绍的模型评估方法应用起来。

所以,较小的神经网络,实际上就是更加简单的模型,因为它对应着更少的神经元,或者说逻辑上它使用了更少的特征,因此它就容易类似前面我们说的线性函数拟合非线性数据一样,可能会出现欠拟合的情况。不过相对而言,它的计算代价并不算大。

而较大的神经网络,无论是层数多还是隐层神经元多,那么它都意味着更加复杂的模型,因为它对应更多的神经元,也就是逻辑上它使用了更多的特征,因此它就容易出现过拟合的情况。当然,过拟合,我们可以使用正则化来解决。不过大型的神经网络本身也会存在计算更加昂贵的问题。但是,对于神经网络的不同结构而言,我们讨论的评估方案、模型选择方法都是通用的。

所以,关于机器学习的实用性建议大约就是这样。通过这些内容,希望大家能够掌握如何评估当前的模型的方法,并且知道在遇到问题时应该采用怎样的措施来解决,把时间花在刀刃上,而不是随机选择一些可能没有意义的方案耗费时间。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐