书名:Python深度学习从原理到应用
ISBN:978-7-115-55116-0
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [美] 瓦伦蒂诺•佐卡(Valentino Zocca)
[英] 丹尼尔•斯莱特(Daniel Slater)
[意] 詹马里奥•斯帕卡尼亚(Gianmario Spacagna)
[比] 彼得•鲁兰茨(Peter Roelants)
译 王存珉 王 燕
责任编辑 吴晋瑜
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
Copyright ©Packt Publishing 2017. First published in the English language under the title Python Deep Learning (9781786464453). All rights reserved.
本书由英国Packt Publishing公司授权人民邮电出版社有限公司出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。
版权所有,侵权必究。
本书借助现实案例介绍深度学习算法的实际应用(包括最佳实践),旨在帮助读者了解如何识别和提取信息,以提高预测准确率及优化结果。
本书共10章,分别是机器学习—引言、神经网络、深度学习基本原理、无监督特征学习、图像识别、递归神经网络和语言模型、深度学习在棋盘游戏中的应用、深度学习在电子游戏中的应用、异常检测和构建一个可用于生产环境的入侵检测系统。
本书适合想深入研究深度学习算法和技术的读者学习,也适合想探究如何从这项强大技术中学到更多知识的读者参考。
瓦伦蒂诺•佐卡(Valentino Zocca)拥有罗马大学数学硕士学位,后又获得了美国马里兰大学的数学博士学位。其博士论文涉及辛几何(symplectic geometry)内容。瓦伦蒂诺曾在英国华威大学工作过一个学期,在巴黎攻读完博士后学位,他去了美国华盛顿哥伦比亚特区,在那里开始了他的职业生涯。当时,他就职于Autometric公司(后被波音公司收购),作为高级立体3D地球可视化软件设计、开发和实现方面的关键人员参与了一项高科技项目。在波音公司工作期间,他开发了许多数学算法和预测模型,并且用Hadoop实现了多个卫星图形可视化程序的自动化。源于在这一领域的积累,他成了一名机器学习和深度学习方面的专家,还曾在意大利米兰和美国纽约举办过机器学习和深度学习方面的研讨会。 瓦伦蒂诺目前居住在纽约,在一家大型金融公司担任独立顾问,负责为公司开发计量经济模型,并利用机器学习和深度学习技术创建预测模型。
詹马里奥•斯帕卡尼亚(Gianmario Spacagna)是Pirelli的一名高级数据科学家,负责处理物联网和联网车辆应用中的传感器数据和遥测数据。为了分析和开发混合动力、物理驱动和数据驱动汽车模型,他在工作岗位中跟轮胎技工、工程师以及业务部门保持着密切合作。詹马里奥擅长为数据产品构建机器学习系统以及端到端的解决方案。詹马里奥是《专业数据科学宣言》(The Professional Data Science Manifesto)的合著者,还是《数据科学》(Data Science)米兰活动社区的创始人,他热衷于在社区推行最佳实践和有效方法。 詹马里奥拥有意大利都灵理工学院远程信息处理技术硕士学位和瑞典皇家理工学院分布式系统软件工程学士学位。在加入倍耐力公司之前,他在零售和商业银行(巴克莱银行)、网络安全(思科公司)、预测营销(安捷隆公司)等行业工作。
丹尼尔•斯莱特(Daniel Slater)的编程生涯始于11岁——为id Software公司的《雷神之锤》(Quake)游戏开发插件。出于对编程的痴迷,他成了游戏行业热门系列电子游戏《锦标赛经理人》(Championship Manager)的开发人员。后来,他转战金融行业,从事高风险、高性能信息系统方面的工作。 丹尼尔•斯莱特目前是Skimlinks的一名工程师,从事了解在线用户行为的大数据工作。他喜欢参加一些与深度学习和强化学习相关的技术会议,还利用业余时间来训练人工智能在游戏中打败计算机。
感谢我的妻子尤迪特•科洛(Judit Kollo)给予我的爱与支持。感谢我的儿子大卫(David)、我的母亲凯瑟琳(Catherine)以及我的父亲唐(Don)。
彼得•鲁兰茨(Peter Roelants)拥有比利时鲁汶大学计算机科学硕士学位,主攻人工智能领域。他擅长将深度学习应用于各种问题,例如光谱成像、语音识别、文本理解和文档信息提取)。 目前,他在Onfido公司担任数据提取研究小组组长,主要从事提取官方文件数据的工作。
马克斯•帕普拉(Max Pumperla)拥有德国汉堡大学代数几何博士学位,是一名专攻深度学习及其应用的数据科学家兼工程师,目前在德国一家名为Collect的人工智能公司担任数据科学主管。他在银行、在线营销和 SMB 等领域有丰富的经验,还作为几个Python程序包的开发者和维护者,为Keras和Hyperopt等机器学习库提供技术支持。
随着人工智能在全球的兴起,深度学习受到了公众的极大关注。如今,深度学习算法的应用几乎遍及各行各业。本书通过现实案例给出关于这一主题的实用信息(包括最佳实践)。通过阅读本书,读者可以了解如何学会识别和提取信息,以提高预测准确率及优化结果。
本书先简要介绍机器学习相关的重要概念,然后深入研究如何运用scikit-learn的深度学习原理,接着介绍如何使用最新的开放源代码库,如Theano、Keras、谷歌的TensorFlow以及H2O。本书还揭示了模式识别的难点,旨在帮助读者以更高的准确率缩放数据以及探讨深度学习算法和技术。本书适合想深入研究深度学习算法和技术的读者学习,也适合想探究如何从这项强大技术中学到更多知识的读者参考。
第 1 章“机器学习——引言”:介绍不同的机器学习方法和技术以及它们在现实问题中的一些应用,还介绍一种用于机器学习的Python主要开源包——scikit-learn。
第 2 章“神经网络”:正式介绍什么是神经网络。本章详细讲解神经元是如何工作的,旨在让读者了解如何通过堆叠多层创建并使用深度前馈神经网络。
第 3 章“深度学习基本原理”:引导读者理解什么是深度学习以及深度学习和深度神经网络之间是相关联的。
第 4 章“无监督特征学习”:介绍两种强大、常用的无监督特征学习体系——自编码器和受限玻尔兹曼机。
第 5 章“图像识别”:先通过类比形式说明视觉皮层是如何工作的,然后介绍什么是卷积层,最后对它们为何有效做出直观描述。
第 6 章“递归神经网络和语言模型”:讨论在很多任务(如语言建模和语音识别)中很有应用前景的强大方法。
第 7 章“深度学习在棋盘游戏中的应用”:内容涵盖解决棋盘游戏的不同工具(如跳棋和国际象棋)。
第 8 章“深度学习在电子游戏中的应用”:介绍有关训练人工智能玩电子游戏的更复杂的问题。
第 9 章“异常检测”:讲解异常点检测和异常检测这两个概念的区别和联系。本章先引导读者进行虚构欺诈案例的研究,然后列举一些示例,给出在现实应用中存在异常的危险以及自动快速检测系统的重要性。
第10章“构建一个可用于生产环境的入侵检测系统”:利用H2O和一般常见实践来针对生产中的部署构建可扩展分布式系统。本章介绍如何使用Spark和MapReduce训练深度学习网络、如何使用自适应学习技术加快收敛,以及(非常重要的一点)如何验证模型和评估端到端传递途径。
本书内容适用于Windows、Linux和mac OS操作系统。为了能够顺利地完成本书内容的学习,读者应提前了解TensorFlow、Theano、Keras、Matplotlib、H2O、scikit-learn等方面的知识,还应有一定的数学基础(已掌握微积分和统计学专业的概念性知识)。
为了便于区分许多不同类型信息,本书使用了不同的字体样式。下面列出了关于这些字体样式的一些示例及其含义的解释。
对正文中的代码、数据库表名称、文件夹名称、文件名、文件扩展名、路径名、虚拟统一资源定位符(URL)、用户输入和Twitter句柄以代码体样式显示,例如:应立即清除上述图表中的代码,只关注导入cm的代码行。
代码块以如下样式设置:
(X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
X_train = X_train.reshape(50000, 3072)
X_test = X_test.reshape(10000, 3072)
input_size = 3072对于需要提醒读者注意代码块的某个特定部分,以粗体显示相关代码行或项:
def monte_carlo_tree_search_uct(board_state, side, number_of_
rollouts):
    state_results = collections.defaultdict(float)
    state_samples = collections.defaultdict(float)命令行输入或输出以如下形式给出:
****git clone https://github.com/fchollet/keras.git
cd keras
python setup.py install新术语和重要词汇以黑体显示。
警告或重要提示以这种框的形式呈现。
提示和技巧以这种方式显示。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书为读者提供源代码。要获得以上配套资源,请在异步社区本书页面中单击 ,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎读者将发现的问题反馈给我们,帮助我们提升图书的质量。
如果读者发现错误,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可。本书的作者和编辑会对读者提交的勘误进行审核,确认并接受后,将赠予读者异步社区的100积分(积分可用于在异步社区兑换优惠券、样书或奖品)。
我们的联系邮箱是contact@epubit.com.cn。
如果读者对本书有任何疑问或建议,请发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果读者有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线投稿(直接访问www.epubit.com/ selfpublish/submission即可)。
如果读者来自学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果读者在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请将怀疑有侵权行为的链接发邮件给我们。这一举动是对作者权益的保护,也是我们持续为读者提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近 40 年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、人工智能、测试、前端、网络技术等。
异步社区
微信服务号
“‘机器学习(CS229)’是斯坦福大学最受欢迎的课程”——这是劳拉•汉密尔顿(Laura Hamilton)在《福布斯》(Forbes)杂志上发表的一篇文章的开头,接下来的内容是:“为什么?因为机器学习正在逐步‘吞噬’这个世界。”
机器学习技术的确被应用到了各种不同领域,而且目前很多行业都在招募数据专家。借助机器学习,我们能够找到可获取那些在数据中并不明显的知识的进程,进而做出决策。机器学习技术的应用范围非常广泛,适用于医学、金融和广告等不同领域。
本章将介绍不同的机器学习方法和技术以及它们在现实问题中的应用,还将介绍用于机器学习的主要Python开源包:scikit-learn。本章将为读者学习后续章节奠定基础。后续章节将重点介绍如何使用神经网络模拟大脑功能的具体机器学习方法(尤其是深度学习)。相比20世纪80年代,如今的深度学习更多地利用了高级神经网络,这不仅得益于理论方面的最新发展,还得益于计算机速度的进步以及图形处理单元(GPU)的应用,而不是传统的计算处理单元(Computing Processing Unit,CPU)的应用。本章主要概述机器学习的定义和作用,旨在帮助读者更好地理解深度学习与传统机器学习技术之间的区别。
本章涵盖以下主题:什么是机器学习、不同的机器学习方法、机器学习系统所涉及的步骤、关于流行技术/算法的简介以及在现实生活中的应用和流行开源包。
机器学习是一个经常与“大数据”和“人工智能”(简称AI)等一并出现的术语,但它与其他二者有着很大的不同。要理解什么是机器学习以及它为什么有用,关键要理解:什么是大数据以及机器学习如何应用于大数据。大数据是一个用于描述大量数据集的术语,而数据集是通过大量聚集和保存的数据创建起来的,例如,通过摄像头、传感器或互联网社交网站产生的数据。据估计,仅仅谷歌公司每天就能处理超过20PB的信息,而且这个数字还会增加。IBM公司估计每天都会产生2500PB的数据,而且世界90%的数据都是最近两年创建的。
显然,如此庞大的数据,单靠人类是无法掌握的,更不用说分析了。不过,这一切可以利用机器学习技术来实现。机器学习是一种可被用于处理大规模数据的手段,并且非常适合处理具有大量变量和特征的复杂数据集。许多机器学习技术(尤其是深度学习)的优点之一是:当被用于大型数据集以改善数据集分析和预测能力时,其性能最佳。换句话说,当机器学习技术(尤其是深度学习神经网络)能够访问大型数据集以便发现数据中所隐藏的模式和规律时,其“学习”效果最佳。
此外,机器学习的预测能力非常适用于人工智能系统。在人工智能系统中,机器学习可被视为“大脑”,而人工智能可被定义为(尽管这个定义可能并不是唯一的)一个可以与其环境交互的系统:人工智能机器拥有传感器,通过该传感器,它们能够了解自己所处的环境以及与其相关联的工具。因此,机器学习是一个允许机器通过其传感器分析数据进而明确给出恰当答案的大脑。举一个简单的例子:iPhone的Siri。Siri通过麦克风接收指令并通过扬声器或显示屏输出答案。但为实现这一点,Siri需要“理解”所接收的内容进而给出正确的答案。同样,无人驾驶汽车会配备摄像头、GPS系统、声呐和激光雷达,但所有这些信息需要处理才能给出正确答案,即是否加速、刹车、转弯等。机器学习就是指能够得出答案的信息处理。
“机器学习”一词应用得非常广泛,它是指从大数据集中推断出模式的通用技术或者基于通过分析现有已知数据所获得的知识来对新数据进行预测的能力。这是一个非常宽泛的定义,并且涵盖了许多不同技术。机器学习技术可大致分为两大类:监督学习和无监督学习。不过,在这两大类的基础上,经常会增加一个名为“强化学习”的分类。
第一类机器学习算法称为监督学习。监督学习算法是利用一组标记数据来对相似未标记数据进行分类的一类机器学习算法。标记数据是指已分类的数据,未标记数据是指尚未完成分类的数据。大家看到的标记不是离散的,就是连续的。为了更好地理解这个概念,我们来看一个示例。
假设用户每天都收到大量的电子邮件,包括一些重要的商务邮件以及一些来路不明的垃圾邮件。监督学习算法将被提供已由用户标记为垃圾邮件或非垃圾邮件的大量电子邮件。该算法将遍历所有标记数据,并预测电子邮件是否为垃圾邮件。这意味着该算法会检查每个示例,并针对每个示例做出其是否为垃圾邮件的预测。通常,该算法在首次遍历所有未标记数据时,会对许多邮件做出错误标记,并且标记过程可能会执行得相当糟糕。然而,在每次运行之后,算法都会将预测结果与期望结果(已标记数据)进行比较。通过这一比较过程,该算法将学会提高自身的性能和准确率。如前所述,这种算法依赖于大量数据,通过大量数据,它会更好地学会什么特征(或特性)会导致每封邮件被归类为垃圾邮件或者非垃圾邮件。
在标记数据(通常也称为训练数据)上遍历一定时间之后,该算法的准确率将不再提高,然后,可将其应用于新邮件,以测试其在识别新的未标记数据时的准确率。
在所用到的示例中,我们描述了一个过程:在该过程中,算法从标记数据(被归类为垃圾邮件或非垃圾邮件的电子邮件)学习进而对新的未标记电子邮件做出预测。但重要应该注意的是:可以将这一过程推广到两个以上的类别,例如,可以运行软件并在一组标记邮件上对其进行训练,其中,标记邮件包括个人邮件、公司/工作邮件、社交或垃圾邮件。
事实上,Gmail(谷歌提供的免费电子邮件服务)允许用户最多选择5个类别,分别标记如下。
(1)常用。包括私人邮件往来。
(2)社交。包括来自社交网络和媒体共享网站的信息。
(3)促销。包括促销邮件、优惠及折扣。
(4)更新。包括账单、银行对账单及收据。
(5)论坛。包括来自在线群组和邮件列表的消息。
有时,结果可能并非是离散的,并且可能会没有有限数量的类别用于进行数据分类,例如,可以尝试基于预先设定的健康参数来预测一群人的寿命。在本示例中,结果是一个连续函数(可以将预期寿命指定为一个表示某人有望存活的年数的实数),因此需要讨论回归问题(不再讨论分类任务)。
一种考虑监督学习的方法是:想象一下要在数据集上建立一个函数 。数据集将由按特征组织起来的信息组成。在电子邮件分类的示例中,垃圾邮件中的某些特征可能会是比其他特征出现频率更高的特定词汇。如果使用了与“性”的相关词汇,很可能会导致一封邮件被识别为垃圾邮件,而非商务/工作邮件。相反,诸如“会议”“公司”和“演示”等词汇更可能被识别为工作邮件。如果能够访问元数据,可以利用发送者信息来更好地分类电子邮件。此外,每封电子邮件将关联一组特征并且每个特征会有一个值(在本示例中,该值是指特定词汇在邮件正文中出现了多少次)。然后,机器学习算法会将这些值映射到一个表示类别集的离散范围,或者(在回归案例中)映射到一个实值。算法将遍历许多示例,直到它能够定义一个最佳函数来正确匹配大多数标记数据。然后,算法能在无人干预的情况下,对未标记数据进行预测。函数定义如下:
。数据集将由按特征组织起来的信息组成。在电子邮件分类的示例中,垃圾邮件中的某些特征可能会是比其他特征出现频率更高的特定词汇。如果使用了与“性”的相关词汇,很可能会导致一封邮件被识别为垃圾邮件,而非商务/工作邮件。相反,诸如“会议”“公司”和“演示”等词汇更可能被识别为工作邮件。如果能够访问元数据,可以利用发送者信息来更好地分类电子邮件。此外,每封电子邮件将关联一组特征并且每个特征会有一个值(在本示例中,该值是指特定词汇在邮件正文中出现了多少次)。然后,机器学习算法会将这些值映射到一个表示类别集的离散范围,或者(在回归案例中)映射到一个实值。算法将遍历许多示例,直到它能够定义一个最佳函数来正确匹配大多数标记数据。然后,算法能在无人干预的情况下,对未标记数据进行预测。函数定义如下:
f:space of features→classes = (discrete values or real values)
也可以将分类视为一个尝试分离不同组的数据点的过程。一旦完成了特征定义,数据集中的任意示例(如电子邮件)会被看作特征空间中的一个点,而这其中的每个点都代表一个不同的示例。机器学习算法的任务是:绘制一个超平面(即高维空间中的一个平面)来分离具有不同特征的点,就像分离非垃圾邮件和垃圾邮件一样。
虽然在图1-1所示的二维情况下,这看起来可能微不足道,但在数百或数千维度情况下,则可能会变得非常复杂。
图1-1 二维情况下的分类数据点
后续章节会给出一些分类或回归问题示例。接下来我们讨论的一个问题是关于数字分类的。给定一组图形(以0~9表示),机器学习算法将对分配给它的每个图形(其所描述的数字)进行分类。对于此类示例,我们将利用经典数据集MNIST。在本示例中,每个手写数字都由一个具有784(28×28=784)个像素的图形来表示,并且因为需要对每10个数字进行分类,所以需要在一个784维空间中绘制出9个单独的超平面。来自MNIST数据集的手写数字示例,如图1-2所示。
图1-2 来自MNIST数据集的手写数字示例
第二类机器学习算法称为无监督学习。在这种情况下,不再事先标记数据,而是通过算法得出结论。最常见且最简单的无监督学习示例之一就是聚类。这是一种尝试将数据分成子集的技术。
举例来说,在前面所讲到的垃圾邮件/非垃圾邮件示例中,算法能够找到所有垃圾邮件的通用元素(如出现拼错的单词)。虽然这种算法可能会比随机分类更好,但并不清楚垃圾邮件/非垃圾邮件是否能够被如此简单地分开。用算法分离数据的子集是不同于数据集的类别。为了使得聚类可行,原则上,每个聚类中的每个元素都应该具有较高的类内相似性和较低的类间相似性。聚类适用于任意数量的类别,聚类算法背后的理念(如 均值)则是:找到原始数据的
均值)则是:找到原始数据的 子集,并且与类外的任何元素相比,这些原始数据元素之间会更接近(更相似)一些。当然,为了做到这一点,需要解释一下什么是更接近或更相似,也就是说,需要定义某种度量标准以便确定点之间的距离。
子集,并且与类外的任何元素相比,这些原始数据元素之间会更接近(更相似)一些。当然,为了做到这一点,需要解释一下什么是更接近或更相似,也就是说,需要定义某种度量标准以便确定点之间的距离。
图1-3所示的是将一组点分为3个子集。
图1-3 将一组点分为3个子集
给定数据集的元素无须聚在一起来形成有限集。此外,聚类也可能包括给定数据集的无界子集,如图1-4所示。
图1-4 该聚类包括给定数据集的无界子集
聚类并不是唯一的无监督学习算法。读者会注意到,深度学习近期的成功与其在无监督学习任务中的有效性是分不开的。
每一天都会有很多新数据被创建出来,而且对所有新数据进行标记是一件非常费力且耗时的事情。无监督学习算法的一大优点是:不需要标记数据。无监督深度学习算法(例如受限玻尔兹曼机)是通过从数据中提取特征来实现的。举个例子,通过使用MNIST数据集,受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)将提取每个数字的独特特征,检测每个数字的直线和曲线形状。无监督学习的运行是通过揭示数据中的隐藏结构以允许对其进行分类(而非进行标记)来实现的。
此外,可以借助深度信念网络(Deep Belief Network,DBN)和监督学习来改进无监督学习算法的性能。
第三类机器学习算法称为强化学习。这种算法的运行原理不同于监督学习,虽然该算法仍然是使用反馈元素来提高性能。强化学习算法的常见应用是教机器如何玩游戏:在这种情况下,不再将每个移动标记为好或坏,而是标记来自游戏的反馈,包括游戏结果或者游戏期间的信号,如得分或者失分。赢得比赛会显示一个积极结果,类似于识别正确数字或者识别电子邮件是否为垃圾邮件;输掉比赛则需要更进一步的“学习”。强化学习算法倾向于重复使用那些曾带来成功结果的动作,例如促使在游戏中获胜的动作。然而,在未知领域,算法必须尝试新动作,从这些动作中,算法会基于结果更深入地学习游戏的结构。由于在通常情况下,动作都是相互关联的,因此不是那种能以“好”或“坏”进行评价的单一行动,而是可以进行评价的行动整体动态。类似于在下棋时偶尔会牺牲小卒以保全棋盘布局可能会被视为一种积极做法,即使通常损失一子是不利结果,但在强化学习中,这种做法是所要探究的整个问题及其目标。例如,移动清扫机器人可能不得不决定自己是继续清扫房间还是返回充电站,并且这类决定的做出要基于其能够在电池耗尽之前找到充电站这一前提。在强化学习中,基本思路是奖赏。在这种情况下,算法会努力最大化其所收到的奖赏。
强化学习可用于经典的井字游戏。在这种情况下,棋盘上的每个位置都关联一个概率(一个值)。该值是指基于先前经验(预测)在某个状态赢得游戏的概率。刚开始时,每个状态的概率都设为50%,也就是说,假设开始时我们拥有从任何位置赢得比赛和输掉比赛的相同概率。一般说来,机器会尝试移向数值更高的位置以便赢得比赛;如果输了游戏,机器则会重新评估这些位置。在每个位置上,机器都会根据可能结果(而非固定的确定规则)来做出选择。当机器继续进行游戏时,这些概率将会得到细化,并且会基于位置输出更高或更低的成功概率。
到目前为止,我们已经探讨了不同的机器学习方法并且将这些方法大致分为三大类。典型的机器学习的另一重要方面是:理解数据,以便更好地理解手头上的问题。为了应用机器学习,需要定义的重要方面可大致描述如下。
(1)学习器。这代表着所用到的算法以及其“学习哲学”。正如在下文会看到的一样,针对不同的学习问题,总有许多可供使用的不同机器学习算法。学习器的选择很重要,因为不同问题需要不同的机器学习算法。
(2)训练数据。这是指大家感兴趣的原始数据集。对于无监督学习,这些数据可以不加标记;对于监督学习,这些数据可以有标记。对学习器而言,重要的是要有足够的样本数据供其了解问题的结构。
(3)表示法。这是指为了能被学习器摄取到,如何根据所选特征来表示数据。举例来说,如果要尝试使用图形对数字进行分类,这就表示用于描述图形像素的数组。要获得更好的结果,重要的是要正确选择数据的表示法。
(4)目的。这是指就手头问题向数据学习的理由。它与目标严格相关,并且可帮助我们明确如何使用学习器、应该使用什么学习器以及要使用什么表示法。例如,目的可能会是清除邮箱中不想收到的电子邮件,那么目的就是为学习器定义目标(如检测垃圾邮件)。
(5)目标。这是指正在学习以及最终输出的是什么。它可能是一个无标记数据分类,可能是依据隐藏模式或特征的输入数据表示法,可能是一个未来预测模拟器,可能是对外部刺激的一个反应,也可能是强化学习情况下的策略。
虽然任何机器学习算法都无法达到完美的数值描述,只能达到目标的近似值,但是怎么强调机器学习算法的重要性都不为过。机器学习算法并不是问题的精确数学解答,而是一个近似值。在上文中,我们已将学习定义为一个从特征(输入)空间到类别范围的函数,稍后将带领大家了解一些机器学习算法(如神经网络)如何被证明能够任意程度地近似任何函数(理论上)。这被称为“万能近似定理”,不过该定理并不意味着我们可以得到问题的精确解。此外,更好地理解训练数据可以更好地找到问题答案。
一般来说,通过经典机器学习方法解决问题之前,我们可能需要透彻地理解和清理训练数据。解决机器学习问题所需要的步骤大致如下。
(1)数据收集。这意味着要收集尽可能多的数据,以及(在监督学习问题中)正确标记。
(2)数据处理。这意味着清理数据(例如,删除冗余或高度相关的特征,或者填补缺失数据),以及理解训练数据的特征。
(3)测试用例的创建。数据通常可被分为两到三个数据集:一个训练数据集——用来训练算法,以及一个测试数据集——在训练算法之后用来测试算法的准确率。通常,还会创建一个验证数据集,在反复完成多次训练测试程序并且对最终结果感到满意之后,会在该数据集上进行最终测试(或验证)。
测试数据集和验证数据集的创建是基于正当理由的。如前所述,机器学习算法只能产生预期结果的近似值。这是因为我们通常只能包含有限数量的变量而且可能会有许多变量超出了我们的控制范围。如果只使用单个数据集,模型可能会以“记住”数据而终止,并在其拥有记忆的数据上产生极高的准确率,但是这个结果可能无法在其他类似数据集上重现。对机器学习算法的关键预期之一是它们的可推广性。这就是为什么要创建一个测试数据集(用于在训练之后调优模型选择)和一个验证数据集(仅在流程结束时用于证实所选算法的有效性)。
我们需要理解选择数据中有效特征的重要性以及避免“记忆”数据的重要性(用更专业的术语来说,是指文献中的“过度拟合”,且在下文中,将其称为“过拟合”)。以一个笑话为例:“在1996年之前,还没出现任何一位总统候选人能够在没有任何实战经验的情况下,击败任何一个名字在拼字游戏中更有价值的人。”很显然在本示例中“规则”是毫无意义的,它强调了选择有效特征的重要性(一个名字在拼字游戏中值多少钱与选总统存在任何关系吗?)。选取自由特征作为预测因子虽然可以预测当前数据,却不能被用作更普遍数据的预测因子。这一点在52次选举中均得到验证,只是一种巧合而已吗?这就是通常所谓的“过拟合”,它使得预测完全符合手头数据,却不能被推广到更大的数据集。过拟合是这么一个过程,它会使通常被称为“噪声”(即没有任何实际意义的信息)的事物变得有意义,并且会将模型与小扰动相拟合。
再来看一个例子:尝试用机器学习算法来预测一个球从地面向上(不是垂直地)抛向空中,直到它再次落回地面的轨迹,如图 1-5 所示。通过物理学知识,我们知道球的轨迹是抛物线形状的,并且认为一个好的观察过成千上万次此类投掷的机器学习算法会得出一个抛物线作为答案。然而,如果将球放大并观察球体由于湍流而在空气中产生的最小波动,就可能会注意到:球体并没有保持稳定的轨迹,而是可能会受到小的扰动的影响。这就是所谓的“噪声”。试图对这些小扰动建模的机器学习算法无法看到大局,因而难以产生一个令人满意的结果。换言之,过拟合是一个会使机器学习算法看到树而忘记森林的过程。
图1-5 好预测模型与坏(过拟合)预测模型——关于从地面抛起的球的轨迹
这就是要将训练数据与测试数据分开的原因:如果测试数据的准确率不同于在训练数据上所获得的结果,就是模型过拟合的迹象。当然,也需要确保不会犯相反的错误,即欠拟合,如图1-6所示。然而,如果在实践中的目标是使得训练数据上的预测模型尽可能精确,相对于过拟合而言,欠拟合的风险要小得多,因此要格外小心,避免出现模型的过拟合。
图1-6 欠拟合也可能是个问题
除了根据算法的“学习风格”对其进行分组,即在本章开头所讨论到的3个类别(监督学习、无监督学习和强化学习),我们还可以根据实现对它们进行分组。显然,可以通过使用不同的机器学习算法来实现前述的每个类别,例如存在许多不同的监督学习算法,其中每一种算法都可能最适合特定分类或手头的回归任务。事实上,分类和回归之间的差别是最关键的一点,并且了解正在努力完成的任务是什么也很重要。
以下并非各种机器学习方法的全部列表或详尽描述,它们只是Sebastian Rashka的Python Machine Learning一书中给出的可以参考的列表或描述,更确切地讲,这是一个为读者提供不同技术的简单说明,以便让读者了解深度学习跟这些技术之间的区别。在后续章节中,读者将看到深度学习不仅是另一种机器学习算法,它与机器学习算法有实质性不同。
我们将介绍回归算法(线性回归)、经典分类器(如决策树、朴素贝叶斯和支持向量机)和无监督聚类算法(如 均值)以及强化学习技术(交叉熵方法),以便对现有机器学习算法的种类做出简单说明,并通过介绍神经网络结束该列表的讲解——这是本书的重点内容。
均值)以及强化学习技术(交叉熵方法),以便对现有机器学习算法的种类做出简单说明,并通过介绍神经网络结束该列表的讲解——这是本书的重点内容。
回归算法是利用输入数据的特征来预测数值的一种监督算法,例如:基于给定某特征(如卫生间大小、使用年限以及数量、层数、位置等)考虑房屋成本。回归分析尝试找到最适合输入数据集的函数的参数值。在线性回归算法中,目的是要最小化成本函数,方法是:通过输入数据为函数找到最近似目标值的适当参数。成本函数是关于误差的函数,而误差是指我们距离得到正确结果有多远。所用到的一个代表性成本函数是均方误差,即期望值和预测结果之差的平方。所有输入示例之和给出了算法的误差并且它代表着成本函数。
假设有一栋带有3个浴室、面积为100m2的两层房子(建于25年前)。此外,假设将房子所处的城市分成10个不同区域并用1到10的整数来表示每个区域,并且假设这个房子位于以“7”表示的区域内,那么可以用5维向量 = (100,25,3,2,7)来对这个房子进行参数化。另外,假设已知这个房子的估计价值为10万欧元。接下来,想要实现的是:创建一个函数
 = (100,25,3,2,7)来对这个房子进行参数化。另外,假设已知这个房子的估计价值为10万欧元。接下来,想要实现的是:创建一个函数 ,即
