跳转至

第1章:赋予计算机学习数据的能力

Github Notebook 地址: https://nbviewer.org/github/rasbt/python-machine-learning-book/blob/master/code/ch01/ch01.ipynb

在我看来,机器学习是一门能够发掘数据价值的算法与应用,它是计算机科学中最激动人心的一个领域。我们生活在一个数据资源非常丰富的时代,通过机器学习领域中自学习算法,可以将这些数据转换为知识。借助于近年来发展起来的诸多功能强大的开源库,现在是进入机器学习领域的最佳时机。同时,利用该领域中那些功能强大的算法来发现数据中的模式,进而实现对未知事件的预测。

本章我们将了解机器学习的主要概念及其几种不同类型的学习算法。同时,还将对相关术语做基本的介绍,为今后熟练使用机器学习解决实际问题打好坚实的基础。

本章将涵盖如下内容:

  • 机器学习的一般概念
  • 机器学习方法的三种类型和基本术语
  • 成功构建机器学习系统所需的模块
  • 面向数据分析和机器学习的 Python 安装与设置

1. 构建智能机器将数据转换为知识

我们正处于现代技术飞速发展的时代,同时还拥有大量的结构化和非结构化的数据资源。20世纪下半叶,机器学习逐渐演化为人工智能的一个分支,其目的是通过对自学习算法的开发,从数据中获取知识,进而对未来进行预测。与以往通过大量的数据分析而人工推导出规则并构造模型不同,机器学习提供了一种从数据中获取知识的方法,同时能够逐步提高预测模型的性能,并将模型应用于基于数据驱动的决策中去。机器学习部件在计算机科学研究领域显现出日益重要的地位,而且在日常生活中也逐渐发挥出越来越大的作用。机器学习技术的存在,使得人们可以享受强大的垃圾邮件过滤带来的便利,拥有方便的文字和语音识别软件,能够使用可靠的网络搜索引擎,同时在象棋的网络游戏对阵中棋逢对手,而且在可见的将来,我们将拥有安全高效的无人驾驶汽车。

2. 机器学习的三种不同方法

本节我们将介绍是三种不同类型的机器学习方法: 监督学习(supervised learning)、无监督学习(unsupervised learning)和 强化学习(reinforcement learning)。我们将学习这是三种不同方法之间的本质区别,并使用概念性示例,让大家对着三种方法在实际问题中的应用有一个直观的认识。

2.1 通过监督学习对未来事件进行预测

监督学习的主要目的是使用有类标的 训练(training) 数据构建模型,我们可以使用训练得到的模型对未来数据进行预测。此处,术语 监督(supervised) 是指训练数据集中的每个样本均有一个已知的输出项(类标 label)。

以(过滤)垃圾邮件为例:基于有类标的电子邮件样本库,可以使用监督学习算法训练生成一个判定模型,用来判别一封新的电子邮件是否为垃圾;其中,在用于训练的电子邮件样本库中,每一封电子邮件都已经准确得标记是否为垃圾邮件。监督学习一般使用离散的类标(class label),类似于过滤垃圾邮件的这类问题也被称为 分类(classification)。监督学习的另一个子类是 回归(regression),回归问题的输出项是连续值。

2.1.1 利用分类对类标进行预测

分类是监督学习的一个子类,其目的是基于对过往类标已知示例的观察学习,实现对新样本类标的预测。这些类标是离散的、无序的值,它们可以视为样本的**组别信息**(group membership)。前面提到的检测垃圾邮件的例子是一个典型的 二类别(binary classification),机器学习算法会生成一系列的规则用以判定邮件属于垃圾邮件还是非垃圾邮件。

然而,类标集合并非一定是二类别分类的。通过监督学习算法构造的预测模型可以将训练样本库出现的任何类标赋给一个尚未被标记的新样本。手写字符识别就是一个典型的 多类别分类(multi-class classification)的例子。在此,我们可以将字母表中每个字母的多个不同的手写样本收集起来作为训练数据集。此时,若用户通过输入设备给出一个新的手写字符,我们的预测模型能够以一定的准确率将其判定为字母表中的某个字母。然后,如果我们的训练样本库没有出现 0~9 的数字字符,那么模型将无法正确辨别任何输入的数字。

