引 言2
1.1 无处不在的数据
我们正实实在在地处于“信息时代”。如今,各种数据从无穷无尽的渠道不断涌入:智能手机、手表、汽车、停车计时表、家用电器。几乎任何一种能够说出名字的技术与生俱来都具备与位于云端的某个数据库进行通信的能力。在看似无限的存储能力的支持下,开发者们为数据仓库选择了一种“更多即是更好”的方法,存储着从他们的产品和客户那里收集到的以拍字节(PB)为单位计的海量数据。
与此同时,计算机的性能也在持续提升。虽然CPU的发展速度已经放缓,但并行处理架构取得了爆炸式的发展。一向主要服务于计算机游戏的图形处理单元(GPU)如今已被大量运用于通用计算领域,并拉开了机器学习迅猛发展的序幕。
机器学习(有时简记为ML)试图利用通用的数学模型回答涉及数据的特定问题。机器学习成功应用于垃圾邮件检测、产品推荐(向客户)、预测商品的价格等领域已有多年。近年来,一种特殊类型的机器学习范式在几乎所有领域都取得了无数巨大的成功,它就是深度学习。
1.2 深度学习
“深度学习”已成为用于描述使用多层神经网络的过程的标准术语,多层神经网络是一类极为灵活的可利用种类繁多的数学方法以及不同数学方法组合的模型。这类模型极为强大,但直到最近几年,人们才有能力卓有成效地利用神经网络,其背后原因主要有两点,一是获取足够数量的数据成为现实;二是得益于通用GPU的快速发展,多层神经网络拥有了超越其他机器学习方法所必需的计算能力。
深度学习的强大之处在于当决定如何最有效地利用数据时,它能够赋予模型更大的灵活性。人们无需盲目猜测应当选择何种输入。一个调校好的深度学习模型可以接收所有的参数,并自动确定输入值的有用高阶组合。这种能力使得更为复杂的决策过程成为可能,并使计算机比以往任何时候都更加智能。借助深度学习,我们可以制造出具有自动驾驶能力的汽车和能够理解人类语音的电话。由于深度学习的出现,机器翻译、人脸识别、预测分析、机器作曲以及无数的人工智能任务都成为可能,或相比以往有了显著改进。
虽然深度学习背后的数学概念几十年前便提出,但致力于创建和训练这些深度模型的编程库是近年来才出现的。遗憾的是,这些库中的大多数都会在灵活性和生产价值之间进行取舍。灵活的库对于研究新的模型架构极有价值,但常常或者运行效率太低,或者无法运用于产品中。另一方面,虽然出现了可托管在分布式硬件上的快速、高效的库,但它们往往专注于特定类型的神经网络,并不适宜研究新的和更好的模型。这就使决策制定者陷于两难境地:是应当用缺乏灵活性的库来从事研究,以避免重新实现代码,还是应当在研究阶段和产品开发阶段分别使用两个完全不同的库?如果选择前一种方案,可能便无法测试不同类型的神经网络模型;如果选择后一种方案,则需要维护可能调用了完全不同的两套API的代码。由此甚至会引发另一个问题—我们是否拥有这样的资源?
解决这个两难问题正是TensorFlow的设计初衷。
1.3 TensorFlow:一个现代的机器学习库
TensorFlow由谷歌于2015年11月向公众正式开源,它是汲取了其前身—DistBelief在创建和使用中多年积累的经验与教训的产物。TensorFlow的设计目标是保证灵活性、高效性、良好的可扩展性以及可移植性。任何形式和尺寸的计算机,从智能手机到大型计算集群,都可运行TensorFlow。TensorFlow中包含了可即刻将训练好的模型产品化的轻量级软件,有效地消除了重新实现模型的需求。TensorFlow拥抱创新,鼓励开源的社区参与,但也拥有一家大公司的支持、引导,并保持一定的稳定性。由于其强大的功能,TensorFlow不仅适合个人使用,对于各种规模的公司(无论是初创公司,还是谷歌这样的大公司)也都非常适合。
如果你和你的同事拥有数据、一个有待求解的问题以及一台可工作的计算机,那么很幸运,TensorFlow正是你们一直寻找的“武林秘籍”。
1.4 TensorFlow:技术概要
本小节将给出一些关于TensorFlow库的高层信息,如它是什么、它的发展史、用例以及与竞争对手的比较。决策制定者、利益相关者以及任何希望了解TensorFlow背景的人都会从本小节受益。
谷歌的深度学习研究简史
谷歌最初开发的大规模深度学习工具是谷歌大脑(Google Brain)团队研发的DistBelief。自创建以来,它便被数十个团队应用于包括深度神经网络在内的不计其数的项目中。然而,像许多开创性的工程项目一样,DistBelief也存在一些限制了其易用性和灵活性的设计错误。DistBelief完成之后的某个时间,谷歌发起了新的项目,开始研发新一代深度学习工具,其设计准备借鉴最初的DistBelief在使用中总结的教训和局限性。这个项目后来发展为TensorFlow,并于2015年11月正式向公众开源,接着迅速成为一个颇受欢迎的机器学习库,如今已被成功运用于自然语言处理、人工智能、计算机视觉和预测分析等领域。
1.5 何为TensorFlow
下面以一种高层观点来介绍TensorFlow,以帮助读者理解它试图求解的问题。
1.5.1 解读来自官网的单句描述
在TensorFlow的官网上,针对访问者的第一句致辞便是下列(相当含糊的)声明:
TensorFlow is an Open Source Software Library for Machine Intelligence
这句话的下方,即“About TensorFlow”下的一段还有这样一句描述:
TensorFlowTM is an open source software library for numerical computation using data flow graphs.
比起前面的声明,第二个定义更为具体,但对那些数学或技术背景不强的人而言,这可能并非最全面的解释。下面我们对其进行解构。
1. Open Source(开源)
TensorFlow最初是作为谷歌的内部机器学习工具而创建的,但在2015年11月,它的一个实现被开源,所采用的开源协议是Apache 2.0。作为开源软件,任何人都可自由下载、修改和使用其代码。开源工程师可对代码添加功能和进行改进,并提议在未来版本中打算实施的修改。由于TensorFlow深受广大开发者欢迎,因此这个库每天都会得到来自谷歌和第三方开发者的改进。
注意,严格来说,我们只能称之为“一个实现”,而不能说“TensorFlow” 被开源。从技术角度讲,TensorFlow是《TensorFlow白皮书》所描述的一个用于数值计算的内部接口,其内部实现仍然由谷歌维护。然而,开源实现与谷歌的内部实现之间的差异是由与其他内部软件的连接造成的,并非谷歌有意“将好东西藏着掖着”。谷歌始终都在不断将内部改进推送到公共代码库。总之,TensorFlow的开源版本包含了与谷歌的内部版本完全相同的功能。
在本书后续内容中,当提到“TensorFlow”时,笔者实际上指的是其开源实现。
2. Library for Numerical Computation(数值计算库)
官网的定义中并未将TensorFlow称为一个“机器学习库”,而是使用了更宽泛的短语“数值计算”。虽然TensorFlow中的确包含一个模仿了具有单行建模功能的机器学习库Scikit-Learn的名为“learn”(也称“Scikit Flow”)的包,但需要注意的是,TensorFlow的主要目标并非是提供现成的机器学习解决方案。相反,TensorFlow提供了一个可使用户用数学方法从零开始定义模型的函数和类的广泛套件。这使得具有一定技术背景的用户可迅速而直观地创建自定义的、具有较高灵活性的模型。此外,虽然TensorFlow为面向机器学习的功能提供了广泛支持,但它也非常适合做复杂的数学计算。然而,由于本书重点讨论机器学习(尤其是深度学习),因此下面主要讲述如何利用TensorFlow创建“机器学习模型”。
3. Data Flow Graphs(数据流图)
TensorFlow的计算模型是有向图(directed graph),其中每个节点(通常以圆圈或方框表示)代表了一些函数或计算,而边(通常以箭头或线段表示)代表了数值、矩阵或张量。
数据流图极为有用的原因如下。首先,许多常见的机器学习模型,如神经网络,本身就是以有向图的形式表示的,采用数据流图无疑将使机器学习实践者的实现更为自然。其次,通过将计算分解为一些小的、容易微分的环节,TensorFlow能够自动计算任意节点关于其他对第一个节点的输出产生影响的任意节点的导数(在TensorFlow中称为“Operation”)。计算任何节点(尤其是输出节点)的导数或梯度的能力对于搭建机器学习模型至关重要。最后,通过计算的分解,将计算分布在多个CPU、GPU以及其他计算设备上更加容易,即只需将完整的、较大的数据流图分解为一些较小的计算图,并让每台计算设备负责一个独立的计算子图(此外,还需一定的逻辑对不同设备间的共享信息进行调度)。
补充:何为张量?
简而言之,张量是一个n维矩阵。因此,2阶张量等价于标准矩阵。从可视化的角度,若将m×m的矩阵视为方形数组(m个数字高,m个数字宽),则可将m×m×m的张量视为立方数组(m个数字高,m个数字宽,m个数字深)。一般而言,如果读者更熟悉矩阵数学,完全可以按矩阵的方式来看待张量。
1.5.2 单句描述未体现的内容
虽然短语“open source software library for numerical computation using data flow graphs”的信息密度非常大,但并未涵盖那些真正使TensorFlow作为机器学习库脱颖而出的重要方面。下面列出一些成就TensorFlow的重要组成。
1.分布式功能
上文在介绍数据流图时间接提到,TensorFlow的设计目标之一是在多台计算机以及单机多CPU、单机多GPU环境中具有良好的可伸缩性。虽然,最初的开源实现在发布时并不具备分布式功能,但自0.8.0版本起,分布式运行时已成为TensorFlow内置库的一部分。虽然这个最初版本的分布式API有些臃肿,但它极其强大。大多数其他机器学习库尚不具备这样的功能,尤其值得注意的是,TensorFlow与特定集群管理器(如Kubernetes)的本地兼容性正在得到改善。
2.软件套件
虽然“TensorFlow”主要是指用于构建和训练机器学习模型的API,但TensorFlow实际上是一组需配合使用的软件:
TensorFlow是用于定义机器学习模型、用数据训练模型,并将模型导出供后续使用的API。虽然实际的计算是用C++编写的,但主要的API均可通过Python访问。这使得数据科学家和工程师可利用Python中对用户更为友好的环境,而将实际计算交给高效的、经过编译的C++代码。TensorFlow虽然也提供了一套可执行TensorFlow模型的C++ API,但在本书编写之时它还具有较大的局限性,因此对大多数用户都是不推荐的。
TensorBoard是一个包含在任意标准TensorFlow安装中的图可视化软件。当用户在TensorFlow中引入某些TensorBoard的特定运算时,TensorBoard可读取由TensorFlow计算图导出的文件,并对分析模型的行为提供有价值的参考。它对概括统计量、分析训练过程以及调试TensorFlow代码都极有帮助。学会尽早并尽可能多地使用TensorBoard会为使用TensorFlow工作增添趣味性,并带来更高的生产效率。
TensorFlow Serving是一个可为部署预训练的TensorFlow模型带来便利的软件。利用内置的TensorFlow函数,用户可将自己的模型导出到可由TensorFlow Serving在本地读取的文件中。之后,它会启动一个简单的高性能服务器。该服务器可接收输入数据,并将之送入预训练的模型,然后将模型的输出结果返回。此外,TensorFlow Serving还可以在旧模型和新模型之间无缝切换,而不会给最终用户带来任何停机时间。虽然Serving可能是TensorFlow生态系统中认可度最低的组成,它却可能是使TensorFlow有别于其他竞争者的重要因素。将Serving纳入生产环境可避免用户重新实现自己的模型—他们只需使用TensorFlow导出的文件。TensorFlow Serving完全是用C++编写的,其API也只能通过C++访问。
笔者相信,只有深入了解上述所有软件之间的联系,并熟练掌握它们的联合使用方法,方可真正使TensorFlow物尽其用。因此,本书会涵盖上述三个软件的用法。
1.6 何时使用TensorFlow
下面介绍一些TensorFlow的用例。一般而言,对于大多数机器学习任务,TensorFlow都是一个很好的选择。下面简单列出了TensorFlow尤其适合的一些场合。
研究、开发和迭代新的机器学习架构。由于TensorFlow极为灵活,因此在构建新颖的、测试较少的模型时非常有用。而使用某些库时,用户只能获取对实现原型有帮助的具有较强刚性的预建模型,而无法对其进行修改。
将模型从训练直接切换到部署。如前所述,TensorFlow Serving使用户可实现训练到部署的快速切换。因此,在创建依赖于机器学习模型的产品时,使用TensorFlow便可实现快速迭代。如果你的团队需要保持较快的开发进度,或者你只是没有用C++、Java等语言重新实现某个模型的资源,TensorFlow可赋予你的团队快速实现产品的能力。
实现已有的复杂架构。一旦用户掌握了如何阅读可视化的计算图,并使用TensorFlow来进行构建,他们便有能力用TensorFlow实现最新的研究文献中所描述的模型。在构建未来的模型,或甚至在对用户的当前模型进行严谨的改进时,这种能力可提供非常有价值的见解。
大规模分布式模型。在面对多种设备时,TensorFlow表现出卓越的向上可扩展性。它已经开始在谷歌内部的各个项目中逐步取代DistBelief。随着最近分布式运行时的发布,我们将看到越来越多的将TensorFlow运行于多台硬件服务器和云端虚拟机的用例。
为移动/嵌入式系统创建和训练模型。虽然TensorFlow主要关注向上的扩展(scaling up),对于向下的扩展(scaling down),它同样有优异的表现。TensorFlow的灵活性之一体现在它可轻松扩展到计算性能不高的系统中。例如,它可在安卓设备以及像树莓派(Raspberry Pi)这样的微型计算机中运行。TensorFlow代码库中包含了一个在安卓系统中运行预训练模型的例程。
1.7 TensorFlow的优势
1.易用性
相对而言,TensorFlow工作流易于理解。它的API保持着高度的一致性,这意味着在尝试不同模型时,无需从头学习一套新的东西。
TensorFlow API很稳定,维护者始终在努力确保每次改动都向下兼容。
TensorFlow与NumPy无缝集成,可使大多数了解Python的数据科学家如鱼得水。
不同于其他库,TensorFlow不占编译时间。这就使用户可快速验证自己的想法,而省去了专门的等待时间。
目前已有多种高层接口构建在TensorFlow之上,如Keras和SkFlow。这就使得即便用户不希望动手实现整个模型,也可以利用TensorFlow的优势。
2.灵活性
TensorFlow能够运行在不同类型和尺寸的机器之上。这使得TensorFlow无论是在超级计算机上,还是在嵌入式系统,或任何其他介于两者之间的计算机上都有用武之地。
TensorFlow的分布式架构使得在大规模数据集上的模型训练可在合理的时间内完成。
TensorFlow可利用CPU、GPU,或同时使用这两者。
3.高效性
当TensorFlow的第一个版本发布时,它在很多流行的机器学习基准测试中都非常低效。从那时起,TensorFlow的开发团队便投入大量的时间和精力对TensorFlow代码的大部分实现进行改进。如今,TensorFlow中大部分库的性能已有了显著提升,已成为众多开源机器学习框架中居于榜首位置的有力竞争者。
TensorFlow的效率仍在持续地得到改进,因为有越来越多的开发者正在共同努力带来更好的实现。
4.幕后支持
TensorFlow为谷歌所支持。谷歌已为其投入巨大的资源,因为它希望TensorFlow成为机器学习研究者和开发者的通用语言。此外,谷歌也在利用TensorFlow完成其日常工作,并且通过投资来为TensorFlow提供持续不断的支持。
围绕TensorFlow已经形成了一个不可思议的社区,从社区中的知名成员或GitHub上的知名开发者那里得到回应相对比较容易。
谷歌已经发布了若干用TensorFlow预训练的机器学习模型。它们可供免费使用,使得无需大量数据的流水线便可迅速实现原型系统。
5.额外特性
当需要对模型进行调试和可视化时,TensorBoard便体现出极为重要的价值,而在其他机器学习库中,并无类似的功能。
TensorFlow Serving可能是会使得更多的初创公司将服务和资源投入到机器学习领域的软件,因为重新实现代码来部署某个模型所需付出的代价绝对不可小觑。
1.8 使用TensorFlow所面临的挑战
1.分布式支持尚不成熟
虽然分布式运行时已正式发布,但在TensorFlow中使用这种特性却并非想象中那样容易。在本书写作之时,为使用该特性,需手工定义每台设备的角色,这种工作既乏味又容易出错。由于它是一种全新的特性,因此可供学习的例程较少,想必未来的版本应当会有所改进。如前文所述,对Kubernetes的支持已进入开发流水线,但到目前为止,它仍然尚未完成。
2.实现定制代码的技巧性较强
虽然关于如何用TensorFlow创建用户自己的运算有一份官方指南可供参考,但要将定制的代码实现到TensorFlow中仍然颇费周折。然而,如果希望对主代码库做出贡献,谷歌开发团队会快速回答你的问题,并查看你所提交的代码,以便为吸纳你的工作成果进行准备。
3.某些特性仍然缺失
如果你是一名经验丰富的机器学习专家,并对其他框架具备深入的了解,你可能会发现一些自己喜欢的虽小但十分有用的特性尚未在TensorFlow中实现。通常,你想要的这种特性在TensorFlow中会有一些替代方案,但这可能无法阻止你的抱怨“为什么它还未得到本地支持?”
1.9 高歌猛进
无需多言,笔者对TensorFlow的未来充满期待,而且笔者对帮助你开始使用这样一款强大工具感到激动万分。下一章将介绍如何安装TensorFlow,并对TensorFlow的核心库、基本使用模式以及环境进行全面讲解。