,即 = 100000。
= 100000。
在线性回归中,这表示找到一个使100 ×  + 25 ×
+ 25 ×  + 3 ×
 + 3 ×  + 2 ×
 + 2 ×  + 7 ×
+ 7 ×  = 100000成立的向量
= 100000成立的向量 = (
 = ( 、
、 、
、 、
、 、
、 )。如果有1000栋房子,可以针对每栋房子重复同样的步骤,并且在理想情况下,可以找到针对每栋房子预测其正确值(或者足够接近数值)的一个向量
)。如果有1000栋房子,可以针对每栋房子重复同样的步骤,并且在理想情况下,可以找到针对每栋房子预测其正确值(或者足够接近数值)的一个向量 。假设最初选择某随机值
。假设最初选择某随机值 ,如果
,如果 = 100 ×
= 100 ×  + 25 ×
 + 25 ×  + 3 ×
 + 3 ×  + 2 ×
 + 2 ×  + 7 ×
 + 7 ×  = 100000不可能成立,那么可以计算误差 = [100000−
 = 100000不可能成立,那么可以计算误差 = [100000− ]2。这是针对一个示例
]2。这是针对一个示例 的平方误差,并且所有示例的所有平方误差的平均值代表着成本,即函数跟实值之间的差异大小。因而,目标是最小化这个误差,为此需要计算成本函数相对于
的平方误差,并且所有示例的所有平方误差的平均值代表着成本,即函数跟实值之间的差异大小。因而,目标是最小化这个误差,为此需要计算成本函数相对于 的导数
的导数 。
。
导数表示函数增加(或减少)的方向,因此向导数相反方向移动 会提高函数的准确率。向成本函数最小值方向移动(这代表着误差),这是线性回归的要点。当然,我们需要确定应该以多快的速度沿导数方向移动,因为导数只表示方向。成本函数不是线性的,所以我们需要确保只在导数所指示的方向上移动小步长。移动太大步长可能会致使移动范围超出最小值,从而导致无法收敛到最小值。这个步骤的步长称为学习率,其大小以符号“lr”来表示。
会提高函数的准确率。向成本函数最小值方向移动(这代表着误差),这是线性回归的要点。当然,我们需要确定应该以多快的速度沿导数方向移动,因为导数只表示方向。成本函数不是线性的,所以我们需要确保只在导数所指示的方向上移动小步长。移动太大步长可能会致使移动范围超出最小值,从而导致无法收敛到最小值。这个步骤的步长称为学习率,其大小以符号“lr”来表示。
因此,通过设置 =
 =  −
 −  *