下面通过给出具有30个训练样本的实例说明二类别任务的概念: 15个样本被标记为 负类别(negative class)(图中用圆圈表示);15个样本被标记为 正类别(positive class)(图中用加号表示)。此时,我们的数据集是二维的,这意味着每个样本都有两个逾期关联的值: \(x_1\)\(x_2\)。现在,我们可以通过有监督的机器学习算法获得一条规则,并将其表示为一条黑色虚线标识的分界线,它可以将两类样本分开,并且可以根据给定的 \(x_1\)\(x_2\) 值将新样本划分到某个类别中。

2.1.2 使用回归预测连续输出值

通过上一节的学习,我们知道了分类的任务就是将具有类别的、无序类标分配给各个新样本。另一个监督学习方法针对连续型输出变量进行预测,也就是所谓的 回归分析(regression analysis)。在回归分析中,数据中会给出大量的自变量(解释变量)和相应的连续因变量(输出结果),通过尝试寻找这两种变量之间的关系,就能够预测输出变量。

例如,假定我们想预测学生 SAT 考试中数学科目的成绩。如果花费在学习上的时间和最终的考试成绩有关,则可以将其作为训练数据来训练模型,以根据学习时间预测将来要参加考试的学生的成绩。

备注

“回归” 一词最早是由 Francis Galton 于 1886 年在其论文 "Regression Towards Mediocrity in Hereditary Stature" 中提出来的。他在文中描述了这样一种生物现象,即人口身高的方差没有随着时间的推移而增加。他发现: 父辈并未将其身高直接遗传给子辈,而子辈的身高更接近于人们的平均身高。

下面用图例阐述了 线性回归(linear regression) 的概念。给定一个自变量 \(x\) 和因变量 \(y\),拟合一条曲线使得样例数据点与拟合直线之间的距离最短,最常用的是采用 平均平方距离 来计算。这样我们就可以通过对样本数据的训练来获得拟合直线的截距和斜率,从而对新的输入变量值所对应的输出变量值进行预测。

2.2 通过强化学习解决交互式问题

另一类机器学习方法是强化学习。强化学习的目标是构建一个系统(Agent),在与 环境 (environment)交互的过程中提高系统的性能。环境的当前状态信息中通常包含一个 反馈 信号,我们可以将强化学习视为与监督学习相关的一个领域。然而,在强化学习中,这个反馈不是一个确定的类标或者连续型的值,而是一个通过反馈函数产生的对当前系统行为的评价。通过与环境的交互,Agent 可以通过强化学习来得到一系列行为,通过探索性的试错或者借助精心设计的激励系统使得正向反馈最大化。

一个常用的强化学习例子就是象棋对弈的游戏。在此,Agent 根据棋盘上的当前局态(环境) 决定落子的位置,而游戏结束时胜负可以作为激励信号。

2.3 通过无监督学习发现数据本身潜在的结构

在监督学习中,训练模型之前,我们事先可以获知各训练样本对应的目标值。在强化学习中,可以由 Agent 定义反馈函数对特定行为进行判定。然而,在无监督学习中,我们将处理无类标数据或者是总体分布趋势不明朗的数据。通过无监督学习,我们可以在没有已知输出变量和反馈函数指导的情况下提取有效信息来探索数据的整体结构。

2.3.1 通过聚类发现数据的子群

聚类 是一种探索性数据分析技术。在没有任何相关先验经验的情况下,它可以帮助我们将数据划分为有意义的小的组别(即簇 cluster)。对数据进行分析时,生成的每个簇中其内部成员之间具有一定的相似度,而与其他簇中的成员则具有较大的不同,这也是为什么聚类有时被称为“无监督分类”。聚类是获取数据的结构信息,以及导出数据间有价值的关系的一种很好的技术,例如,它使得市场人员可以基于用户的兴趣将其分为不同的类别,以分别定制相应的市场营销计划。

下图演示了聚类方法如何根据数据的 \(x_1\)\(x_2\) 两个特征之间的相似性将无类标的数据划分到三个不同的组别中。

2.3.2 数据压缩中的降维

数据降维(dimensionality reduction) 是无监督学习的另一个子领域。通常,我们面对的数据都是高维的(每一次采样都会获取大量的样本值),这就对有限的数据存储空间以及机器学习算法性能提出了挑战。无监督降维是数据特征预处理时常用的技术,用于清除数据中的噪声,它能够在最大程度保留相关信息的情况下,将数据压缩到一个维度较小的空间,但同时也可能降低某些算法在准确性方面的性能。

