红色石头给大家介绍了《Scikit-Learn 和 TensorFlow 机器学习指南》第1次学习笔记。内容很干,翻译的质量红色石头自认为还是不错的,翻译的同时也会取舍或增加一些内容,尽量把主要内容提炼出来,希望能帮到大家学习这本书。虽然更新得有点慢,但是翻译+整理确实比较花时间~对了,这个翻译项目我已经同步在 GitHub 上了,喜欢的给个 Star 吧!链接如下:
https://github.com/RedstoneWill/Hands-On-Machine-Learning-with-Sklearn-TensorFlow
好了,言归正传,今天给大家讲讲两个比较实际的问题:一是机器学习面临得哪些挑战;二是为什么要使用测试集和验证集。
1. 机器学习面临哪些挑战?
简而言之,因为机器学习的主要任务就是选择合适的机器学习算法在数据集上进行训练,所以不好的算法和不好的数据都可能严重影响训练效果。下面我们先来看看不好的数据会带来什么影响。
1.1 训练数据不足
对一个蹒跚学步的孩子来说,如何识别苹果?方法是拿出很多各种各样颜色、形状的苹果图片给他看,教他。这样,孩子就能够更好地识别出各种苹果。
而对机器学习来说还达不到这种程度,大多数机器学习算法都需要很多数据才能有不错的表现。即使是简单的算法可能也需要上千个训练样本。对于复杂的机器学习问题,例如图像识别、语音处理,需要的训练样本就更多了,甚至是百万级别的(除非你基于已有的模型进行再次训练,类似于迁移学习,所需的样本可能不多)。
数据的不合理有效性:
在 2001 年发表的著名文章里,微软研究员 Michele Banko 和 Eric Brill 展示了不同的机器学习算法在一个较复杂的自然语言消歧问题上的表现情况,他们发现一旦有足够多的训练数据,各算法的表现都基本一致(如下图所示)。
正如作者所说:“这个结果表明我们可能需要重新考虑是花费时间、金钱在算法研究上还是在扩充语料库上。”
对于复杂问题,数据比算法更加重要这一思想在 Peter Norving 等人于 2009 年发布的文章《The Unreasonable Effectiveness of Data》中得到进一步的推广。值得注意的是,小型和中等数量的数据集仍然非常常见,而且想要获得大量的训练数据通常并不是一件简单的事情,所以还不能抛弃算法。
1.2 没有代表性的训练数据
为了让模型有更好的泛化能力,很重要的一点是你的训练数据应该有很好的代表性,无论你使用的是基于实例学习还是基于模型学习。例如,之前我们训练线性模型选择的一些国家并不具有很好的代表性,缺少了一些国家。下图展示了增加这些国家之后的数据分布和线性模型。
如果你在这些完整的数据上训练线性模型,得到的黑色实线;原来的线性模型是蓝色虚线。如你所见,添加几个缺失的国家后不仅显著地改变了模型,而且清楚地表明,这种简单的线性模型可能永远都不会有很好的性能。看起来,非常富裕的国家并不比中等富裕国家幸福(事实上,他们似乎更不幸福),相反,一些穷国似乎比许多富裕国家更加幸福。
如果使用没有代表性的数据进行训练,模型不可能得到准确的预测,特别是那些非常贫困和非常富有的国家。
使用有代表性的训练数据是非常重要的。但这通常比较困难,如果样本太少,容易引入采样噪声(即非代表性的数据);即使是很多样本,如果采样方法有缺陷,也可能得到不好的数据,这被称为采样偏差(sampling bias)。
一个著名的采样偏差例子:
或许最有名的采样偏差例子发生在 1936 年的美国大选,林轩田课程中也提到过这个例子。当时的候选人是 Landon 和 Roosevelt,《Literary Digest》做了一次很大的民意调查,给 10,000,000 选民发送邮件征集选民意向,总共收到了 2,400,000 的反馈结果。调查报告显示 Landon 的支持率是 57%,但是最终选举投票 Roosevelt 得到了 62% 的选票赢了 Landon。差别如此之大的原因在于《Literary Digest》的民意调查采样方法有缺陷:
还有一个例子,假如你想构建一个系统来识别 funk 音乐视频。得到训练集的方法之一就是在 YouTube 上搜索 “funk music”,得到的视频作为训练集,但这是假设 YouTube 搜索引擎返回的是所有具有代表性的 funk music。事实上,搜索结果可能偏向于推荐某些有名的音乐家(跟你的所在地、平时喜好都有关系)。
1.3 低质量数据
显然,如果训练数据都是错误、离群点和噪声(例如,由于质量不佳的测量),想要得到一个性能较好的模型是非常困难的。因此,花费时间清洗训练数据是十分必要的,这也是数据科学家们非常重视的。常用的方法如下:
1.4 不相关特征
俗话说:种瓜得瓜,种豆得豆。如果训练数据包含了足够的相关特征,没有太多的不相关特征,模型就有能力学习。机器学习如此强大的一个重要原因就是提取一些重要的特征来训练。提取特征并处理的过程我们称之为特征工程,具体包含以下几个方面:
以上就是一些不好的数据类型,接下来我们将介绍有哪些不好的算法。
1.5 过拟合
举个形象的例子,比如你去某个国家旅游搭乘出租车,半路上司机把你丢在路边,你可能会说这个国家的出租车司机都是坏蛋!这种过度概括的行为是人类经常做的。同样不幸的是,机器有时候也会出现类似的情况,机器学习里称之为过拟合:表示模型在训练数据上表现的很好,但是在其它样本上表现得却不好,泛化能力差。
下图展示了使用高阶多项式模型来拟合生活满意度与人均 GDP 的关系。尽管在训练数据上该高阶模型表现比简单的线性模型好得多,但是你真的相信这是一个很好的模型吗?
诸如深层神经网络这种复杂模型可以检测出数据中的细微模式,但是如果训练集包含噪声,或者样本不多(带来采样噪声),模型很可能会检测到噪声本身的模式。很明显这些模式无法很好地泛化到其它样本中。例如,生活满意度模型中,采用国家名称这一属性作为特征之一,发现所有训练样本中国家名称包含字母 w 的生活指数都大于 7:New Zealand (7.3), Norway (7.4), Sweden (7.2), Switzerland (7.5)。这种结论你觉得能归纳到训练样本以外的其它样本吗?例如 Rwanda、Zimbabwe?显然是不行的,这一模式只是偶然发生在训练数据中,但是模型本身没有办法判断一个模式是真实反映数据内在特征的还是数据中噪声造成的。
当模型过于复杂时,容易发生过拟合,常用的解决方法是:
限制模型复杂度,让它变得简单,减少过拟合风险的做法称之为正则化(regularization)。例如,我们之前定义的线性模型包含两个参数 θ0 和 θ1 。这给了学习算法两个自由度来让模型适应训练数据:可以调试直线的截距 θ0 和斜率 θ1。如果令 θ1=0,则算法只有一个自由度,很难较好地拟合数据:可以做的仅仅是把这条水平线上下移动,尽量接近训练样本,最终停留在所有训练样本的均值位置。这确实是一个非常简单的模型!如果 θ1≠0,但值很小,学习算法有效的自由度在一和二之间,它比两个自由度模型简单,比一个自由度模型复杂。其实,你的目标就是在完美拟合数据和简化模型之间找到平衡,使模型具有较好的泛化能力。
下图展示了三种模型:蓝色点线表示原始的线性模型,缺少一些国家的数据;红色短划线表示第二个线性模型,使用了所有国家的数据训练得到的;蓝色实线表示的模型与第一个类似,只是使用了正则化限制。可以看出正则化使得模型的斜率变小,对训练数据的拟合效果比第一种差一些,但是对新样本的拟合效果比第一种更好,泛化能力变强了。
正则化的程度由超参数控制。超参数是算法的参数(不是模型的参数),不受算法本身的影响。超参数在训练模型之前就设置好,整个训练过程中保持不变。如果将超参数设置很大的值,将会得到一个近似平坦的模型(斜率接近 0 )。这时候不太可能出现过拟合,但是模型过于简单,对数据的拟合效果很差。这种情况叫做欠拟合,它和过拟合是两个对立的概念。调试超参数是构建机器学习系统过程中非常重要的一步,下一章节我们想详细介绍。
1.6 欠拟合
正如上文所说,欠拟合是与过拟合对立的概念:它发生在模型过于简单以至于不能很好地拟合数据的时候。例如,生活满意度的线性模型就可能存在欠拟合,实际的模型可能要比线性模型更加复杂。因此,线性模型即便是对训练样本也会预测得不够准确。
解决欠拟合得主要方法有:
1.7 回顾
到目前为止,我们已经学习了很多机器学习概念知识,下面做个简单回顾:
还有一点需要讨论:一旦训练了一个模型,不能仅仅是“希望”它的泛化能力好,我们还要去评估这个模型,必要的时候调试模型。下面就来介绍怎么去调试模型。
2. 测试和验证
评估模型好坏的唯一方法就是测试模型在新样本中的表现。一种做法是把模型直接放到生产中实际检测其表现。但如果模型性能不佳,会让用户抱怨吐槽。因此,这并不是一个好方法。
一种更好的做法是把数据集划分成两部分:训练集和测试集。顾名思义,训练集用来训练模型,测试集用来评估模型。模型在新样本下的错误率被称为泛化误差(又叫样本外误差,out-of-sample error)。模型在测试集上评估模型,得到的误差可以近似认为就是模型的泛化误差。一般使用整个数据集的 80% 作为训练集,20% 作为测试集。
如果模型的训练误差(模型在训练集上的误差)很小,而泛化误差很大,则说明模型很可能发生了过拟合。
这下,评估模型变得简单了:使用测试集即可。如果有两个模型(一个线性模型,一个多项式模型),如何决定哪个模型更好呢?方法就是直接训练两个模型,然后比较它们在测试集上的泛化误差大小就可以了。
还有一个问题,如何选择最佳的正则化超参数呢?一种方法就是分别使用不同的超参数训练模型,然后比较各个超参数对应模型的泛化误差(泛化误差在测试集上得到),对应泛化误差最小(例如 5%)的超参数即为最佳值。
然后,将模型上线发布,但不幸的是模型表现却并不像测试时那么好,实际误差达到了 15%。这又是为什么呢?
问题在于我们是在同一测试集上多次测量泛化误差的,这样产生的最佳模型是适应测试集的,可能造成模型在测试集之外新的样本上表现得不太好。
解决这一问题通常的做法是除了设置训练集、测试集之外,还设置一个验证集。同样使用训练集来训练不同超参数的模型,每个模型在验证集上进行验证,选择表现最好的超参数对应的模型,最后该模型在测试集上进行测试得到的误差为最终的泛化误差。
为了避免验证集占用过多的训练样本,造成浪费,通常使用交叉验证(cross-validation):将整个训练集划分为 N 份,取其中的 N-1 份作为训练集,另外的 1 份作为验证集,重复 N 次。然后将 N 次的验证误差求平均作为验证误差。一旦模型和超参数选定之后,使用该模型和超参数,在整个训练集上进行训练。最后,在测试集上测试得到泛化误差。
无免费午餐定理:
模型是样本观测的一种简化。简化意味着丢弃一些多余的不具备泛化能力的细节。然而,决定哪些数据保留,哪些数据抛弃,我们必须做出假设。例如,一个线性模型假设数据是呈线性关系的,实例与直线之间的距离仅仅是噪声,是可以忽略的。
在 1996 年的一篇著名论文中,David Wolpert 证明了如果对数据不作任何假设,选择一个模型而不选择其它模型是没有理由的。这被称为无免费午餐(NFL)定理。对某些数据集来说,最好的模型是线性模型,而对于另外某些数据集来说,最好的模型可能是神经网络。没有哪个模型一定是最好的(正如这个定理的名字那样)。确定哪个模型最好的唯一方法就是对所有的模型进行评估,但是这显然不太可能。实际上我们通常会对数据作出某些合理的假设,仅仅评估一些合理的模型。例如,我们可能设置不同的正则化参数来评估线性模型;对于更复杂的问题,可能评估不同的神经网络模型。