*  ,我们可以改进
,我们可以改进 的选择进而取得更好的解决方案。多次重复此过程将会生成可代表函数
的选择进而取得更好的解决方案。多次重复此过程将会生成可代表函数 的最佳可能选择的值
的最佳可能选择的值  。但应该强调的是:此过程仅局部适用,并且如果空间不是凸面的,则无法通过该过程找到全局最佳值。如图1-7所示,如果存在许多局部极小值,算法可能会陷入其中一个局部极小值,并且无法避开该值进而达到误差函数的全局最小值,这类似于一个小球从山上向下移动时可能会陷入一个小山谷并且因此永远无法到达山脚一样。
。但应该强调的是:此过程仅局部适用,并且如果空间不是凸面的,则无法通过该过程找到全局最佳值。如图1-7所示,如果存在许多局部极小值,算法可能会陷入其中一个局部极小值,并且无法避开该值进而达到误差函数的全局最小值,这类似于一个小球从山上向下移动时可能会陷入一个小山谷并且因此永远无法到达山脚一样。
图1-7 图(a)是凸面的,因此它只有一个最小值。在图(b)中,函数有两个局部极小值,
 因此可能会找到并非全局最小值的第一个局部极小值
另一种使用广泛的监督算法是决策树算法。决策树算法会创建树形结构的分类器。决策树的组成包括:在具体特征上执行测试的决策节点,以及说明目标属性的值的叶节点。决策树是一种分类器,它从根节点开始沿着决策节点向下移动,直至到达叶节点。
该算法的一个经典应用是鸢尾花数据集,该数据集包含来自3种鸢尾花(山鸢尾花、弗吉尼亚鸢尾和变色鸢尾)的50个样本的数据。创建该数据集的Ronald Fisher对这些花的不同特征(萼片的长度和宽度以及花瓣的长度和宽度)进行了测量。基于这些特征的不同组合,我们可以创建一个决策树来确定每一朵花属于哪个种类。这里将仅使用这些特征中的两个(花瓣长度和宽度)来描述一个简单的可用于正确分类几乎所有花朵的简化决策树。
我们从第一个节点开始,针对花瓣长度创建第一次测试:如果花瓣长度小于 2.5cm,则该花朵属于山鸢尾花品种。事实上,我们通过测试可以将所有山鸢尾花正确地分类出来——这种花的花瓣长度均小于 2.5cm。因而我们到达叶节点,按测试结果将该节点标记为:山鸢尾花。如果花瓣长度大于2.5cm,则取不同分支,且到达一个新的决策节点,在该新节点处,测试花瓣宽度是否小于1.8cm。如果花瓣宽度大于或等于1.8cm,则到达一个叶节点,在该叶节点,将花朵分类为弗吉尼亚鸢尾;否则,将到达一个新的决策节点,在该新节点,再次测试花瓣长度是否大于4.9cm。如果是的话,会到达一个被标记为弗吉尼亚鸢尾的叶节点;否则,会到达另一个被标记为变色鸢尾的叶节点。
所讨论的决策树模型如图1-8所示。其中,左侧分支反映了测试在决策节点中的肯定答案,右侧分支则反映了测试在决策节点中的否定答案。每个分支的结束节点均为叶节点。
图1-8 决策树模型
该示例显示出决策树算法和线性回归算法有多么不同。此外,我们在介绍神经网络时,会给出一个关于神经网络是如何通过使用相同数据集运行的示例。在那个示例中,我们还将提供Python代码并展示一些图像,以说明神经网络如何根据花朵的特征来对其完成分组。
 均值聚类
