TensorFlow 2.0深度学习算法实战 第一章 人工智能绪论

1.1 人工智能

信息技术是人类历史上的第三次工业革命,计算机、互联网、智能家居等技术的普及极大地方便了人们的日常生活。通过编程的方式,人类可以将提前设计好的交互逻辑重复且快速地执行,从而将人类从简单枯燥的重复劳动任务中解脱出来。但是对于需要较高智能的任务,如人脸识别,聊天机器人,自动驾驶等任务,很难设计明确的逻辑规则传统的编程方式显得力不从心,而人工智能技术是有望解决此问题的关键技术。

随着深度学习算法的崛起,人工智能在部分任务上取得了类人甚至超人的水平,如围棋上AlphaGo 智能程序已经击败人类最强围棋专家柯洁,在 Dota2 游戏上 OpenAI Five 智能程序击败冠军队伍 OG,同时人脸识别,智能语音,机器翻译等一项项实用的技术已经进入到人们的日常生活中。现在我们的生活处处被人工智能环绕,尽管目前达到的智能水平离通用人工智能(Artificial General Intelligence,简称 AGI)还有一段距离,我们仍坚定相信人工智能时代即将来临。

接下来我们将介绍人工智能,机器学习,深度学习的概念以及它们之间的联系与区别。

1.1.1 人工智能

人工智能是指让机器获得像人类一样的智能机制的技术,这一概念最早出现在 1956 年召开的达特茅斯会议上。这是一项极具挑战性的任务,人类目前尚无法对人脑的工作机制有全面科学的认知,希望能制造达到人脑水平的智能机器无疑是难于上青天。即使如此,在某个方面呈现出类似、接近甚至超越人类智能水平的机器被证明是可行的。

怎么实现人工智能是一个非常广袤的问题。人工智能的发展主要经历过 3 种阶段,每个阶段都代表了人类从不同的角度尝试实现人工智能的探索足迹。最早期人类试图通过总结、归纳出一些逻辑规则,并将逻辑规则以计算机程序的方式来开发智能系统。但是这种显式的规则往往过于简单,很难表达复杂、抽象的规则。这一阶段被称为推理期

1970 年代,科学家们尝试通过知识库+推理的方式解决人工智能,通过构建庞大复杂的专家系统来模拟人类专家的智能水平。这些明确指定规则的方式存在一个最大的难题,就是很多复杂,抽象的概念无法用具体的代码实现。比如人类对图片的识别,对语言的理解过程,根本无法通过既定规则模拟。为了解决这类问题,一门通过让机器自动从数据中学习规则的研究学科诞生了,称为机器学习,并在 1980 年代成为人工智能中的热门学科。

在机器学习中,有一门通过神经网络来学习复杂、抽象逻辑的方向,称为神经网络。神经网络方向的研究经历了 2 起 2 落,并从 2012 年开始,由于效果极为显著,应用深层神经网络技术在计算机视觉、自然语言处理、机器人等领域取得了重大突破,部分任务上甚至超越了人类智能水平,开启了以深层神经网络为代表的人工智能的第 3 次复兴。深层神经网络有了一个新名字,叫做深度学习,一般来讲,神经网络和深度学习的本质区别并不大,深度学习特指基于深层神经网络实现的模型或算法。人工智能,机器学习,神经网络,深度学习的相互之间的关系如图所示。
在这里插入图片描述

1.1.2 机器学习

机器学习可以分为有监督学习(Supervised Learning)、无监督学习(Unsupervised
Learning)和强化学习(Reinforcement Learning),如图 所示:
在这里插入图片描述
有监督学习 有监督学习的数据集包含了样本𝒙与样本的标签𝒚,算法模型需要学习到映射𝑓𝜃: 𝒙 → 𝒚,其中𝑓𝜃代表模型函数,𝜃为模型的参数。在训练时,通过计算模型的预测值𝑓𝜃(𝒙)与真实标签𝒚之间的误差来优化网络参数𝜃,使得网络下一次能够预测更精准。常见的有监督学习有线性回归逻辑回归支持向量机随机森林等。

无监督学习 收集带标签的数据往往代价较为昂贵,对于只有样本𝒙的数据集,算法需要自行发现数据的模态,这种方式叫做无监督学习。无监督学习中有一类算法将自身作为监督信号,即模型需要学习的映射为𝑓𝜃: 𝒙 → 𝒙,称为自监督学习(Self-supervised Learning)。在训练时,通过计算模型的预测值𝑓𝜃(𝒙)与自身𝒙之间的误差来优化网络参数𝜃。常见的无监督学习算法有自编码器,生成对抗网络等。

强化学习 也称为增强学习,通过与环境进行交互来学习解决问题的策略的一类算法。与有监督、无监督学习不同,强化学习问题并没有明确的“正确的”动作监督信号,算法需要与环境进行交互,获取环境反馈的滞后的奖励信号,因此并不能通过计算动作与“正确动作”之间的误差来优化网络。常见的强化学习算法有 DQN,PPO 等。

1.1.3 神经网络与深度学习

神经网络算法是一类通过神经网络从数据中学习的算法,它仍然属于机器学习的范畴。受限于计算能力和数据量,早期的神经网络层数较浅,一般在 1~4 层左右,网络表达能力有限。随着计算能力的提升和大数据时代的到来,高度并行化的 GPU 和海量数据让大规模神经网络的训练成为可能。