降维技术有时在数据可视化方面也是非常有用的。例如,一个具有高维度的数据集可以映射到一维、二维或者三维的属性空间,并通过三维或者二维的散点图和直方图对数据进行可视化展示。下图展示了一个使用非线性降维方法将三维的 Swiss Roll 压缩到二维特征子空间的实例。

2.4 基本术语及符号介绍

目前我们已经讨论了机器学习的三大方法: 监督学习、无监督学习和强化学习。在此,我们介绍一下下一章将要用到的一些基本术语。下面表格摘录了鸢尾花(Iris dataset) 中的部分数据,鸢尾花数据集是机器学习领域的一个经典示例,它包含了 Setosa、Versicolor 和 Virginica 三个品种总共 150 种鸢尾花的测量数据。其中,每一个样本代表数据集中的一行,而花的测量值以厘米为度量单位存储为列,我们将其定义为数据集的特征。

为了保证描述过程中所用符号及推导过程简单、高效,我们将采用 线性代数(Linear algebra) 中的一些基础知识。在后续章节中,我们将主要使用 矩阵向量 来标识数据。并作如下约定: 矩阵 \(X\) 中的每一行代表一个样本,而样本中的每个特征都表示为单独的列。

在鸢尾花数据集中,包含了 150 个样本和 4 个特征,因此将其记作 150x4 维的矩阵 \(X \in R^{\ 150*4}\):

\[ \begin{bmatrix} x_1^{(1)} & x_2^{(1)} & x_3^{(1)} & x_4^{(1)} \\\\ x_1^{(2)} & x_2^{(2)} & x_3^{(2)} & x_4^{(2)} \\\\ \vdots & \vdots & \vdots & \vdots \\\\ x_1^{(150)} & x_2^{(150)} & x_3^{(150)} & x_4^{(150)} \end{bmatrix} \]

在本书中,我们将使用上标 (\(i\)) 来指代第 \(i\) 个训练样本,使用下标 (\(j\)) 来指代训练数据集中的第 \(j\) 维特征。

加粗的小写字母代表向量(\(x \in R^{\ n*1}\)),而加粗的大写字母则代表矩阵 (\(X \in R^{\ n*n}\))。斜体的 \(x^{(n)}\)\(x_m^{(n)}\) 分别代表向量、矩阵中的单个元素。

例如: \(x_1^{150}\) 为第150个花朵样本的第1个特征“萼片宽度”。在这样一个特征矩阵中,每一行代表一个花朵的样本,可记为一个四维行向量 \(x^{(i)} \in R^{\ 1 \times 4}\)\(x^{(i)} = [ x_1^{(1)} \ x_2^{(1)} \ x_3^{(1)} \ x_4^{(1)} ]\)

数据集中的每个特征可以看作是一个 150 维的列向量 \(x_{j} \in R^{\ 150 \times 1}\)

\[ x_j = \begin{bmatrix} x_j^{(1)} \\ x_j^{(2)} \\ \vdots \\ x_j^{(150)} \end{bmatrix} \]

类似地,可以用一个 150 维的列向量来存储目标变量(在本例中为类标):

\[ y = \begin{bmatrix} y^{(1)} \\ y^{(2)} \\ \vdots \\ y^{(150)} \end{bmatrix} \\ (y \in \{Setosa, Versicolor, Virginica \}) \]

3. 构建机器学习系统的蓝图

我们已经在前序章节中讨论了机器学习的基本概念和是三种不同类型的机器学习方法。在本小节,我们将讨论其他与机器学习系统和学习算法相关的重要内容。下图展示了使用机器学习的预测模型进行数据分析的典型工作流程,这些内容将在后续小节中做进一步讨论。

3.1 数据预处理

为了尽可能发挥机器学习的算法性能,往往对原始数据的格式等有一些特定的要求,但原始数据很少能达到此标准。因此,数据预处理是机器学习应用过程中必不可少的重要步骤之一。以前面提及的鸢尾花数据集为例,我们可以将花朵的图像看做原始数据,从中提取有用的特征。有效的特征可以是花的颜色、饱和度、色彩强度,花朵的整体长度,以及花冠的长度和宽度等。许多机器学习算法为达到性能最优的目的,将属性值映射到 [0, 1] 区间,或者使其满足方差为1、平均值为0的标准正态分布,从而使得提取出的特征具有相同的度量标准。我们将在后续章节中对此做进一步的讨论。