均值聚类正如前面所讨论的,聚类算法是一种无监督机器学习方法。最常见的聚类算法称为 均值聚类,它是一种通过将数据集中每个元素分组为
均值聚类,它是一种通过将数据集中每个元素分组为 个不同子集(因此名称中出现
个不同子集(因此名称中出现 )的方式来实现对元素分类的聚类技术。
)的方式来实现对元素分类的聚类技术。 均值聚类是一个相对简单的过程:选择代表
均值聚类是一个相对简单的过程:选择代表 子集不同中心的随机
子集不同中心的随机 点(称为质心),然后可为每个质心选择距离其最近的所有点。这样将会创建
点(称为质心),然后可为每个质心选择距离其最近的所有点。这样将会创建 个不同的子集。此时,对于每个子集,将重新计算中心。于是,又有了
个不同的子集。此时,对于每个子集,将重新计算中心。于是,又有了 个新质心,然后重复上面的步骤,从而为每个质心选择最接近质心的点的新子集。不断重复这个过程,直到质心停止移动。
个新质心,然后重复上面的步骤,从而为每个质心选择最接近质心的点的新子集。不断重复这个过程,直到质心停止移动。
显然,要运行该算法,我们需要能够确定一个度量标准,以便计算点之间的距离。这个过程总结如下。
(1)选择初始 点(称为质心)。
点(称为质心)。
(2)将最近的质心关联到数据集中的点。
(3)计算与特定质心相关联的点集的新中心。
(4)将新中心定义为新质心。
(5)重复步骤3和步骤4,直到质心停止移动。
需要注意的是,这种方法对随机质心的初始选择很敏感,并且针对不同初始选择重复该过程可能是一个好办法。此外,一些质心和数据集中的任何点可能都达不到最接近状态,因此会导致子集的数目低于 个。值得一提的是,如果在上面所讨论的决策树的示例中使用了
个。值得一提的是,如果在上面所讨论的决策树的示例中使用了 = 3的
= 3的 均值,对于鸢尾花数据集,可能无法得到和使用决策树时相同的分类,这再次强调了针对每个问题仔细选择以及使用正确的机器学习方法是多么重要。
均值,对于鸢尾花数据集,可能无法得到和使用决策树时相同的分类,这再次强调了针对每个问题仔细选择以及使用正确的机器学习方法是多么重要。
现在,我们来讨论使用 均值聚类的一个示例。假设一个比萨饼配送点计划在一个新的城市开设4家新的专营店,需要为这4家新店选择位置。通过使用
均值聚类的一个示例。假设一个比萨饼配送点计划在一个新的城市开设4家新的专营店,需要为这4家新店选择位置。通过使用 均值聚类可以很容易地解决这个问题。想法就是:找出最常点比萨饼的地方,并以此作为数据点。接下来,随机选择4个可供选择的地点。通过使用
均值聚类可以很容易地解决这个问题。想法就是:找出最常点比萨饼的地方,并以此作为数据点。接下来,随机选择4个可供选择的地点。通过使用 均值聚类算法可以在稍后确定4个最佳位置,以便使新网点到每个配送地点的距离最小。这是
均值聚类算法可以在稍后确定4个最佳位置,以便使新网点到每个配送地点的距离最小。这是 均值聚类可以帮助解决业务问题的一个示例(见图1-9)。
均值聚类可以帮助解决业务问题的一个示例(见图1-9)。
图1-9 图(a)是最经常配送比萨的地点分布,图(b)中的圆点表示这些新店应该选择的
 位置及相应的配送区域