2006 年,Geoffrey Hinton(杰弗里 希尔顿) 首次提出深度学习的概念,2012 年,8 层的深层神经网络 AlexNet 发布,并在图片识别竞赛中取得了巨大的性能提升,此后数十层,数百层,甚至上千层的神经网络模型相继提出,展现出深层神经网络强大的学习能力。我们一般将利用深层神经网络实现的算法或模型称作深度学习,本质上神经网络和深度学习是相同的。

我们来比较一下深度学习算法与其他算法,如图 1.3 所示。基于规则的系统一般会编写显示的规则逻辑,这些逻辑一般是针对特定的任务设计的,并不适合其他任务。

传统的机器学习算法一般会人为设计具有一定通用性的特征检测方法,如 SIFT,HOG 特征,这些特征能够适合某一类的任务,具有一定的通用性,但是如何设计特征方法,特征方法的好坏是问题的关键。神经网络的出现,使得人为设计特征这一部分工作可以通过神经网络让机器自动学习,不需要人类干预。但是浅层的神经网络的特征提取能力较为有限,而深层的神经网络擅长提取深层,抽象的高层特征,因此具有更好的性能表现。
在这里插入图片描述

1.2 神经网络发展简史

我们将神经网络的发展历程大致分为浅层神经网络阶段深度学习阶段,以 2006 年为分割点。2006 年以前,深度学习以神经网络和连接主义名义发展,历经了 2 次兴盛和 2 次寒冬;在 2006 年,Geoffrey Hinton 首次将深层神经网络命名为深度学习,开启了深度学习的第 3 次复兴之路。

1.2.1 浅层神经网络

1943 年,心理学家 Warren McCulloch 和逻辑学家 Walter Pitts 根据生物神经元(Neuron)结构,提出了最早的神经元数学模型,称为 MP 神经元模型。该模型的输出𝑓(𝒙) =ℎ(𝑔(𝒙)),其中𝑔(𝒙) = ∑𝑖 𝑥𝑖, 𝑥𝑖 ∈ {0,1},模型通过𝑔(𝒙)的值来完成输出值的预测,如果𝑔(𝒙) ≥ 𝟎,输出为 1;如果𝑔(𝒙) < 𝟎,输出为 0。可以看到,MP 神经元模型并没有学习能力,只能完成固定逻辑的判定
在这里插入图片描述

1958 年,美国心理学家 Frank Rosenblatt 提出了第一个可以自动学习权重的神经元模型,称为感知机(Perceptron),如图 1.5 所示,输出值与真实值之间的误差用于调整神经元的权重参数{ w 1 , w 2 , . . . , w n w_{1},w_{2},...,w_{n} w1,w2,...,wn)。感知机随后基于“Mark 1 感知机”硬件实现,如图 1.6 、1.7 所示,输入为 400 个单元的图像传感器,输出为 8 个节点端子,可以成功识别一些英文字母。我们一般认为 1943 年~1969 年为人工智能发展的第一次兴盛期
在这里插入图片描述

在这里插入图片描述
1969 年,美国科学家 Marvin Minsky 等人在出版的《Perceptrons》一书中指出了感知机等线性模型的主要缺陷,即无法处理简单的异或 XOR 等线性不可分问题。这直接导致了以感知机为代表的神经网络相关研究进入了低谷期,一般认为 1969 年~1982 年为人工智能发展的第一次寒冬。

尽管处于 AI 发展的低谷期,仍然有很多意义重大的研究相继发表,这其中最重要的成果就是反向传播算法(Backpropagation,简称 BP 算法)的提出,它依旧是现代深度学习的核心理论基础。实际上,反向传播的数学思想早在 1960 年代就已经被推导出了,但是并没有应用在神经网络上。直到 1974 年,美国科学家 Paul Werbos 在他的博士论文中第一次提出可以将 BP 算法应用到神经网络上,遗憾的是,这一成果并没有获得足够重视。直至1986 年,David Rumelhart 等人在 Nature 上发表了通过 BP 算法来表征学习的论文,BP 算法才获得了广泛的关注。

1982 年 John Hopfild 的循环连接的 Hopfield 网络的提出,开启了 1982 年~1995 年的第二次人工智能复兴的大潮,这段期间相继提出了卷积神经网络循环神经网络反向传播算法等算法模型。1986 年,David Rumelhart 和 Geoffrey Hinton 等人将 BP 算法应用在多层感知机上;1989 年Yann LeCun 等人将 BP 算法应用在手写数字图片识别上,取得了巨大成功,这套系统成功商用在邮政编码识别、银行支票识别等系统上;1997 年,应用最为广泛的循环神经网络变种之一 LSTM 被 Jürgen Schmidhuber 提出;同年双向循环神经网络也被提出。

遗憾的是,神经网络的研究随着以支持向量机(Support Vector Machine,简称 SVM)为代表的传统机器学习算法兴起而逐渐进入低谷,称为人工智能的第二次寒冬。支持向量机拥有严格的理论基础,需要的样本数量较少,同时也具有良好的泛化能力,相比之下,神经网络理论基础欠缺,可解释性差,很难训练深层网络,性能也一般。图 1.8 画出了 1943年~2006 年之间的重大时间节点。
在这里插入图片描述

1.2.2 深度学习

2006 年,Geoffrey Hinton 等人发现通过逐层预训练的方式可以较好地训练多层神经网络,并在 MNIST 手写数字图片数据集上取得了优于 SVM 的错误率,开启了第 3 次人工智能的复兴。在论文中,Geoffrey Hinton 首次提出了 Deep Learning 的概念,这也是(深层)神经网络被叫做深度学习的由来。2011 年,Xavier Glorot 提出了线性整流单元(Rectified Linear Unit, ReLU)激活函数,这是现在使用最为广泛的激活函数之一。2012 年,Alex Krizhevsky 提出了 8 层的深层神经网络 AlexNet,它采用了 ReLU 激活函数,并使用 Dropout 技术防止过拟合,同时抛弃了逐层预训练的方式,直接在 2 块 GTX580 GPU 上训练网络。AlexNet 在 ILSVRC-2012 图片识别比赛中获得了第一名,比第二名在 Top-5 错误率上降低了惊人的 10.9%。