某些属性可能存在较高的关联,因此存在一定的数据冗余。在此情况下,使用数据降维技术将数据压缩到相对低维度的子空间是非常有用的。数据降维不仅能够使得所需的存储空间更小,而且还能够使学习算法运行得更快。

为了保证算法不仅在训练数据集上有效,同时还能很好地应用于新数据,我们通常会随机地将数据集划分为训练数据集和测试数据集。我们使用训练数据集来训练及优化我们的机器学习模型,在完成后,使用测试数据集对最终的模型进行评估。

3.2 选择预测模型类型并进行评估

后续章节我们将会看到,目前已经有多种不同的机器学习算法来解决不同的问题。从 David Wolpert 的著名论断: “天下没有免费的午餐”中,我们可以总结出重要的一点: 我们无法真正免费使用学习算法1。直觉上,我们会联想到另外一个流行的谚语,“如果你手上有一把锤子,你会把所有问题都看作是钉子,我觉得这个是一种莫名的吸引力”(Abraham Maslow, 1996)。举例来说,任何分类模型都有其内在的局限性,如果我们不对分类任务预先做一些设定,没有任何一个分类模型会比其他模型更具有优势。因此在实际解决问题过程中,必不可少的一个环节就是选用几种不同的算法来训练模型,并比较它们的性能,从中选择最优的一个。在比较不同模型之前,我们需要先确定一个指标来衡量算法的性能。一个常用的指标就是分类的准确率,指的是被正确分类的样例所占的比例。

正常情况下大家会问: 我们在选择训练模型的时候没有使用测试数据集,却将这些数据用于最终的模型评估,那该如何判断究竟哪一个模型会在测试数据集和实测数据上有更好的表现?针对该问题,我们可以采用 交叉验证 技术,将训练数据集进一步分为训练子集和验证子集,从而对模型的泛化能力进行评估。不同机器学习算法的默认参数对于特定类型的任务来说,肯定不是最优的。后续章节将介绍如何使用超参优化技术来帮助我们提升训练模型的性能。直观上看,超参并不是从数据集中训练得出的参数,但却是我们借以提升模型性能的关键节点。后续章节将结合实例对这些内容进行更清晰的介绍。

3.3 模型验证与使用未知数据进行预测

在使用训练数据集构建出一个模型之后,可以采用测试数据集对模型进行测试,预测该模型在未知数据上的表现并对模型的泛化误差进行评估。如果我们对模型的评估结果表示满意,就可以使用此模型对以后新的未知数据进行预测。有一点需要注意,之前所提到的特征缩放、降维等步骤中所需的参数,只可以从训练数据集中获取,并能够应用于测试数据集及新的数据样本,但仅在测试集上对模型进行性能评估或许无法侦测模型是否被过度优化。

4. Python 在机器学习中的应用

Python 是数据科学领域最流行的编程语言之一,因此拥有大量由众多社区开发的附加扩展库。

对于计算密集型任务,尽管解释性型语言(如 Python)在性能方面不如低级语言,但使用相对低级别语言(如 Fortran 和 C 等) 开发的扩展库(如 Numpy、Scipy 等)实现了多维数组高速向量化的运算。

处理机器学习程序开发任务,我们主要使用最流行的开源机器学习库 scikit-learn 来完成。

4.1 安装 Python 包

Python 可用于主流的三大操作系统: Microsoft Windows、Mac OS X 和 Linux。所有版本的安装程序、文档均可从 Python 官网下载: https://www.python.org

本书中示例需要使用 Python 3.4.3 及以上版本,建议读者安装 Python 3 的最新版本,不过本书大部分示例程序均兼容 Python 2.7.10 及之后的版本。如果读者决定使用 Python 2.7 运行示例代码,请确保了解这两个 Python 版本之间的主要区别。连接 https://wiki.python.org/moin/Python2orPython3 ,详细地比较了 Python 3.4 和 Python 2.7 之前的差异。