朴素贝叶斯(Naive Bayes)算法不同于许多其他机器学习算法。从概率上讲,大多数机器学习算法尝试评估的都是在给定条件 时某个事件
时某个事件 的概率,我们用
的概率,我们用 来表示。例如,给定表示数字的图片(即具有一定像素分布的图片),那么,该数字为5的概率是多少?如果像素分布接近于其他被标记为“5”的示例的像素分布,则该事件的概率将会很高;否则,概率将会很低。
来表示。例如,给定表示数字的图片(即具有一定像素分布的图片),那么,该数字为5的概率是多少?如果像素分布接近于其他被标记为“5”的示例的像素分布,则该事件的概率将会很高;否则,概率将会很低。
有时,会有相反信息,即假设知道有一个事件 ,就会知道样本为
,就会知道样本为 的概率。朴素贝叶斯定理指出:
的概率。朴素贝叶斯定理指出: ,其中
,其中 表示在给定
表示在给定 时生成示例
时生成示例 的概率,这也是朴素贝叶斯被称为生成方法的原因。简言之,可以计算特定像素配置代表数字“5”的概率,知道在假设有一个数字“5”的情况下,随机像素配置可能会和给定数字相匹配的概率是多少。
的概率,这也是朴素贝叶斯被称为生成方法的原因。简言之,可以计算特定像素配置代表数字“5”的概率,知道在假设有一个数字“5”的情况下,随机像素配置可能会和给定数字相匹配的概率是多少。
在医学测试领域,这是最容易理解的。假设检测一种特定疾病或癌症,想要知道当检测结果是阳性时患某种疾病的概率是多少。现在,大多数测试有一个可靠性值,该值是在对患有特定疾病的人进行测试时,测试结果呈阳性的概率的百分比。通过反转表达式 ,可得到:
,可得到:
 (癌症 | 测试 = 阳性) =
(癌症 | 测试 = 阳性) =  (测试 = 阳性 | 癌症)*
(测试 = 阳性 | 癌症)*  (癌症)/
(癌症)/ (测试 = 阳性)
(测试 = 阳性)
假设测试的可靠性为98%,这就意味着在98%的病例中,如果患者患有癌症,测试就会显示阳性;同样,如果患者没有患癌症,测试结果就会显示阴性。此外,假设这种特殊类型的癌症只会影响到老年人,并且50岁以下的人群中只有2%的人患有这种癌症,并且针对50岁以下人群所进行的检测的结果显示只有3.9%的人的测试结果呈阳性(可以从数据中推导出这个事实,但为了简单起见,我们直接提供该信息)。
我们可以提出这样一个问题:如果一个针对癌症的测试的准确率是98%,而一个45岁的人参加了该测试并且测试结果是阳性的,那么他/她患有癌症的概率是多少?使用上述公式,可以计算出:
 (癌症 | 测试 = 阳性) = 0.98 * 0.02/0.039 ≈ 0.50