AlexNet 模型提出后,各种各样的算法模型相继被发表,其中有 VGG 系列,GoogleNet,ResNet 系列,DenseNet 系列等等,其中 ResNet 系列网络实现简单,效果显著,很快将网络的层数提升至数百层,甚至上千层,同时保持性能不变甚至更好

除了有监督学习领域取得了惊人的成果,在无监督学习和强化学习领域也取得了巨大的成绩。2014 年,Ian Goodfellow 提出了生成对抗网络,通过对抗训练的方式学习样本的真实分布,从而生成逼近度较高的图片。此后,大量的生成对抗网络模型被提出,最新的图片生成效果已经达到了肉眼难辨真伪的逼真度。2016 年,DeepMind 公司应用深度神经网络到强化学习领域,提出了 DQN 算法,在 Atari 游戏平台中的 49 个游戏取得了人类相当甚至超越人类的水平;在围棋领域,DeepMind 提出的 AlphaGo 和 AlphaGo Zero 智能程序相继打败人类顶级围棋专家李世石、柯洁等;在多智能体协作的 Dota2 游戏平台,OpenAI 开发的 OpenAI Five 智能程序在受限游戏环境中打败了 TI8 冠军 OG 队,展现出了大量专业级的高层智能的操作。图 1.9 列出了 2006 年~2019 年之间重大的时间节点。
在这里插入图片描述

1.3 深度学习特点

与传统的机器学习算法、浅层神经网络相比,现代的深度学习算法通常具有如下特点。

1.3.1 数据量

早期的机器学习算法比较简单,容易快速训练,需要的数据集规模也比较小,如 1936年由英国统计学家 Ronald Fisher 收集整理的鸢尾花卉数据集 Iris 共包含 3 个类别花卉,每个类别 50 个样本。随着计算机技术的发展,设计的算法越来越复杂,对数据量的需求也随之增大。1998 年由 Yann LeCun 收集整理的 MNIST 手写数字图片数据集共包含 0~9 共 10类数字,每个类别多达 7000 张图片。随着神经网络的兴起,尤其是深度学习,网络层数较深,模型的参数量成百上千万个,为了防止过拟合,需要的数据集的规模通常也是巨大的。现代社交媒体的流行也让收集海量数据成为可能,如 2010 年的ImageNet 数据集收录了 14,197,122 张图片,整个数据集的压缩文件大小就有 154GB。

尽管深度学习对数据集需求较高,收集数据,尤其是收集带标签的数据,往往是代价昂贵的。数据集的形成通常需要手动采集、爬取原始数据,并清洗掉无效样本,再通过人类智能去标注数据样本,因此不可避免地引入主观偏差和随机误差。因此研究数据量需求较少的算法模型是非常有用的一个方向。
在这里插入图片描述

在这里插入图片描述

1.3.2 计算力

计算能力的提升是第三次人工智能复兴的一个重要因素。实际上,目前深度学习的基础理论在 1980 年代就已经被提出,但直到 2012 年基于 2 块 GTX580 GPU 训练的 AlexNet发布后,深度学习的真正潜力才得以发挥。传统的机器学习算法并不像神经网络这样对数据量和计算能力有严苛的要求,通常在 CPU 上串行训练即可得到满意结果。但是深度学习非常依赖并行加速计算设备,目前的大部分神经网络均使用 NVIDIA GPU 和 Google TPU或其他神经网络并行加速芯片训练模型参数。如围棋程序 AlphaGo Zero 在 64 块 GPU 上从零开始训练了 40 天才得以超越所有的 AlphaGo 历史版本;自动网络结构搜索算法使用了800 块 GPU 同时训练才能优化出较好的网络结构。

目前普通消费者能够使用的深度学习加速硬件设备主要来自 NVIDIA 的 GPU 显卡,图 1.12 例举了从 2008 年到 2017 年 NVIDIA GPU 和 x86 CPU 的每秒 10 亿次的浮点运算数(GFLOPS)的指标变换曲线。可以看到,x86 CPU 的曲线变化相对缓慢,而 NVIDIA GPU的浮点计算能力指数式增长,这主要是由日益增长的游戏计算量和深度学习计算量等驱动的。
在这里插入图片描述

1.3.3 网络规模

早期的感知机模型和多层神经网络层数只有 1 层或者 2~4 层,网络参数量也在数万左右。随着深度学习的兴起和计算能力的提升,AlexNet(8 层),VGG16(16 层),GoogLeNet(22 层),ResNet50(50 层),DenseNet121(121 层)等模型相继被提出,同时输入图片的大小也从 28x28 逐渐增大,变成 224x224,299x299 等,这些使得网络的总参数量可达到千万级别,如图 1.13 所示。
在这里插入图片描述

网络规模的增大,使得神经网络的容量相应增大,从而能够学习到复杂的数据模态,模型的性能也会随之提升;另一方面,网络规模的增大,意味着更容易出现过拟合现象,训练需要的数据集和计算代价也会变大。

1.3.4 通用智能