本书中所用到的其他包可通过 pip 来进行安装,在 Python 3.3 中,pip 已经默认为 Python 标准库的一个组成部分。更多信息请参照链接: https://docs.python.org/3/installing/index.html

成功安装 Python 后,我们可以在终端中通过 pip 命令安装附加 Python 包:

 pip install Somepackage

已经安装的扩展包,可通过 --upgrade 选项进行更新:

 pip install Somepackage --upgrade

强烈推荐由 Continuum Analytics 开发的 Python 版本 Anaconda 来进行科学计算。Anaconda 是一款免费的、内置商业应用的 Python 版本,它已经内置了应用于数据科学、教学、工程领域所需的核心包,是一个用户友好的跨平台发行版本。Anaconda 的安装程序可通过链接 http://continuum.io/downloads/#py34 下载,链接 https://store.continuu,.io/static/img/Anaconda-Quickstart.pdf 提供其快速指南手册。

在成功安装 Anaconda 后,我们可以使用如下命令安装 Python 包:

 conda install Somepackage

可使用如下命令更新包:

 conda update Somepackage

本书主要使用 Numpy 的多维数组存储和处理数据,我们也会用到 pandas,它是一个建立在 Numpy 上、更方便处理表格类数据的附加工具包。为了使读者对数据有个直观的感觉,以提高学习体验和数据可视化的质量,我们使用了可高度定制的 matplotlib 库。

本书使用的主要的 Python 包的版本如下。请确保你选择的版本号满足此要求或者比所列版本更新,以保证示例代码能够正常运行。

  • Numpy 1.9.1
  • Scipy 0.14.0
  • scikit-learn 0.15.2
  • matplotlib 1.4.0
  • pandas 0.15.2

5. 本章小结

在本章中,我们从宏观上讨论了机器学习,并且介绍相关的重点和主要概念,后续章节会对这些问题进行更详细地探讨。

通过本章的学习,我们已经了解到,监督学习由两个重要的子领域组成: 分类和回归。其中,我们可以通过分类技术将对象划分到不同的类别中,而回归则能够对输出为连续型的目标变量进行预测。无监督学习不仅能从众多的无类标数据中发现其整体结构,同时在特征预处理阶段的数据压缩中也发挥了重要作用。

我们还简要介绍了将机器学习应用到实际工作中的具体路线图,这些内容也为后续章节中做进一步探讨和实践打好了基础。最后,还介绍了 Python 运行环境及其安装过程,并讲解了如何更新所需的包以满足机器学习实战的需要。

在下一章中,我们将实现一个分类领域最早提出的机器学习算法,并以此作为第3章的铺垫。在第3章中,将借助于开源的机器学习库 scikit-learn 来讲解更加高级的机器学习算法。既然机器学习算法是通过数据来进行学习,因此如何将有用的信息输入到算法中是至关重要的,第4章将介绍数据预处理技术的几种重要的方法。降维是数据预处理领域的一种重要技术,它使得我们可以将数据压缩到一个相对低维的特征子空间上,这对提高机器学习算法的计算效率是非常有效的,大家可以在第5章学到降维的相关内容。在第6章,大家将学习到模型评估和参数调优技术。不过,在某些情况下,即使在参数调优与测试上花费了大量的时间与精力,模型的预测性能可能仍旧无法达到我们的预期。第7章将介绍如何同通过组合不同的机器学习算法来构建一个性能更加强大的预测系统。

在掌握了机器学习领域中相关的重要概念之后,我们将了解一下机器学习在实际工作中的应用: 第8张介绍使用模型来对文本数据做情感分析;而第9章的学习,大家可以了解如何将机器学习模型嵌入到 Web 应用程序中,使其在整个网络范围得以共享。如何对目标值为连续变量的数据进行预测分析,是机器学习领域中的一个重要分支,我们将在第10章中通过回归分析来对其进行讲解。第11章则主要介绍如何通过聚类算法来发现数据中隐含的结构。本书最后将介绍神经网络,这是目前机器学习研究领域的热门话题之一,它使得我们可以解决复杂的问题,如图像和语音识别等。


  1. The Lack of A Priori Distinctions Between Learning Algorithms, D.H.Wolpert 1996; No Free Lunch Theorems for Optimization, D.H.Wolpert and W.G.Macready, 1997.)