(癌症 | 测试 = 阳性) = 0.98 * 0.02/0.039 ≈ 0.50
因此,尽管测试的准确率很高,朴素贝叶斯告诉我们,还需要兼顾“癌症在50岁以下的人群众发生的概率是相当罕见的”这一情况,因此仅根据检测结果呈阳性并不能给出98%的癌症概率。概率 (癌症),或者更笼统地说,我们尝试估计的结果的概率
(癌症),或者更笼统地说,我们尝试估计的结果的概率 ,被称为先验概率,因为它表示在进行测试之前尚无任何其他信息的情况下事件的发生概率。
,被称为先验概率,因为它表示在进行测试之前尚无任何其他信息的情况下事件的发生概率。
这时,有人可能会想,如果有更多信息(例如,如果用不同的可靠性进行不同的测试,或者知道一些关于这个人的信息——如家族成员癌症复发),会发生什么。在前面所使用的等式中,我们以概率作为计算中的因子之一,即 (测试 = 阳性 | 癌症)。如果进行第二次测试并且结果呈阳性,则也会得到
(测试 = 阳性 | 癌症)。如果进行第二次测试并且结果呈阳性,则也会得到 (测试 2 = 阳性 | 癌症)。朴素贝叶斯技术算法做出如下假设,即每条信息都彼此独立(这意味着测试2的结果不知道测试1的结果,并且独立于测试1的结果而存在,即进行测试1不会改变测试2的结果,则测试2的结果不受测试1的影响)。朴素贝叶斯是一种分类算法,该算法假设了不同事件在计算概率时的独立性。因此:
(测试 2 = 阳性 | 癌症)。朴素贝叶斯技术算法做出如下假设,即每条信息都彼此独立(这意味着测试2的结果不知道测试1的结果,并且独立于测试1的结果而存在,即进行测试1不会改变测试2的结果,则测试2的结果不受测试1的影响)。朴素贝叶斯是一种分类算法,该算法假设了不同事件在计算概率时的独立性。因此:
 (测试1和测试2 =
(测试1和测试2 =  | 癌症) =
 | 癌症) =  (测试1 =
(测试1 =  | 癌症) ×
 | 癌症) ×  (测试2 =
(测试2 =  | 癌症)
 | 癌症)
这个等式也称为可能性L(测试1和测试2=阳性),即在某人确实患有癌症时,测试1和测试2是阳性的。
然后,可以将等式改写为:
 (癌症|两次测试 =
(癌症|两次测试 =  ) =
) =
 (两次测试 =
(两次测试 =  | 癌症) ×
| 癌症) ×  (癌症)/
(癌症)/ (两次测试 =
(两次测试 =  ) =
) =
 (测试1 =
(测试1 =  | 癌症) ×
| 癌症) ×  (测试2 =
(测试2 =  | 癌症) ×
| 癌症) ×  (癌症)/
(癌症)/ (两次测试 =
(两次测试 =  )
)
支持向量机是一种主要用于分类的监督机器学习算法。支持向量机相对于其他机器学习算法的优点在于:它不仅将数据分离成类,还能据此发现分离的超平面(在大于三维的空间中的平面模拟)——这个超平面能够最大化分离超平面每个点的间隔。支持向量机还能处理数据不是线性分离的情况。处理非线性可分数据的方法有两种:一种是引入软间隔(soft margin);另一种是引入所谓的核技巧(kernel trick)。
软间隔的工作原理是在保留算法的大部分预测能力的同时,允许一些未分类元素存在。如前所述,在实践中,最好不要过拟合任何机器学习模型——我们可以通过放松一些支持向量机假设做到这一点。
相反,核技巧涉及将特征空间映射到可以定义一个超平面的另一个空间。如图1-10所示,当该超平面映射回特征空间时,其不再是线性超平面,其允许将在数据集中看起来不可分离的元素分离。本书主要关注深度学习,因此不会花费太多时间去详细探讨支持向量机是如何实现的,而是会强调概念,即由于向量机可推广至非线性情况的能力,支持向量机曾一度流行且有效。如前所述,监督机器学习算法的任务是从特征空间到一组类别之间找到一个函数。每个输入 代表着一个输入示例,并且每个
代表着一个输入示例,并且每个 代表着第
代表着第 个特征的
个特征的 的值。我们在前面举过一个例子,即尝试基于某些特征(如浴室数量或位置)估算房子的转售价。如果第
的值。我们在前面举过一个例子,即尝试基于某些特征(如浴室数量或位置)估算房子的转售价。如果第 个特征对应浴室的数量,则
个特征对应浴室的数量,则 将对应房子
将对应房子 中浴室的数量。我们可以从特征空间创建一个函数,以实现这个空间的不同表示(称为 “核”):例如示例
中浴室的数量。我们可以从特征空间创建一个函数,以实现这个空间的不同表示(称为 “核”):例如示例 可以将
可以将 映射到(
映射到( )2,并且通常将特征空间非线性地映射到另一空间
)2,并且通常将特征空间非线性地映射到另一空间 。这样,
。这样, 中的一个分离超平面就可以被映射回到特征空间。在特征空间中,该超平面不再是一个线性超平面。在确切的情况下,这是正确的定义,但超出了本章这一简要介绍的范畴。然而,这再次强调了正确特征选择(一个能够允许找到具体问题解决办法的选择)在经典机器学习算法中的重要性。
中的一个分离超平面就可以被映射回到特征空间。在特征空间中,该超平面不再是一个线性超平面。在确切的情况下,这是正确的定义,但超出了本章这一简要介绍的范畴。然而,这再次强调了正确特征选择(一个能够允许找到具体问题解决办法的选择)在经典机器学习算法中的重要性。
图1-10 图(a)是在应用核技巧之前的非线性可分集,图(b)是在应用核技巧之后的相同
 数据集并且数据可被线性分离
到目前为止,我们介绍了监督学习算法和无监督学习算法。交叉熵方法属于强化学习类算法(见第7章和第8章),是一种求解最优化问题的技术,即找到可以最小化或最大化特定函数的最佳参数。
一般说来,交叉熵方法包括以下阶段。
(1)生成我们想要优化的变量的随机样本。对于深度学习,这些变量可能会是神经网络的权值。
(2)运行任务并存储性能变量。
(3)确定最佳运行并选择最佳性能变量。
(4)基于最佳性能变量运行,计算每个变量的新均值及方差,并生成变量的新样本。
(5)重复上述步骤,直至达到停止条件或者系统停止改善为止。
假设要求解依赖于许多变量的一个函数,例如,做模型飞机,使其从特定高度起飞时,能飞得最远。飞机飞过的距离是一个与其机翼尺寸、角度、重量等相关的函数。每一次都记录下每个变量,然后启动飞机并测量它的飞行距离。然而,我们并不去尝试所有可能的组合,而是创建统计数据,选择最佳运行和最差运行,并且注意变量在最佳运行和最差运行期间所设置的值。例如,如果检测到每一次最佳飞行时飞机都有着特定尺寸的机翼,就可以得出这样的结论:特定尺寸的机翼可能是飞机实现长距离飞行的最佳选择。相反,如果飞机的机翼在每一次最差飞行中都处于一定角度,则可以得出这样的结论:这个角度对飞机机翼来说是一个糟糕的选择。一般说来,针对应该产生最佳飞行的每个值会产生一个概率分布,这些概率不再是随机概率,而是基于已经收到的反馈的概率。
因此,在具代表性的强化学习过程中,该方法会使用来自运行的反馈(飞机飞行了多远)以确定问题的最佳解决方案(每个变量的值)。
在补充了一些流行经典机器学习算法的知识之后,现在我们介绍一下神经网络,并更详细地解释它们是如何工作的以及它们跟前面简单总结的算法有何不同。
神经网络是另一种机器学习算法,它们有过非常流行的时期,也有过很少被人提及的经历。理解神经网络(见第2章和后续章节),确实是理解本书内容的关键。
神经网络的第一个例证叫作感知机,它是由Frank Rosenblatt于1957年发明的。感知机是一个仅由输入层和输出层组成的网络,如图1-11所示。在二值分类情况下,输出层只有一个神经元或者单元。从一开始,这种感知机似乎前途一片光明,虽然人们很快意识到它只能学习线性可分模式。例如,Marvin Minsky和Seymour Papert证明了它不能学习异或逻辑函数。在其最基本的表示中,感知机只是一个神经元及其输入的简单表示,其中,输入由几个神经元组成。
图1-11 带有3个输入单元(神经元)和一个输出单元(神经元)的简单感知机
在给定神经元的不同输入的情况下,用公式 来定义一个激活值,其中
来定义一个激活值,其中 是指输入神经元的值,而
是指输入神经元的值,而 是指神经元
是指神经元 与输出之间的连接的值。在第2章中,我们将深入学习相关知识,目前只需注意一点:感知机与逻辑回归算法之间存在许多相似之处,并且也受到线性分类器的约束。如果激活值(应该被认为是神经元的内部状态)大于一个固定阈值
与输出之间的连接的值。在第2章中,我们将深入学习相关知识,目前只需注意一点:感知机与逻辑回归算法之间存在许多相似之处,并且也受到线性分类器的约束。如果激活值(应该被认为是神经元的内部状态)大于一个固定阈值 ,那么神经元将被激活,也就是说,它要么放电,要么不会放电。
,那么神经元将被激活,也就是说,它要么放电,要么不会放电。
上面所定义的简单激活可被解释为向量 和向量
和向量 之间的点积。向量
之间的点积。向量 是固定的并且定义了感知机是如何工作的,而
是固定的并且定义了感知机是如何工作的,而 则代表着输入。如果
则代表着输入。如果 ,则向量
,则向量 垂直于权值向量
垂直于权值向量 ,所以,使得
,所以,使得 成立的所有向量
成立的所有向量 可定义
可定义 中的一个超平面(其中,3是
中的一个超平面(其中,3是 的维数,但其通常可以是任意整数)。因此,满足
的维数,但其通常可以是任意整数)。因此,满足 的任意向量
的任意向量 都是用
都是用 定义的超平面侧边上的一个向量。由此,我们便可以弄清楚感知机是如何定义超平面以及是如何作为分类器运行的。一般说来,可以将阈值设置为不是0的任意实数
 定义的超平面侧边上的一个向量。由此,我们便可以弄清楚感知机是如何定义超平面以及是如何作为分类器运行的。一般说来,可以将阈值设置为不是0的任意实数 ,这会产生将超平面从原点移开的效果。然而,通常不是保持这个值,而是在网络中包含一个偏置单元,这是一个带有连接权值“