在过去,为了提升某项任务上的算法性能,往往需要手动设计相应的特征和先验设定,以帮助算法更好地收敛到最优解。这类特征或者先验往往是与具体任务场景强相关的,一旦场景发生了变动,这些依靠人工设计的特征或先验无法自适应新场景,往往需要重新设计算法模型,模型的通用性不强。

设计一种像人脑一样可以自动学习、自我调整的通用智能机制一直是人类的共同愿景。深度学习从目前来看,是最接近通用智能的算法之一。在计算机视觉领域,过去需要针对具体的任务设计征、添加先验的做法,已经被深度学习完全抛弃了,目前在图片识别、目标检测、语义分割等方向,几乎全是基于深度学习端到端地训练,获得的模型性能好,适应性强;在 Atria 游戏平台上,DeepMind 设计的 DQN 算法模型可以在相同的算法、模型结构和超参数的设定下,在 49 个游戏上获得人类相当的游戏水平,呈现出一定程度的通用智能。图 1.14 是 DQN 算法的网络结构,它并不是针对于某个游戏而设计的,而是可以运行在所有的 Atria 游戏平台上的 49 个游戏。
在这里插入图片描述

1.4 深度学习应用

深度学习算法已经广泛应用到人们生活的角角落落,例如手机中的语音助手,汽车上的智能辅助驾驶,人脸支付等等。我们将从计算机视觉、自然语言处理和强化学习 3 个领域入手,为大家介绍深度学习的一些主流应用。

1.4.1 计算机视觉

图片识别(Image Classification) 是常见的分类问题。神经网络的输入为图片数据,输出值为当前样本属于每个类别的概率,通常选取概率值最大的类别作为样本的预测类别。图片识别是最早成功应用深度学习的任务之一,经典的网络模型有 VGG 系列、Inception 系列、ResNet 系列等。

目标检测(Object Detection) 是指通过算法自动检测出图片中常见物体的大致位置,通常用边界框(Bounding box)表示,并分类出边界框中物体的类别信息,如图 1.15 所示。常见的目标检测算法有 RCNN,Fast RCNN,Faster RCNN,Mask RCNN,SSD,YOLO 系列等。
在这里插入图片描述

语义分割(Semantic Segmentation) 是通过算法自动分割并识别出图片中的内容,可以将语义分割理解为每个像素点的分类问题,分析每个像素点属于物体的类别,如图 1.16 所示。常见的语义分割模型有 FCN,U-net,SegNet,DeepLab 系列等。
在这里插入图片描述

视频理解(Video Understanding) 随着深度学习在 2D 图片的相关任务上取得较好的效果,具有时间维度信息的 3D 视频理解任务受到越来越多的关注。常见的视频理解任务有视频分类,行为检测,视频主体抽取等。常用的模型有 C3D,TSN,DOVF,TS_LSTM等。

图片生成(Image Generation) 通过学习真实图片的分布,并从学习到的分布中采样而获得逼真度较高的生成图片。目前主要的生成模型有 VAE 系列,GAN 系列等。其中 GAN 系列算法近年来取得了巨大的进展,最新 GAN 模型产生的图片样本达到了肉眼难辨真伪的效果,如图 1.17 为 GAN 模型的生成图片。
在这里插入图片描述

除了上述应用,深度学习还在其他方向上取得了不俗的效果,比如艺术风格迁移(图1.18),超分辨率,图片去燥/去雾,灰度图片着色等等一系列非常实用酷炫的任务,限于篇幅,不再敖述。
在这里插入图片描述

1.4.2 自然语言处理

机器翻译(Machine Translation) 过去的机器翻译算法通常是基于统计机器翻译模型,这也是 2016 年前 Google 翻译系统采用的技术。2016 年 11 月,Google 基于 Seq2Seq 模型上线了 Google 神经机器翻译系统(GNMT),首次实现了源语言到目标语言的直译技术,在多项任务上实现了 50~90%的效果提升。常用的机器翻译模型有 Seq2Seq,BERT,GPT,GPT-2 等,其中 OpenAI 提出的 GPT-2 模型参数量高达 15 亿个,甚至发布之初以技术安全考虑为由拒绝开源 GPT-2 模型。

聊天机器人(Chatbot) 聊天机器人也是自然语言处理的一项主流任务,通过机器自动与人类对话,对于人类的简单诉求提供满意的自动回复,提高客户的服务效率和服务质量。常应用在咨询系统、娱乐系统,智能家居等中。

1.4.3 强化学习

虚拟游戏 相对于真实环境,虚拟游戏平台既可以训练、测试强化学习算法,有可以避免无关干扰,同时也能将实验代价降到最低。目前常用的虚拟游戏平台有 OpenAI Gym,OpenAI Universe,OpenAI Roboschool,DeepMind OpenSpiel,MuJoCo 等,常用的强化学习算法有 DQN,A3C,A2C,PPO 等。在围棋领域,DeepMind AlaphGo 程序已经超越人类围棋专家;在 Dota2 和星际争霸游戏上,OpenAI 和 DeepMind 开发的智能程序也在限制规则下战胜了职业队伍。

机器人(Robotics) 在真实环境中,机器人的控制也取得了一定的进展。如 UC Berkeley在机器人的 Imitation Learning,Meta Learning,Few-shot Learning 等方向取得了不少进展。美国波士顿动力公司在人工智能应用中取得喜人的成就,其制造的机器人在复杂地形行走,多智能体协作等任务上表现良好(图 1.19)。

自动驾驶(Autonomous Driving) 被认为是强化学习短期内能技术落地的一个应用方向,很多公司投入大量资源在自动驾驶上,如百度、Uber,Google 无人车等,其中百度的无人巴士“阿波龙”已经在北京、雄安、武汉等地展开试运营,图 1.20 为百度的自动驾驶汽车。
在这里插入图片描述