,这会产生将超平面从原点移开的效果。然而,通常不是保持这个值,而是在网络中包含一个偏置单元,这是一个带有连接权值“ ”的常开(数值=1)特殊神经元,如图 1-12所示。在这种情况下,如果连接权值具有数值“−b”,则激活值变为
”的常开(数值=1)特殊神经元,如图 1-12所示。在这种情况下,如果连接权值具有数值“−b”,则激活值变为 ,并且设置
,并且设置 > 0相当于设置
 > 0相当于设置 。
。
图1-12 一个带有为输出向量增加偏置单元的感知机。偏置单元总是在感知机上,虽然其性能有限,但有着重要的历史意义,因为它们是神经网络的第一批示例
当然,神经网络不需要并且(事实上)通常也没有单一输出神经元。如果网络有一个以上的输出神经元,则针对每个输出神经元,可以重复相同的过程。然后,用两个指数 和
和 来标记每个权值,以说明权值将输入层上的神经元
来标记每个权值,以说明权值将输入层上的神经元 连接到输出层上的神经元
连接到输出层上的神经元 。此外,从偏置单元(值为1)到输出层的每个神经元也都会有一个连接。还要注意的是,可以在激活值上定义不同的激活函数。我们在前面已经将激活值定义为
。此外,从偏置单元(值为1)到输出层的每个神经元也都会有一个连接。还要注意的是,可以在激活值上定义不同的激活函数。我们在前面已经将激活值定义为 (从现在开始假设这个公式中包含了偏置),并且说过:如果激活值大于0,则神经元就会被激活。正如接下来会看到的,这已经定义了一个活动函数,即在激活上(也就是在神经元的内部状态上)定义的一个函数,并且因为在激活值大于0时,神经元会被激活,因此这被称为阈值激活。然而,接下来我们将看到神经网络能够有许多(能在激活值上定义的)不同激活函数。在第2章中,我们将就此展开更详细的探讨。
(从现在开始假设这个公式中包含了偏置),并且说过:如果激活值大于0,则神经元就会被激活。正如接下来会看到的,这已经定义了一个活动函数,即在激活上(也就是在神经元的内部状态上)定义的一个函数,并且因为在激活值大于0时,神经元会被激活,因此这被称为阈值激活。然而,接下来我们将看到神经网络能够有许多(能在激活值上定义的)不同激活函数。在第2章中,我们将就此展开更详细的探讨。
我们在前面介绍了一个关于神经网络(1层前馈网络)的非常简单示例。之所以包含“前馈”一词,是因为信息从输入层传入输出层,并且永不循环。之所以包含“1层”,是因为除了输入层,只有1层输出层。这不是通常情况。在提到1层前馈网络只能在线性分离数据上运行时,我们讨论了1层前馈网络的局限性,并且特别提及这些网络会逼近逻辑异或函数。但是,在有些网络的输入层和输出层之间会有其他层,我们将这些其他层称为“隐藏层”。那么,具有隐藏层的前馈网络会将信息从输入层经由隐藏层传入输出层——该层会定义一个接收输入的函数,并且该函数会定义一个输出。有一个名为“万有定理”的定理,该定理表示任何函数能够由具有至少一个隐藏层的神经网络来近似。我们将在第2章给出“为什么该定理是正确的”的直观说明。
长期以来,鉴于该定理以及运用复杂网络的困难,人们一直使用仅带有一个隐藏层的浅层网络(图 1-13)。然而,最近人们认识到,具有许多隐藏层的更复杂网络可以理解浅层网络所无法理解的抽象层次。此外,针对神经元也可以将信息反馈给自己的情况,人们还引入了递归网络。一些神经网络的结构还允许定义能量函数,以便创造记忆。我们将在第 2 章讲解这些令人兴奋的功能,届时还将深入探究深度学习的最新发展。
图1-13 带有一个隐藏层的浅层网络
总的来说,机器学习(特别是深度学习)正在预测质量、特征检测和分类方面产生越发惊人的结果。近年来,许多这样的研究成果成了焦点新闻。
机器学习的进步如此之快,以至于许多专家担心机器人很快就会比人类聪明。在2015年10月14日召开的联合国会议上,人工智能专家和许多其他领域的研究人员发出警告:有必要制定道德准则,以预防超级智能级别的机器给人类造成的威胁。这种恐慌源于近期的一些令人难以置信的结果:计算机竟在一些曾被认为依靠人比机器更富优势的直觉便可以取胜的游戏中获胜。
AlphaGo是一种基于深度学习的人工智能机器,因曾在2016年击败围棋世界冠军李世石而广为人知。早在2016年1月,便传出AlphaGo击败欧洲冠军樊麾Fan Hui的消息。不过,当时的AlphaGo似乎不太可能会接着击败世界冠军。然而,经过几个月的快速进步,AlphaGo以4 : 1取胜,一举横扫对手,取得了非凡战绩。之所以值得庆祝,是因为围棋比其他游戏(如国际象棋)具有更多可能的游戏变化,并且不可能提前考虑所有可能的动作。此外,跟国际象棋不同的是:在围棋中,很难判断棋盘上每颗棋子的当前位置或价值。
AlphaGo的优势在于,它并非通过编程学会玩游戏,而是利用强化学习和深度学习技术,通过进行成千上万次跟自己的比赛来学习的。学习能力使得机器学习(尤其是深度学习)成为解决问题的一种完全不同的方法。深度学习是关于创建程序,从而可以在根本不需要人类帮助或者只需很少帮助的情况下自行学习。
然而,不仅在游戏方面,深度学习在各种领域的应用均取得了成功。Kaggle是一个举办多种机器学习竞赛的网站。使用深度学习的领域与深度学习的应用有着千差万别。2013年,美国俄勒冈大学赞助了一项赛事,该赛事要求参赛者通过使用真实世界音频数据的标准录音,将机器学习技术用于检测和识别鸟类。为了更好地了解鸟类的数量趋势,人们常常需要耗费大量的人力。机器学习可以通过简单听取音频记录来自动识别都有哪些种类的鸟来帮助解决这一问题。
近期,亚马逊针对授予员工访问内部计算机和网络问题,举办了另一场内部竞赛,以期利用成功的解决方案来削减由人力监督的干预所导致的高昂延迟代价。
美国芝加哥卫生部门在2015年举行了一场竞赛,提出“根据给定天气、位置、测试和喷洒数据……何时何地对车西尼罗病毒测试呈阳性”。
2015年8月,一场要求对整个西澳大利亚州租金价格做出预算的竞赛成功举办;2016年2月,一家法国银行(BNP Paribas)发起了一场加快索赔管理程序的竞赛。
上述赛事为利用机器学习来解决各种问题提供了一些思路,并且应该注意的是,所有这些竞赛都为最佳解决方案准备了奖励。2009年,Netflix发起了一项耗资100万美元的赛事,该赛事是基于用户以往影片排名来提高关于用户可能会喜爱什么影片的预测的准确率。与此同时,数据专家也成了薪酬最高且最受欢迎的职业之一。
机器学习通常应用于自动驾驶汽车、军用无人机和目标侦察系统乃至医疗应用,例如,能够阅读医生笔记进而发现潜在健康问题,以及能够提供面部识别的监视系统的应用。
光学字符识别得到广泛应用,举例来说,邮局利用字符识别来读取信封上的地址。我们也将在后文向大家展示如何使用MNIST数据集将神经网络应用于数字识别。此外,无监督深度学习也被广泛应用于自然语言处理(Natural Language Processing,NLP),并且在这方面取得了巨大效果。在几乎每个人的智能手机上都有一个深度学习的NLP应用程序,例如苹果和安卓系统都将应用于NLP的深度学习用作虚拟助手(如Siri)。机器学习也被应用于生物测定学,例如,用于识别某人物理特征(如指纹、DNA或视网膜识别)。此外,汽车自动驾驶技术近年来得以改进,现已被用于现实。
机器学习也可应用于编排相册图片目录,或者(更重要的)为编排卫星图形目录,这样卫星可以根据其是否是市区环境,是否描述了森林、冰川、水域等来描述图形。
总而言之,机器学习应用已经慢慢渗透到了我们生活中的方方面面,并且随着计算机的计算能力越来越好、越来越快,机器学习的准确率和性能也在不断提高。
机器学习是一个流行且存在激烈竞争的领域,并且有许多开源包均可用来实现大多数的经典机器学习算法。其中最为流行的是在Python中得到广泛使用的一个开源库:scikit-learn。
scikit-learn会提供可实现大多数经典机器学习分类器、回归器和聚类算法(如支持向量机、最近邻、随机森林、线性回归、 均值、决策树和神经网络)以及更多机器学习算法的函数库。
均值、决策树和神经网络)以及更多机器学习算法的函数库。
根据所选算法的类型,基类scikit-learn拥有几个可用软件包,如sklearn.ensemble、sklearn.linear_model、sklearn.naive_bayes、sklearn.neural_network、sklearn.svm,以及sklearn.tree。
还有一些帮助程序可用于执行交叉验证以及帮助选择最佳特征。接下来,我们将列出一个使用多层神经网络的简单示例来描述所有函数库,而不是花时间对它们做出抽象描述。scikit-learn函数库会针对每个机器学习算法使用具有相似特征的方法,这样分类器便可共享相同的常用功能。此外,希望读者能够快速了解神经网络能够做什么,而不是花时间去从头开始创建一个神经网络。在后续章节中,我们将讨论其他函数库以及许多不同类型深度学习神经网络的更复杂的实现。但是现在,读者可以首先快速了解一下上述函数库的功能。
例如,如果要将多层神经网络用于scikit-learn,只需输入以下命令,便可将其导入程序:
from sklearn.neural_network.multilayer_perceptron import MLPClassifier每个算法都需要通过使用预定义参数来调用,尽管在大多数情况下可以使用默认值。在MLPClassifier情况下,不需要参数,可以使用默认值(通过scikit-learn网站可以找到所有参数,特别是针对MLPClassifier的参数)。
然后,在训练数据上调用该算法,使用参数来调优标记并使用拟合(fit)函数:
MLPClassifier().fit(data, labels)一旦算法与训练数据完成拟合,就可以将该算法用于预测测试数据,使用会针对每个类别输出概率的predict_proba函数:
probabilities = MLPClassifier().predict_proba(data)下面是一个简单例子,用来说明如何在iris数据集上使用MLPClassifier分类器,其中iris数据集已在介绍决策树时简短讨论过:
probabilities = MLPClassifier().predict_proba(data)利用scikit-learn,我们可以很容易地加载重要的经典数据集。要加载数据集,只需执行以下代码:
from sklearn import datasets
iris = datasets.load_iris()
data = iris.data
labels = iris.target加载完数据集后,我们用如下代码加载分类器:
from sklearn.neural_network.multilayer_perceptron import MLPClassifier使用以下数据来调优参数:
mlp = MLPClassifier(random_state=1) 
mlp.fit(data, labels)因为权值是随机初始化的,所以随机状态(random_state)值只是强制初始化过程始终使用相同的随机值,以便在不同尝试中得到一致结果,这与理解这个过程完全无关。fit函数是一种可供调用的重要函数,这种函数可以在监督形式下通过使用所提供的数据和标记来训练算法进而找到最佳权值。
现在我们可以查看预测并将其与实际结果进行比较。predict_proba函数会输出概率,而predict函数会输出具有最高概率的类,因此我们将使用后者进行比较,并使用scikit-learn辅助模块给出准确率:
pred = mlp.predict(data)
from sklearn.metrics import accuracy_score
print('Accuracy: %.2f' % accuracy_score(labels, pred))就这么简单!当然,正如前文所提到的,在通常情况下,最好将数据分为训练数据和测试数据。我们还可以通过使用数据的一些正则化来改进这段简单的代码。scikit-learn也针对此提供了一些辅助函数:
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler
data_train, data_test, labels_train, labels_test = train_test_
split(data, labels, test_size=0.5, random_state=1)
scaler = StandardScaler()
scaler.fit(data)
data_train_std = scaler.transform(data_train)
data_test_std = scaler.transform(data_test)
data_train_std = data_train
data_test_std = data_test这段代码是无须解释的,我们要分割数据并将其正则化,这意味着要减去均值并将数据缩放到单元方差,然后将算法与训练数据进行拟合并在测试数据上进行测试:
mlp.fit(data_train, labels_train)
pred = mlp.predict(data_test)
print('Misclassified samples: %d' % (labels_test != pred).sum())
from sklearn.metrics import accuracy_score print('Accuracy: %.2f' %
accuracy_score(labels_test, pred))这样会得到以下输出:
Misclassified samples: 3 Accuracy: 0.96我们可以绘制一些图来显示数据以及神经网络是如何将空间分成3个区域来分离这3种类型的花朵(只能绘制出二维图,因此只能绘制出两个特征)的。第一张图(图 1-14)显示了算法如何在不对数据进行正则化的情况下,根据花瓣的宽度和长度来分离花朵。
图1-14 算法如何在不对数据进行正则化的情况下,根据花瓣的宽度和长度来分离花朵
第二张图只是基于花瓣宽度和萼片宽度来显示相同花朵,如图1-15所示。
图1-15 基于花瓣宽度和萼片宽度来显示相同花朵
在对数据进行正则化之后,第三张图和第一张图相同,如图 1-16所示。
图1-16 正则化数据后的显示效果
最后,具有正则化数据的第四张图与第二张图相同,如图1-17所示。
图1-17 与第二张图相同
这里还给出了用于绘制这些图的代码。注意,绘制这些图的源代码来自 Sebastian Raschka的Python Machine Learning。
绘制上述图片的代码如下。注意,必须设置为仅包含两个变量的数据,例如萼片长度和花瓣长度data = iris. data[:,[1,3]],因为只能绘制二维图。
import numpy
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
markers = ('s', '*', '^')
colors = ('blue', 'green', 'red')
cmap = ListedColormap(colors)
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1
resolution = 0.01
x, y = numpy.meshgrid(numpy.arange(x_min, x_max, resolution), numpy.
arange(y_min, y_max, resolution))
Z = mlp.predict(numpy.array([x.ravel(), y.ravel()]).T)
Z = Z.reshape(x.shape)
plt.pcolormesh(x, y, Z, cmap=cmap)
plt.xlim(x.min(), x.max())
plt.ylim(y.min(), y.max())
# plot the data
classes = ["setosa", "versicolor", "verginica"]
for index, cl in enumerate(numpy.unique(labels)):
plt.scatter(data[labels == cl, 0], data[labels == cl, 1],
c=cmap(index), marker=markers[index], s=50, label=classes[index])
plt.xlabel('petal length')
plt.ylabel('sepal length')
plt.legend(loc='upper left')
plt.show()正如前文所提到的,MLPClassifier确实有很多能够使用的参数。这里只引用激活函数和隐藏层的数量以及每个层都可能有多少个神经元:
neural_network.MLPClassifier.html隐藏层的数量和神经元的数量都可以通过添加hidden_layer_sizes=(n1, n2, n3, …, nm)来指定,其中ni是第 层中的神经元数。
层中的神经元数。
对于一个具有两个隐藏层(分别带有200个神经元和100个神经元)的神经网络,将代码写成如下:
mlp = MLPClassifier(random_state=1, hidden_layer_sizes=(200, 100,))另一个重要的参数是指激活函数。此模块支持以下3种类型。
ReLU函数是最简单并且最流行的函数之一(以及默认激活函数),并且被简单地定义为 = max(0,
= max(0,  )。
)。
如果读者对计算事件概率感兴趣,可使用logistic函数,事实上它的值介于0和1之间,并且可被定义为 。
。
最后,tanh函数被简单定义为
例如,要将两个隐藏层(分别带有200个神经元和100个神经元)用于logistic函数,修改后的代码如下:
mlp = MLPClassifier(random_state=1, hidden_layer_sizes=(200, 100,),activation = "logistic")我们建议读者运用其中的一些参数,并使用max_uiter参数限制迭代次数。迭代次数是指遍历训练数据的次数。一个小数值(如max_uiter=100)不会产生很好的结果,因为没有时间对算法进行收敛。不过,注意,在这样一个小的数据集上,要获得好的预测无需更多的隐藏层,并且使用更多隐藏层反而可能会降低预测准确率。
本章到此结束。在本章中,我们向读者介绍了机器学习的重要性以及机器学习在现实世界中的许多应用。我们已经简要提及一些问题,并且提到在第2章中将会重点讲解的神经网络,还提到了如何利用标准开源库(如scikit-learn)来实现一些简单的多层前馈网络。
接下来,我们开始深入讨论神经网络以及使用它们的动机。
本章讨论了机器学习包含哪些内容以及这些内容如此重要的原因,并通过一些示例说明了机器学习技术的应用领域以及使用机器学习可以解决哪些类型的问题。本章还介绍了一种特殊类型的机器学习算法(称为神经网络,该算法是深度学习的基础),并给出了示例代码。在该示例中,我们利用流行的机器学习库解决了具体分类问题。第2章将针对神经网络展开更为详细的讲解,并基于观察人脑如何运行所得出的生物学因素,给出有关神经网络的理论依据。