1.5 深度学习框架

工欲善其事,必先利其器。在了解了深度学习及其发展简史后,我们来挑选一下深度学习要使用的工具吧。

1.5.1 主流框架

Theano 是最早的深度学习框架之一,由 Yoshua Bengio 和 Ian Goodfellow 等人开发,是一个基于 Python 语言、定位底层运算的计算库,Theano 同时支持 GPU 和 CPU 运算。由于 Theano 开发效率较低,模型编译时间较长,同时开发人员转投 TensorFlow等原因,Theano 目前已经停止维护。

Scikit-learn 是一个完整的面向机器学习算法的计算库,内建了常见的传统机器学习算法支持,文档和案例也较为丰富,但是 Scikit-learn 并不是专门面向神经网络而设计的,不支持 GPU 加速,对神经网络相关层实现也较欠缺

Caffe 由华人博士贾扬清在 2013 年开发,主要面向使用卷积神经网络的应用场合,并不适合其他类型的神经网络的应用。Caffe 的主要开发语言是 C++,也提供 Python 语言等接口,支持 GPU 和 CPU。由于开发时间较早,在业界的知名度较高,2017 年Facebook 推出了 Caffe 的升级版本 Cafffe2,Caffe2 目前已经融入到 PyTorch 库中

Torch 是一个非常优秀的科学计算库,基于较冷门的编程语言 Lua 开发。Torch 灵活性较高,容易实现自定义网络层,这也是 PyTorch 继承获得的优良基因。但是由于 Lua语言使用人群较小,Torch 一直未能获得主流应用。

MXNET 由华人博士陈天奇和李沐等人开发,已经是亚马逊公司的官方深度学习框架。采用了命令式编程和符号式编程混合方式,灵活性高,运行速度快,文档和案例也较为丰富。

PyTorch 是 Facebook 基于原有的 Torch 框架推出的采用 Python 作为主要开发语言的深度学习框架。PyTorch 借鉴了 Chainer 的设计风格,采用命令式编程,使得搭建网络和调试网络非常方便。尽管 PyTorch 在 2017 年才发布,但是由于精良紧凑的接口设计,PyTorch 在学术界获得了广泛好评。在 PyTorch 1.0 版本后,原来的 PyTorch 与 Caffe2进行了合并,弥补了 PyTorch 在工业部署方面的不足。总的来说,PyTorch 是一个非常优秀的深度学习框架。

Keras 是一个基于 Theano 和 TensorFlow 等框架提供的底层运算而实现的高层框架,提供了大量方便快速训练,测试的高层接口,对于常见应用来说,使用 Keras 开发效率非常高。但是由于没有底层实现,需要对底层框架进行抽象,运行效率不高,灵活性一般

TensorFlow 是 Google 于 2015 年发布的深度学习框架,最初版本只支持符号式编程。得益于发布时间较早,以及 Google 在深度学习领域的影响力,TensorFlow 很快成为最流行的深度学习框架。但是由于 TensorFlow 接口设计频繁变动,功能设计重复冗余,符号式编程开发和调试非常困难等问题,TensorFlow 1.x 版本一度被业界诟病。2019年,Google 推出 TensorFlow 2 正式版本,将以动态图优先模式运行,从而能够避免TensorFlow 1.x 版本的诸多缺陷,已获得业界的广泛认可。

目前来看,TensorFlow 和 PyTorch 框架是业界使用最为广泛的两个深度学习框架,TensorFlow 在工业界拥有完备的解决方案和用户基础,PyTorch 得益于其精简灵活的接口设计,可以快速设计调试网络模型,在学术界获得好评如潮。TensorFlow 2 发布后,弥补了 TensorFlow 在上手难度方面的不足,使得用户可以既能轻松上手 TensorFlow 框架,又能无缝部署网络模型至工业系统。本书以 TensorFlow 2.0 版本作为主要框架,实战各种深度学习算法。

我们这里特别介绍 TensorFlow 与 Keras 之间的联系与区别。Keras 可以理解为一套高层 API 的设计规范,Keras 本身对这套规范有官方的实现,在 TensorFlow 中也实现了这套规范,称为 tf.keras 模块,并且 tf.keras 将作为 TensorFlow 2 版本的唯一高层接口,避免出现接口重复冗余的问题。如无特别说明,本书中 Keras 均指代 tf.keras。

1.5.2 TensorFlow 2 与 1.x

TensorFlow 2 是一个与 TensorFlow 1.x 使用体验完全不同的框架,TensorFlow 2 不兼容TensorFlow 1.x 的代码,同时在编程风格、函数接口设计等上也大相径庭,TensorFlow 1.x的代码需要依赖人工的方式迁移,自动化迁移方式并不靠谱。Google 即将停止支持TensorFlow 1.x,不建议学习 TensorFlow 1.x 版本。

TensorFlow 2 支持动态图优先模式,在计算时可以同时获得计算图与数值结果,可以代码中调试实时打印数据,搭建网络也像搭积木一样,层层堆叠,非常符合软件开发思维。

以简单的2.0 + 4.0的相加运算为例,在 TensorFlow 1.x 中,首先创建计算图:

import tensorflow as tf
# 1.创建计算图阶段
# 2.创建2个输入端子,指定类型和名字
a_ph=tf.placeholder(tf.float32,name='variable_a');
b_ph=tf.placeholder(tf.float32,name='variable_b');
# 创建输出端子的运算操作,并命名
c_op=tf.add(a_ph,b_ph,name='variable_a')

创建计算图的过程就类比通过符号建立公式𝑐 = 𝑎 + 𝑏的过程,仅仅是记录了公式的计算步骤,并没有实际计算公式的数值结果需要通过运行公式的输出端子𝑐,并赋值𝑎 =2.0, 𝑏 = 4.0才能获得𝑐的数值结果:

#2. 运行计算图阶段
# 创建运行环境
sess=tf.InteractiveSession()
# 初始化步骤也需要为操作运行
init=tf.global_variables_initializer()
sess.run(init) #运行初始化操作,完成初始化
#运行端输出端子,需要给输入端子赋值
c_numpy=sess.run(c_op,feed_dict={a_ph:2.,b_ph:4.});
#运算完输出端子才能得到数值类型的c_numpy
print('a+b=',c_numpy)

可以看到,在 TensorFlow 中完成简单的2.0 + 4.0尚且如此繁琐,更别说创建复杂的神经网络算法有多艰难,这种先创建计算图后运行的编程方式叫做符号式编程。接下来我们使用 TensorFlow 2 来完成2.0 + 4.0运算:

# 1.创建输入张量
a=tf.constant(2.)
b=tf.constant(4.)
# 2.直接计算并打印
print('a+b=',a+b)

这种运算时同时创建计算图𝑎 + 𝑏和计算数值结果2.0 + 4.0的方式叫做命令式编程,也称为动态图优先模式。TensorFlow 2 和 PyTorch 都是采用动态图(优先)模式开发,调试方便,所见即所得。一般来说,动态图模型开发效率高,但是运行效率可能不如静态图模式,TensorFlow 2 也支持通过 tf.function 将动态图优先模式的代码转化为静态图模式,实现开发和运行效率的双赢。

1.5.3 功能演示

深度学习的核心是算法的设计思想,深度学习框架只是我们实现算法的工具。下面我们将演示 TensorFlow 深度学习框架的 3 大核心功能,从而帮助我们理解框架在算法设计中扮演的角色。

a) 加速计算
神经网络本质上由大量的矩阵相乘,矩阵相加等基本数学运算构成,TensorFlow 的重要功能就是利用 GPU 方便地实现并行计算加速功能。为了演示 GPU 的加速效果,我们通过完成多次矩阵 A 和矩阵 B 的矩阵相乘运算的平均运算时间来验证。其中矩阵 A 的 shape为[1,𝑛],矩阵 B 的 shape 为[𝑛, 1],通过调节 n 即可控制矩阵的大小。

首先我们分别创建使用 CPU 和 GPU 运算的 2 个矩阵:

# 创建在CPU上运行的2个矩阵
import tensorflow as tf
# 创建在CPU上运行的2个矩阵
n=5
with tf.device('/cpu:0'):
  cpu_a=tf.random.normal([1,n])
  cpu_b=tf.random.normal([3,n])
  print(cpu_a.device,cpu_b.device)
# 创建使用GPU运算的2个矩阵
with tf.device('/device:gpu:0'):
  gpu_a=tf.random.normal([1,n])
  gpu_b=tf.random.normal([n,1])
  print(gpu_a.device,gpu_b.device)

并通过 timeit.timeit()函数来测量 2 个矩阵的运时间:

import timeit
import_module = "import tensorflow as tf"
testcode = ''' 
def cpu_run():
  with tf.device('/device:cpu:0'):
    cpu_a=tf.random.normal([1,100])
    cpu_b=tf.random.normal([100,1])
    c=tf.matmul(cpu_a,cpu_b)
  return c
'''
testcode2='''
def gpu_run():
  with tf.device('/device:gpu:0'):
    gpu_a=tf.random.normal([1,100])
    gpu_b=tf.random.normal([100,1])
    c=tf.matmul(gpu_a,gpu_b)
  return c
'''

print(timeit.timeit(stmt=testcode,setup=import_module))
print(timeit.timeit(stmt=testcode2,setup=import_module))

我们将不同大小的 n 下的 CPU 和 GPU 的运算时间绘制为曲线,如图 1.21 所示。可以看到,在矩阵 A 和 B 较小时,CPU 和 GPU 时间几乎一致,并不能体现出 GPU 并行计算的优势;在矩阵较大时,CPU 的计算时间明显上升,而 GPU 充分发挥并行计算优势,运算时间几乎不变。
在这里插入图片描述

b) 自动梯度
在使用 TensorFlow 构建前向计算过程的时候,除了能够获得数值结果,TensorFlow 还会自动构建计算图,通过 TensorFlow 提供的自动求导的功能,可以不需要手动推导,即可计算出输出对网络的偏导数。
y = a w 2 + b w + c y=a w^{2}+b w+c y=aw2+bw+c
d y d w = 2 a w + b \frac{\mathrm{d} y}{\mathrm{d} w}=2 a w+b dwdy=2aw+b
考虑在(a,b,c,w)=(1,2,3,4)处的导数, d y d w = 2 ∗ 1 ∗ 4 + 2 = 10 \frac{d y}{d w}=2 * 1 * 4+2=10 dwdy=214+2=10
通过Tensorflow实现如下

import tensorflow as tf
# 创建4个张量
a=tf.constant(1.)
b=tf.constant(2.)
c=tf.constant(3.)
w=tf.constant(4.)

with tf.GradientTape() as tape: #构建梯度环境
  tape.watch([w]) # 将w加入梯度跟踪列表
  # 构建计算过程
  y=a*w**2+b*w+c
# 求导
[dy_dw]=tape.gradient(y,[w])
print(dy_dw) # 打印出导数

tf.Tensor(10.0, shape=(), dtype=float32)

c) 常用神经网络接口
TensorFlow 除了提供底层的矩阵相乘,相加等运算函数,还内建了常用网络运算函数,常用网络层,网络训练,网络保存与加载,网络部署等一系列深度学习系统的便捷功能。使用 TensorFlow 开发网络,可以方便地利用这些功能完成常用业务流程,高效稳定。

1.6 开发环境安装

在领略完深度学习框架所带来的的便利后,我们来着手在本地计算机环境安装TensorFlow 最新版框架。TensorFlow 框架支持多种常见的操作系统,如 Windows 10,Ubuntu 18.04, Mac OS 等等,同时也支持运行在 NVIDIA 显卡上的 GPU 版本和仅适用 CPU完成计算的 CPU 版本。我们以最为常见的 Windows 10 系统,NVIDIA GPU,Python 语言环境为例,介绍如何安装 TensorFlow 框架及其他开发软件等。

一般来说,开发环境安装分为 4 大步骤:安装 Python 解释器 Anaconda,安装 CUDA加速库,安装 TensorFlow 框架,安装常用编辑器。

1.6.1 Anaconda 安装

Python 解释器是让 Python 语言编写的代码能够被 CPU 执行的桥梁,是 Python 语言的核心。用户可以从 官网下载最新版本(Python 3.8)的解释器,像普通的应用软件一样安装完成后,就可以调用 python.exe 程序执行 Python 语言编写的源代码文件(*.py)。

我们这里选择安装集成了 Python 解释器和虚拟环境等一系列辅助功能的 Anaconda 软件,通过安装 Anaconda 软件,可以同时获得 Python 解释器,包管理,虚拟环境等一系列便捷功能,何乐而不为呢。我们从 网址进入 Anaconda 下载页面,选择 Python 最新版本的下载链接即可下载,下载完成后安装即可进入安装程序。如图 1.22 所示,勾选”Add Anaconda to my PATH environmentvariable”一项,这样可以通过命令行方式调用 Anaconda 的程序。如图 1.23 所示,安装程序询问是否连带安装 VS Code软件,选择skip即可。整个安装流程持续5~10分钟,具体时间需依据计算机性能而定。
在这里插入图片描述
安装完成后,怎么验证 Anaconda 是否安装成功呢?通过键盘上的 Windows 键+R 键,即可调出运行程序对话框,输入 cmd 回车即打开 Windows 自带的命令行程序 cmd.exe,或者点击开始菜单,输入 cmd 也可搜索到 cmd.exe 程序,打开即可。输入 conda list 命令即可查看Python 环境已安装的库,如果是新安装的 Python 环境,则列出的库都是 Anaconda 自带已默认安装的软件库,如图 1.24 所示。如果 conda list 能够正常弹出一系列的库列表信息,说明 Anaconda 软件安装成功,如果 conda 命名不能被识别,则说明安装失败,需要重新安装。
在这里插入图片描述

1.6.2 CUDA 安装

目前的深度学习框架大都基于 NVIDIA 的 GPU 显卡进行加速运算,因此需要安装NVIDIA 提供的 GPU 加速库 CUDA 程序。在安装 CUDA 之前,请确认本地计算机具有支持 CUDA 程序的 NVIDIA 显卡设备,如果计算机没有 NVIDIA 显卡,如部分计算机显卡生产商为 AMD,以及部分 MacBook 笔记本电脑,则无法安装 CUDA 程序,因此可以跳过这一步,直接进入 TensorFlow 安装。CUDA 的安装分为 CUDA 软件的安装、cuDNN 深度神经网络加速库的安装和环境变量配置三个步骤,安装稍微繁琐,请读者在操作时思考每个步骤的原因,避免死记硬背流程。

CUDA 软件安装 打开 CUDA 程序的下载官网:https://developer.nvidia.com/cuda-10.0-download-archive,这里我们使用 CUDA 10.0 版本,依次选择 Windows 平台,x86_64 架构,10 系统,exe(local)本地安装包,再选择 Download 即可下载 CUDA 安装软件。下载完成后,打开安装软件。如图 1.25 所示,选择”Custom”选项,点击 NEXT 按钮进入图 1.26安装程序选择列表,在这里选择需要安装和取消不需要安装的程序。在 CUDA 节点下,取消”Visual Studio Integration”一项;在“Driver components”节点下,比对目前计算机已经安装的显卡驱动“Display Driver”的版本号“Current Version”和 CUDA 自带的显卡驱动版本号“New Version”,如果“Current Version”大于“New Version”,则需要取消“Display Driver”的勾,如果小于或等于,则默认勾选即可。设置完成后即可正常安装完成。
在这里插入图片描述
安装完成后,我们来测试 CUDA 软件是否安装成功。打开 cmd 命令行,输入“nvcc -V”,即可打印当前 CUDA 的版本信息,如图 1.29 所示,如果命令无法识别,则说明安装失败。同时我们也可从 CUDA 的安装路径“C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v10.0\bin”下找到“nvcc.exe”程序,如图 1.28 所示。
在这里插入图片描述
cuDNN 神经网络加速库安装 CUDA 并不是针对于神经网络设计的 GPU 加速库,它面向各种需要并行计算的应用设计。如果希望针对于神经网络应用加速,需要额外安装cuDNN 库。需要注意的是,cuDNN 库并不是运行程序,只需要下载解压 cuDNN 文件,并配置 Path 环境变量即可。

打开网址 https://developer.nvidia.com/cudnn,选择“Download cuDNN”,由于 NVIDIA公司的规定,下载 cuDNN 需要先登录,因此用户需要登录或创建新用户后才能继续下载。登录后,进入 cuDNN 下载界面,勾选“I Agree To the Terms of the cuDNN SoftwareLicense Agreement”,即可弹出 cuDNN 版本下载选项。我们选择 CUDA 10.0 匹配的 cuDNN版本,并点击“cuDNN Library for Windows 10”链接即可下载 cuDNN 文件。需要注意的是,cuDNN 本身具有一个版本号,同时它还需要和 CUDA 的版本号对应上,不能下错不匹配 CUDA 版本号的 cuDNN 文件。

在这里插入图片描述
下载完成 cuDNN 文件后,解压并进入文件夹,我们将名为“cuda”的文件夹重命名为“cudnn765”,并复制此文件夹。进入 CUDA 的安装路径 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0,粘贴“cudnn765”文件夹即可,此处可能会弹出需要管理员权限的对话框,选择继续即可粘贴,如图 1.31 所示。
在这里插入图片描述

环境变量 Path 配置 上述 cudnn 文件夹的复制即已完成 cuDNN 的安装,但为了让系统能够感知到 cuDNN 文件的位置,我们需要额外配置 Path 环境变量。打开文件浏览器,在“我的电脑”上右击,选择“属性”,选择“高级系统属性”,选择“环境变量”,如图1.32。在“系统变量”一栏中选中“Path”环境变量,选择“编辑”,如图 1.33 所示。选择“新建”,输入我们 cuDNN 的安装路径“C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v10.0\cudnn765\bin”,并通过“向上移动”按钮将这一项上移置顶。
在这里插入图片描述
CUDA 安装完成后,环境变量中应该包含“C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v10.0\bin”,“C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v10.0\libnvvp”和“C:\Program Files\NVIDIA GPU ComputingToolkit\CUDA\v10.0\cudnn765\bin”三项,具体的路径可能依据实际路径略有出入,如图测
1.34 所示,确认无误后依次点击确定,关闭所有对话框。
在这里插入图片描述

1.6.3 TensorFlow 安装

TensorFlow 和其他的 Python 库一样,使用Python 包管理工具 pip install 命令即可安装。安装 TensorFlow 时,需要根据电脑是否 NVIDIAGPU 显卡来确定是安装性能更强的GPU 版本还是性能一般的 CPU 版本。

国内使用 pip 命令安装时,可能会出现下载速度缓慢甚至连接断开的情况,需要配置国内的 pip 源,只需要在 pip install 命令后面带上“-i 源地址”即可,例如使用清华源安装numpy 包,首先打开 cmd 命令行程序,输入:

# 使用国内清华源安装 numpy
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

即可自动下载并按着 numpy 库,配置上国内源的 pip 下载速度会提升显著。现在我们来 TensorFlow GPU 最新版本:

# 使用清华源安装 TensorFlow GPU 版本
pip install -U tensorflow-gpu -i https://pypi.tuna.tsinghua.edu.cn/simple

上述命令自动下载 TensorFlow GPU 版本并安装,目前是 TensorFlow 2.0.0 正式版,“-U”参数指定如果已安装此包,则执行升级命令。

现在我们来测试 GPU 版本的 TensorFlow 是否安装成功。在 cmd 命令行输入 ipython 进入 ipython 交互式终端,输入“import tensorflow as tf”命令,如果没有错误产生,继续输入“tf.test.is_gpu_available()”测试 GPU 是否可用,此命令会打印出一系列以“I”开头的信息(Information),其中包含了可用的 GPU 显卡设备信息,最后会返回“True”或者“False”,代表了 GPU 设备是否可用,如图 1.35 所示。如果为 True,则 TensorFlow GPU版本安装成功;如果为 False,则安装失败,需要再次检测 CUDA,cuDNN,环境变量等步骤,或者复制错误,从搜索引擎中寻求帮助。
在这里插入图片描述
如果不能安装 TensorFlow GPU 版本,则可以安装 CPU 版本暂时用作学习。CPU 版本无法利用 GPU 加速运算,计算速度相对缓慢,但是作为学习介绍的算法模型一般不大,使用 CPU 版本也能勉强应付,待日后对深度学习有了一定了解再升级 NVIDIA GPU 设备也未尝不可。亦或者,安装 TensorFlow GPU 版本可能容易出现安装失败的情况,很多读者朋友动手能力一般,如果折腾了很久还不能搞定,可以直接安装 CPU 版本先使用着。

安装 CPU 版本的命令为:

# 使用国内清华源安装 TensorFlow CPU 版本
pip install -U tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完后,在 ipython 中输入“import tensorflow as tf”命令即可验证 CPU 版本是否安装成功。

TensorFlow GPU/CPU 版本安装完成后,可以通过“tf.version”查看本地安装的TensorFlow 版本号,如图 1.36所示
在这里插入图片描述
常用的 python 库也可以顺带安装:

# 使用清华源安装常用 python 库
pip install -U numpy matplotlib pillow pandas -i https://pypi.tuna.tsinghua.edu.cn/simple

1.6.4 常用编辑器安装

使用 Python 语言编写程序的方式非常多,可以使用 ipython 或者 ipython notebook 方式交互式编写代码,也可以利用 Sublime Text,PyCharm 和 VS Code 等综合 IDE 开发中大型项目。本书推荐使用 PyCharm 编写和调试,使用 VS Code 交互式开发,这两者都可以免费使用,用户自行下载安装,并配置 Python 解释器,限于篇幅,不再敖述。接下来,让我们开启深度学习之旅吧!

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安替-AnTi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值