深度学习详解

978-7-115-64211-0
作者: 王琦杨毅远江季
译者:
编辑: 郭泳泽

图书目录:

详情

本书根据李宏毅老师“机器学习”公开课中与深度学习相关的内容编写而成,介绍了卷积神经网络、Transformer、生成模型、自监督学习(包括 BERT 和 GPT)等深度学习常见算法,并讲解了对抗攻击、领域自适应、强化学习、元学习、终身学习、网络压缩等深度学习相关的进阶算法. 在理论严谨的基础上,本书保留了公开课中大量生动有趣的例子,帮助读者从生活化的角度理解深度学习的概念、建模过程和核心算法细节.

图书摘要

版权信息

书名:深度学习详解

ISBN:978-7-115-64211-0

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


版  权

编  著 王 琦 杨毅远 江 季

责任编辑 郭泳泽

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内 容 提 要

本书根据李宏毅老师“机器学习”公开课中与深度学习相关的内容编写而成,介绍了卷积神经网络、Transformer、生成模型、自监督学习(包括BERT和GPT)等深度学习常见算法,并讲解了对抗攻击、领域自适应、强化学习、元学习、终身学习、网络压缩等深度学习相关的进阶算法. 在理论严谨的基础上,本书保留了公开课中大量生动有趣的例子,帮助读者从生活化的角度理解深度学习的概念、建模过程和核心算法细节.

本书适合对深度学习感兴趣、想要入门深度学习的读者阅读,也可作为深度学习相关课程的教材.

致  谢

本书编者特向台湾大学李宏毅老师致以诚挚的谢意!

感谢李老师的分享精神,让无数的机器学习和深度学习初学者从他的课程中受益. 感谢李老师对编者以及Datawhale开源学习出版项目的支持,使得本书的正式出版成为可能!

李宏毅老师给本书编者的签名

前  言

深度学习在近年来取得了令人瞩目的发展,无论是传统的图像分类、目标检测等技术,还是以Sora、ChatGPT为代表的生成式人工智能,都离不开深度学习. 深度学习相关的图书有很多,但大部分都偏重理论推导及分析,缺少对深度学习内容的直观解释,而直观的解释恰恰对初学者非常重要. 理解深度学习方法的具体用途,以及掌握其基本的内部结构,有利于我们培养深度学习直觉,更好地将其作为工具,进而在其理论的基础上进行创新.

笔者在学习深度学习的过程中经常听人提及一门公开课,即李宏毅老师的“机器学习”公开课. 虽然名为“机器学习”,但该课程经过多年发展,内容已经几乎全部与深度学习相关了. 笔者也便选择其作为学习课程,获益匪浅,于是将所学内容结合笔者个人的理解和体会初步整理成笔记. 之后,在众多优秀开源教程的启发下,笔者决定将该笔记制作成教程,以让更多的深度学习初学者受益. 笔者深知一个人的力量有限,便邀请另外两位编著者(杨毅远、江季)参与教程的编写. 杨毅远在人工智能研究方面颇有建树,曾多次在中国计算机学会A类、B类会议中以第一作者的身份发表论文;江季对深度学习也有较深的理解,有丰富的深度学习研究经历,发表过顶级会议论文,也获得过相关专利. 杨毅远与江季的加入让教程的创作焕发出了新的生机. 通过不懈的努力,我们在GitHub 上发布线上教程,分享给深度学习的初学者. 截至目前,该教程被“标星”逾万次.

为了更好地优化教程,我们尝试把该教程作为教材,并组织上百人的组队学习活动,受到了一致好评. 不少学习者通过组队学习入门了深度学习,并给出了大量的反馈,这也帮助我们进一步改进了教程. 为了方便读者阅读,我们历时1年多制作了电子版的笔记,并对很多地方进行了优化. 非常荣幸的是,人民邮电出版社的陈冀康老师联系我们商量出版事宜. 通过出版社团队和我们不断的努力,本书得以出版.

本书主要内容源于李宏毅老师“机器学习”公开课的部分内容,在其基础上进行了一定的原创. 比如,为了尽可能地降低阅读门槛,笔者对公开课的精华内容进行选取并优化,对所涉及的公式给出详细的推导过程,对较难理解的知识点进行了重点讲解和强化,方便读者较为轻松地入门. 此外,为了丰富内容,笔者还补充了不少公开课内容之外的深度学习相关知识.

本书共 19 章,大体上可分为两个部分:第一部分包括第 1 ~ 11章,介绍深度学习基础知识以及经典深度学习算法;第二部分包括第 12 ~ 19章,介绍深度学习算法更加深入的方向. 第二部分各章相对独立,读者可根据自己的兴趣和时间选择性阅读.

李宏毅老师是台湾大学教授,其研究方向为机器学习、深度学习及语音识别与理解. 李老师的“机器学习”课程很受广大学习者的欢迎,其幽默风趣的授课风格深受大家喜爱. 此外,李老师的课程内容很全面,覆盖了深度学习必须掌握的常见理论,能让学习者对于深度学习的绝大多数领域都有一定了解,从而进一步选择想要深入的方向进行学习. 读者在观看“机器学习”公开课时,可以使用本书作为辅助资料,以进一步深入理解课程内容.

本书配有索引,方便读者根据自己的需求快速找到知识点所对应的篇幅高效学习. 此外,笔者认为,深度学习是一个理论与实践相结合的学科,读者不仅要理解其算法背后的数学原理,还要通过上机实践来实现算法. 本书配有Python代码实现,可以让读者通过动手实现各种经典的深度学习算法,充分掌握深度学习算法的原理. 值得注意的是,本书配套的Python 代码均可在异步社区本书页面的“配套资源”处下载. 本书经过 1年多的优化,吸收了读者对开源版教程的众多反馈. 相信本书一定会对读者的学习和工作大有裨益.

衷心感谢李宏毅老师的授权和开源奉献精神,李老师的无私使本书得以出版,并能够造福更多对深度学习感兴趣的读者. 本书由开源组织Datawhale 的成员采用开源协作的方式完成,历时 1 年有余,参与者包括 3 位编著者(笔者、杨毅远和江季)和3位 Datawhale的小伙伴(范晶晶、谢文睿和马燕鹏).此外,感谢付伟茹同学对本书初稿提出的宝贵建议. 在本书写作和出版过程中,人民邮电出版社提供了很多出版的专业意见和支持,使得本书较开源版本更加规范、更加系统化. 在此特向人民邮电出版社信息技术分社社长陈冀康老师和本书的责任编辑郭泳泽老师致谢.

深度学习发展迅速,笔者水平有限,书中难免有疏漏和表述不当的地方,还望各位读者批评指正.

王 琦

2024年5月22日

资源与支持

资源获取

本书提供如下资源:

视频课程对照表;

配套代码文件;

本书思维导图;

异步社区7天VIP会员.

要获得以上资源,您可以扫描下方二维码,根据指引领取. 注意:部分资源可能需要验证您的身份才能提供.

提交错误信息

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏,欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量.

当您发现错误时,请登录异步社区(www.epubit.com),按书名搜索,进入本书页面,单击“发表勘误”,输入错误信息,单击“提交勘误”按钮即可(见下页图). 本书的作者和编辑会对您提交的错误信息进行审核,确认并接受后,您将获赠异步社区的100积分. 积分可用于在异步社区兑换优惠券、样书或奖品.

与我们联系

我们的联系邮箱是contact@epubit.com.cn.

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈.

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们.

如果您所在的学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们.

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发给我们. 您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源.

关于异步社区和异步图书

“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作者与读者在线交流互动,以及传统出版与数字出版的融合发展.

“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域40余年的发展与积淀. 异步图书面向IT行业以及各行业使用IT的用户.

主要符号表

标量

向量

矩阵

单位矩阵

实数集

矩阵的转置

的按元素乘积

关于的导数

关于的偏导数

关于的梯度

具有分布的随机变量

的期望

的方差

的指数函数

的对数函数

sigmoid函数,

状态

动作

奖励

策略

折扣因子

轨迹

时刻时的回报

取最小值时的值

第1章 机器学习基础

在本书的开始,先简单介绍一下机器学习(Machine Learning,ML)深度学习(Deep Learning,DL)的基本概念. 机器学习,顾名思义,机器具有学习的能力. 具体来讲,机器学习就是让机器具备找一个函数的能力.机器具备找一个函数的能力以后,就可以做很多事. 比如语音识别,机器听一段声音,产生这段声音对应的文字.我们需要的是一个函数,它的输入是一段声音信号,输出是这段声音信号的内容.这个函数显然非常复杂,难以写出来,因此我们想通过机器的力量把这个函数自动找出来. 此外,还有好多的任务需要找一个很复杂的函数,以图像识别为例,图像识别函数的输入是一张图片,输出是这张图片里面的内容. AlphaGo 也可以看作一个函数,机器下围棋需要的就是一个函数,该函数的输入是棋盘上黑子和白子的位置,输出是机器下一步应该落子的位置.

随着要找的函数不同,机器学习有了不同的类别.假设要找的函数的输出是一个数值或标量(scalar),这种机器学习任务称为回归(regression).举个回归的例子,假设机器要预测未来某个时间段的 PM2.5 数值.机器要找一个函数 ,其输入可能是各种跟预测PM2.5数值有关的指数,包括今天的PM2.5数值、平均温度、平均臭氧浓度等,输出是明天中午的PM2.5数值.

除了回归,还有一种常见的机器学习任务是分类(classification).分类任务是要让机器做选择题. 先准备一些选项,这些选项称为类别(class),机器要找的函数会从设定好的选项里面选择一个当作输出.举个例子,我们可以在邮箱账户里设置垃圾邮件检测规则,这套规则就可以看作输出邮件是否为垃圾邮件的函数.分类问题不一定只有两个选项,也可能有多个选项 .

AlphaGo 解决的是分类问题,如果让机器下围棋,则选项与棋盘的位置有关.棋盘上有19×19个位置,机器其实是做一道有19×19个选项的选择题.机器要找一个函数,该函数的输入是棋盘上黑子和白子的位置,输出就是从19×19个选项里面选出一个最适合的选项,也就是从19×19个可以落子的位置里面,选出下一步应该落子的位置.

在机器学习领域,除了回归和分类,还有结构化学习(structured learning).机器不仅要做选择题或输出一个数字,还要产生一个有结构的结果,比如一张图、一篇文章等.这种让机器产生有结构的结果的学习过程称为结构化学习.

1.1 案例学习

本节以视频的观看次数预测为例介绍机器学习的运作过程.假设有人想要通过视频平台赚钱,他会在意频道有没有流量,这样他才会知道自己能不能获利.假设从后台可以看到很多相关的信息,比如每天点赞的人数、订阅人数、观看次数.根据一个频道过往所有的信息,可以预测明天的观看次数. 我们想寻找一个函数,该函数的输入是后台的信息,输出是次日这个频道的预计观看次数.

机器学习的过程分为3个步骤.第1个步骤是写出一个带有未知参数的函数 ,它能预测未来观看次数. 比如将函数写成

  (1.1)

其中,是要预测的值,假设这里要预测的是2月26日这个频道总的观看次数.是这个频道前一天(2月25日)的观看次数. 是数值;是未知的参数,我们只能隐约地猜测它们的值. 猜测往往来自对这个问题本质上的了解,即领域知识(domain knowledge).机器学习需要一些领域知识,比如一天的观看次数总是会跟前一天的观看次数有点关联,所以不妨把前一天的观看次数乘以一个数值,再加上一个 做修正,当作对2月26日观看次数的预测. 这只是一个猜测,不一定是对的,稍后我们再来修正这个猜测.

带有未知参数(parameter)的函数称为模型(model). 模型在机器学习里面,就是一个带有未知参数的函数,特征(feature) 是这个函数里面已知的来自后台的信息——2月25日的观看次数是已知的. 称为权重(weight)称为偏置(bias).

第2个步骤是定义损失(loss),损失也是一个函数,记为.损失函数输出的值意味着,当把模型参数设定为某个数值时,这个数值好还是不好.举一个具体的例子,如果我们猜测,则函数就变成了 .对于从训练数据中计算损失这个问题,训练数据是这个频道过去的观看次数.如果我们已经掌握2017年1月1日~ 2020年12月31日的观看次数(如图1.1 所示)接下来就可以计算损失了.

图1.1 2017年1月1日~ 2020年12月31日的观看次数(此处的观看次数是随机生成的)

把2017年1月1日的观看次数代入函数,得到

  (1.2)

根据我们的猜测,预测次日的观看次数为 ,但真实的观看次数为4900,我们高估了这个频道的观看次数. 可以评估一下估测值跟真实值间的差距.评估差距其实有多种方式,比如取二者差的绝对值:

  (1.3)

真实值称为标签(label).

我们不仅可以用2017年1月1日的值来预测2017年1月2日的值,也可以用2017年1月2日的值来预测2017年1月3日的值.根据2017年1月2日的观看次数4900,我们预测2017年1月3日的观看次数是5400.接下来计算 5400跟标签(7500)之间的差距:

  (1.4)

以此类推,把接下来每一天的差距通通加起并取平均,得到损失

  (1.5)

其中, 代表训练数据数,即4年来所有的训练数据. 是每一笔训练数据的误差平均以后的结果.越大,代表我们猜测的这组参数越差;越小,代表这组参数越好.

估测值跟真实值之间的差距,其实有不同的评估方法,比如计算二者差的绝对值,如式(1.6) 所示,这个评估方式所计算的值称为平均绝对误差(Mean Absolute Error,MAE).

  (1.6)

也可以计算 二者差的平方,如式(1.7) 所示,称为这个评估方式所计算的值均方误差(Mean Squared Error,MSE).

  (1.7)

在有些任务中, 都是概率分布,这时候可能会选择计算交叉熵(cross entropy).}刚才举的那些数字不是真实的例子,以下数字才是真实的例子,是用一个频道真实的后台数据计算出来的结果.我们可以调整不同的和不同的 ,计算损失,并画出图1.2 所示的等高线图.在这个等高线图中,色相越红,代表计算出来的损失越大,也就代表这一对越差;色相越蓝,就代表损失越小,也就代表这一对越好. 将损失小的放到函数里面,预测会更精准. 从图1.2 中我们得知,如果为代入一个接近1的值,并为代入一个较小的正值(比如100),则预测较精准,这跟大家的预期可能比较接近:相邻两天观看次数总是差不多的.

在图1.2 中,我们尝试了不同的参数,并且计算了损失. 这样画出来的等高线图称为误差表面(error surface).

图1.2 误差表面

机器学习的第3个步骤是解一个优化问题,即找到最好的一对,使损失的值最小. 我们用符号,代表最好的一对.

对于这个问题,梯度下降(gradient descent)是最常用的优化方法.为了简化起见,先假设只有参数是未知的,而是已知的.当为代入不同的数值时,就会得到不同的损失,从而绘制出误差表面,只是刚才在前一个例子里面,误差表面是二维的,而这里只有一个参数,所以误差表面是一维的.怎么才能找到一个让损失值最小呢?如图1.3 所示,首先要随机选取一个初始的点.接下来计算,也就是时,损失对参数的微分,得到处误差表面的切线(即蓝色虚线)的斜率. 如果斜率是负的,就代表左边比较高、右边比较低,此时把的值变大,就可以让损失变小. 相反,如果斜率是正的,就代表把变小可以让损失变小.我们可以想象有一个人站在这个地方左右环视,看看左边比较高还是右边比较高,并往比较低的地方跨出一步.步伐的大小取决于以下两件事情.

图1.3 优化过程

这个地方的斜率,斜率大,步伐就跨大一点;斜率小,步伐就跨小一点.

学习率(learning rate).学习率可以自行设定,如果设大一点,每次参数更新就会量大,学习可能就比较快;如果设小一点,参数更新就很慢,每次只改变一点点参数的值. 这种需要自己设定,而不是由机器找出来的参数称为超参数(hyperparameter).

Q: 为什么损失可以是负的?

A: 根据刚才损失的定义,损失是估测值和真实值的差的绝对值,不可能是负的.但如何定义损失函数是我们自己决定的,比如设置一个损失函数为差的绝对值再减100,它就可以为负了.损失曲线并不反映真实的损失,也不是真实任务的误差表面.因此,损失曲线可以是任何形状.

往右移一步,新的位置为,这一步的步伐是乘上微分的结果,即

  (1.8)

接下来反复执行刚才的操作,计算一下的微分结果,再决定要把移动多少,得到,继续执行同样的操作,不断地移动的位置,最后我们会停下来.这往往对应两种情况.

第一种情况是在一开始就设定,在调整参数的时候,微分最多计算几次,如100万次,参数更新100万次后,就不再更新了,我们就会停下来. 更新次数也是一个超参数.

另一种情况是在不断调整参数的过程中,我们遇到了微分的值是0的情况,此时哪怕继续迭代,参数的位置也不再更新,我们因此而停下来.

梯度下降有一个很大的问题,就是有可能既没有找到真正最好的解,也没有找到可以让损失最小的.在图1.4 所示的例子中,把设定在最右侧红点附近可以让损失最小.但如果在梯度下降过程中,是随机初始的位置,则也很有可能走到时,训练就停住了,我们无法再移动的位置.右侧红点这个位置是真的可以让损失最小的地方,称为全局最小值(globalminimum);而这个地方称为局部最小值(local minimum),其左右两边都比这个地方的损失还要高一点,但它不是整个误差表面上的最低点.所以我们常常可能会听到有人讲梯度下降法不是什么好方法,无法真正找到全局最小值.

图1.4 局部最小值

在有两个参数的情况下使用梯度下降法,跟只有一个参数的情景没有什么不同.

假设有两个参数,它们的随机初始值分别为 . 在的位置,分别计算的微分以及的微分:

  (1.9)

计算完毕后,更新. 把减掉学习率和微分结果的积,得到;把减掉学习率和微分结果的积,得到.

  (1.10)

在深度学习框架(如 PyTorch)中,微分都是由程序自动计算的.程序会不断地更新,试图找到一对最好的. 可以将这个计算过程绘制成一系列点,如图1.5 所示,随便选一个初始值,计算一下,就可以决定更新的方向. 这是一个向量,见图1.5 中红色的箭头.沿箭头方向不断移动,应该就可以找出一组不错的.实际上,在真正用梯度下降进行一番计算以后,有.计算损失,结果是480. 也就是说,在2017年~ 2020年的数据上,如果使用这个函数,为代入0.97,为代入100,则平均误差是480.

图1.5 梯度下降优化的过程

1.2 线性模型

我们刚才找出来的对应的误差是480. 这是由2017年~ 2020年的数据计算出的结果. 现在,不妨用这对去预测下2021年初每日的观看次数. 我们预测2021年1月1日~2021年2月14日间的每日观看次数,计算出新的损失. 在2021年没有看过的数据上,损失用来表示,值是580. 将预测结果绘制出来,如图1.6 所示,横轴代表距离2021年1月1日的天数,0代表2021年1月1日,图中最右边的点代表2021年2月14日;纵轴代表观看次数. 红色线是真实的观看次数,蓝色线是预测的观看次数. 可以看到,蓝色线几乎就是红色线往右平移一天而已,这很合理,因为目前的模型正是用某天观看次数乘以0.97,再加上100,来计算次日的观看次数.

图1.6 预估曲线图

这个真实的数据中有一个很神奇的现象:它是周期性的,每 7 天就会有两天(周五和周六)的观看次数特别少. 目前的模型只能向前看一天.一个模型如果能参考前 7 天的数据,也许能预测得更准,所以可以修改一下模型. 通常,一个模型的修改方向,往往来自我们对这个问题的理解,即领域知识.

一开始,由于对问题完全不理解,我们的模型是

  (1.11)

这个只考虑1天的模型不怎么好.接下来,我们观测了真实的数据,得到一个结论:每 7 天是一个循环.所以要把前 7 天的观看次数都列入考虑. 现在,模型变成

  (1.12)

其中, 代表前7天中第天的观看次数,它们分别乘以不同的权重,加起来,再加上偏置,就可以得到预测的结果.该模型在训练数据(即2017年~ 2020年的数据)上的损失是380,而只考虑1天的模型在训练数据上的损失是480; 对于2021年1月1日~ 2021年2月14日的数据(以下简称2021年的数据)上,它的损失是490. 只考虑1天的模型的损失是580.

这个新模型中的最优值如表1.1所示.

表1.1 的最优值

50

0.79

-0.31

0.12

-0.01

-0.10

0.30

0.18

模型的逻辑是:7天前的数据跟要预测的数值关系很大,所以是0.79,而其他几天则没有那么重要.

其实,可以考虑更多天的影响,比如28天,即

  (1.13)

这个模型在训练数据上的损失是330,在2021年1月1日~ 2021年2月14日数据上的损失是460.如果考虑56天,即

  (1.14)

则训练数据上的损失是320,2021年1月1日~ 2021年2月14日数据上的损失还是460.

可以发现,虽然考虑了更多天,但没有办法再降低损失. 看来考虑天数这件事,也许已经到了一个极限.把输入的特征乘上一个权重,再加上一个偏置,得到预测的结果,这样的模型称为线性模型(linear model).

1.2.1 分段线性曲线

线性模型也许过于简单, 之间可能存在比较复杂的关系,如图1.7 所示.对于的线性模型, 的关系就是一条斜率为正的直线,随着 越来越大, 也应该越来越大.设定不同的 可以改变这条直线的斜率,设定不同的 则可以改变这条直线和 轴的交点.但无论如何改变 ,它永远都是一条直线,永远都是 越大, 就越大:某一天的观看次数越多,次日的观看次数就越多.但在现实中,也许当 大于某个数值的时候,次日的观看次数反而会变少. 之间可能存在一种比较复杂的、像红色线一样的关系.但不管如何设置 ,我们永远无法用简单的线性模型构造红色线.显然,线性模型有很大的限制,这种来自模型的限制称为模型的偏差,无法模拟真实情况.

图1.7 线性模型的局限性

所以,我们需要写一个更复杂、更有灵活性、有更多未知参数的函数. 图1.8 中,红色线可以看作一个常数项 再加上一些 hard sigmoid 函数(hard sigmoid 函数的特性是当输入的值介于两个阈值间的时候,图像呈现出一个斜坡,其余位置都是水平的).常数项被设成红色线和轴的交点一样大.第1个蓝色函数斜坡的起点,设在红色函数的起始地方. 第2个斜坡的终点设在第一个转角处,第1个蓝色函数的斜坡和红色函数的第1段斜坡斜率相同,这时候求+❶, 就可以得到红色线左侧的线段.接下来,叠加第2个蓝色函数,所以第2个蓝色函数的斜坡就在红色函数的第1个转折点和第2个转折点之间,第2个蓝色函数的斜坡和红色函数的第2段斜坡斜率相同. 这时候求+❶+❷,就可以得到红色函数左侧和中间的线段.对于第2个转折点之后的部分,再叠加第3个蓝色函数,第3个蓝色函数的斜坡的起点设在红色函数的第2个转折点,蓝色函数的斜坡和红色函数的第3段斜坡斜率相同. 最后,求 +❶+❷+❸,就得到了完整的红色线.

图1.8 构建红色线

所以红色线[即分段线性曲线(piecewise linear curve)]可以看作一个常数和一些蓝色函数的叠加.分段线性曲线越复杂,转折的点越多,所需的蓝色函数就越多.

也许要考虑的 的关系不是分段线性曲线 ,而是图1.9 所示的曲线. 可以在这样的曲线上先取一些点,再把这些点连起来,变成一条分段线性曲线.而这条分段线性曲线跟原来的曲线非常接近,如果点取得够多或位置适当,分段线性曲线就可以逼近连续曲线,甚至可以逼近有角度和弧度的连续曲线. 我们可以用分段线性曲线来逼近任何连续曲线,只要有足够的蓝色函数.

图1.9 分段线性曲线可以逼近任何连续曲线

的关系非常复杂也没关系,可以想办法写一个带有未知数的函数.直接写 hard sigmoid 函数不是很容易,但可以用 sigmoid 函数来逼近 hard sigmoid 函数,如图1.10 所示.sigmoid函数的表达式为

其中,输入是 ,输出是 为常数.

图1.10 使用 sigmoid 函数逼近 hard sigmoid 函数

的值趋近于正无穷的时候,这一项就会几乎消失,就会收敛于常数 ;当 的值趋近于负无穷的时候,分母就会非常大, 就会收敛于 0.

所以可以用这样的一个函数逼近蓝色函数.为了简洁,蓝色函数的表达式记为

  (1.15)

其中

  (1.16)

调整式(1.15)中的 , 就可以构造各种不同形状的 sigmoid函数,从而用各种不同形状的 sigmoid函数逼近 hard sigmoid 函数.如图1.11 所示,如果调整 ,就会改变斜坡的坡度;如果调整,就可以左右移动sigmoid函数曲线;如果调整 ,就可以改变曲线的高度.所以,只要叠加拥有不同的 、 不同的 和不同的 的sigmoid函数,就可以逼近各种不同的分段线性函数(如图1.12 所示):

  (1.17)

图1.11 调整参数,构造不同的 sigmoid 函数

图1.12 使用 hard sigmoid 函数来合成红色线

此外,我们可以不只用一个特征 ,而是用多个特征代入不同的 ,构建出各种不同的sigmoid函数,从而得到更有灵活性(flexibility)的分段线性函数,如图1.13 所示. 可以用 来代表特征的编号. 如果要考虑 28 天的数据, 就可以取 1 ~ 28.

图1.13 构建更有灵活性的函数

举个只考虑3个特征(即只考虑前3天~前1天)的例子. 此时 可以取 1、2、3,每一个 就代表一个蓝色函数. 每一个蓝色函数都用一个 sigmoid函数来近似,一共需要3个 sigmoid函数:

  (1.18)

代表在第 个 sigmoid 函数中乘给第 个特征的权重.设图1.13 的蓝色虚线框中有

  (1.19)

我们可以用矩阵和向量相乘的方法,得到如下比较简洁的写法.

  (1.20)

也可以改成线性代数比较常用的表示方式,如下所示.

  (1.21)

对应的是 .有了, 分别通过 sigmoid函数得到 ,即

  (1.22)

因此,如图1.14 所示,蓝色虚线框里面做的事情,就是从 得到 .

图1.14 比较有灵活性函数的计算过程

上面这个比较有灵活性的函数可以用线性代数来表示,即

  (1.23)

接下来,如图1.15 所示, 是特征,绿色的是向量,灰色的是数值. 是未知参数.把矩阵展平,与其他项“拼合”,就可以得到一个很长的向量. 把 的每一行或每一列拿出来,拿行或拿列都可以. 先把 的每一列或每一行“拼”成一个长向量,再把 “拼”进来,这个长向量可以直接用 来表示. 我们将所有未知参数一律统称 .

图1.15 将未知参数“拼”成一个向量

Q: 优化是找一个可以让损失最小的参数,是否可以穷举所有可能的未知参数的值?

A:在只有 两个参数的前提下,可以穷举所有可能的 的值. 所以在参数很少的情况下,甚至可能不用梯度下降,也不需要优化技巧. 但是当参数非常多的时候,就不能使用穷举的方法,而应使用梯度下降的方法找出可以让损失最小的参数.

Q:刚才的例子里面有 3 个 sigmoid函数,为什么是 3 个,能不能是 4 个或更多个?

A:sigmoid 函数的数量由我们自己决定,sigmoid 函数的数量越多,可以产生的分段线性函数就越复杂.sigmoid 函数的数量也是一个超参数.

接下来定义损失. 此前的损失函数记作 ,现在未知参数太多了,所以直接用 来统设所有的参数,损失函数记作 . 损失函数能够判断 的好坏,计算方法跟只有两个参数的情况是一样的:先给定 的值,即某一组 的值,再把特征 加进去,得到估测出来的 ,最后计算一下跟真实标签之间的误差. 把所有的误差通通加起来,就得到了损失.

下一步就是优化,即优化

  (1.24)

要找到一组 , 让损失越小越好,可以让损失最小的一组 称为 .一开始,要随机选一个初始的数值 . 接下来计算每一个未知参数对 的微分,得到向量

  (1.25)

  (1.26)

假设有 1000 个参数,向量的长度就是 1000,这个向量也称为梯度向量. 代表梯度; 是指计算梯度的位置,也就是 等于 的地方.计算出以后,接下来更新参数. 代表起始值,它是一个随机选的起始值,代表 更新过一次的结果. 用 减掉微分结果和 的积,得到,以此类推,就可以把 1000 个参数都更新了(见图1.16):

  (1.27)

  (1.28)

图1.16 使用梯度下降更新参数

参数有 1000 个,就是 1000 个数值, 是1000 维的向量, 也是 1000 维的向量.整个操作就是这样,由 开始计算梯度,根据梯度把 更新成 ;再算一次梯度,再根据梯度把 更新成 ;以此类推,直到不想做,或者梯度为零,导致无法再更新参数为止. 不过在实践中,几乎不太可能梯度为零,通常停下来就是因为我们不想做了.

实现上,有个细节上的区别,如图1.17 所示,实际使用梯度下降时,会把 笔数据随机分成一个个的批量(batch),每个批量里面有 笔数据.本来是把所有的数据拿出来计算损失,现在只拿一个批量里面的数据出来计算损失,记为 .假设 够大,也许 会很接近.所以在实现上,每次会先选一个批量,用该批量来算 ,根据 来算梯度,再用梯度来更新参数;接下来再选下一个批量,算出 ,根据 算出梯度,再更新参数;最后再取下一个批量,算出 ,根据 算出梯度,再用 算出来的梯度更新参数.

图1.17 分批量进行梯度下降

把所有的批量都看过一遍的过程称为一个回合(epoch),每更新一次参数称为一次更新. 更新和回合是两个不同的概念.

举个例子,假设有 10 000 笔数据,即 等于 10 000;批量大小(batch size)设为 10,即 等于10.10 000 个样本(example)形成了 1000 个批量,所以在一个回合里面更新了参数 1000 次,所以一个回合不只更新参数一次.

再举个例子,假设有 1000 个数据,批量大小设为 100,批量大小和sigmoid 函数的个数都是超参数.1000 个 样本,批量大小 设为 100,1个回合总共更新10次参数.一个回合的训练其实不知道更新了几次参数,有可能 1000 次,也有可能 10 次,取决于批量有多大.

1.2.2 模型变形

其实还可以对模型做更多的变形,不一定要把 hard sigmoid 函数换成 soft sigmoid函数. hard sigmoid 函数可以看作两个ReLU(Rectified Linear Unit,修正线性单元)的叠加,ReLU先是一条水平的线,到了某个地方经过一个转折点,变成一个斜坡,对应的公式为

  (1.29)

旨在看 0 和 哪个比较大,比较大的值会被当作输出:如果 ,输出是0;如果 ,输出是 . 如图1.18 所示,通过 可以挪动ReLU的位置和斜率. 把两个 ReLU 叠起来,就可以变成 hard sigmoid函数. 想要用 ReLU,就把前文用到 sigmoid 函数的地方换成.

图1.18 ReLU

如图1.19 所示,两个 ReLU才能够合成一个 hard sigmoid函数.要合成 个 hard sigmoid函数,需要 个 sigmoid函数. 如果要用 ReLU 做到一样的事情,则需要 个 ReLU,因为两个 ReLU 合起来才是一个 hard sigmoid函数.表示一个 hard sigmoid 函数不是只有一种做法. 在机器学习里面,sigmoid 函数或 ReLU 称为激活函数(activation function).

图1.19 激活函数

当然还有其他常见的激活函数,但 sigmoid 函数和 ReLU 是最为常见的激活函数. 接下来的实验都选择用了 ReLU,显然 ReLU 比较好. 对于使用前56天数据的情况,实验结果如图1.20 所示.

图1.20 激活函数实验结果

连续使用 10个ReLU作为模型,跟使用线性模型的结果差不多.但连续使用 100 个 ReLU作为模型,结果就有显著差别了. 100 个 ReLU 在训练数据上的损失就可以从 320 降到 280,在测试数据上的损失也低了一些.接下来使用 1000 个 ReLU 作为模型,在训练数据上 损失 更低了一些,但是在模型没看过的数据上,损失没有变化.

接下来可以继续改进模型,如图1.21 所示,从 变成 ,就是把 乘上 再加 ,最后通过 sigmoid函数(不一定要通过 sigmoid函数,通过 ReLU 也可以得到 ). 可以增加网络的层数,将同样的事情再反复多做几次:把 做这一连串的运算产生 ,接下来把 做这一连串的运算产生 ,等等.反复的次数是另一个超参数.注意, 不是同一组参数,这里增加了更多的未知参数.

图1.21 改进模型

每多做一次上述的事情,我们就添加了 100 个 ReLU. 依然考虑前 56 天的数据,实验结果如图1.22 所示,对于2017年~ 2020年的数据,如果做两次(2层),损失降低很多,从280 降到 180.如果做3次(3层),损失从 180 降到 140. 而在2021年的数据上,通过3次ReLU,损失从 430 降到了 380.

图1.22 使用 ReLU 的实验结果

通过3次 ReLU 的实验结果如图1.23 所示,其中红色线是真实数据,蓝色线是预测出来的数据. 看红色线,每隔一段时间,就会有低点,在低点的地方,机器的预测还是很准确的.机器高估了真实的观看次数,尤其是红圈标注的这一天. 这一天有一个很明显的低谷,但是机器没有预测到这一天有明显的低谷,它晚一天才预测出低谷.

图1.23 使用3次 ReLU 的实验结果

如图1.24 所示,sigmoid 函数或 ReLU 称为神经元(neuron),神经网络(neural network)就是由神经元组成的.这些术语来自真实的人脑,人脑中有很多真实的神经元,很多神经元组成神经网络.图1.24 中的每一列神经元称为神经网络的一层,又称为隐藏层(hidden layer),隐藏层多的神经网络就“深”,称为深度神经网络.

图1.24 神经网络的结构

神经网络正向越来越深的方向发展,2012 年的 AlexNet有 8 层,在图像识别上的错误率为 16.4%. 两年之后的 VGG 有19层,错误率降至 7.3 %.后来的 GoogleNet 有 22 层,错误率降至 6.7%. 残差网络(Residual Network,ResNet)有 152 层,错误率降至3.57%.

刚才只做到 3 层,我们应该做得更深,现在的神经网络都是几百层的,深度神经网络还要更深.但 4 层的网络在训练数据上的损失 是 100,在2021年的数据上的损失是440. 在训练数据上,3 层的网络表现比较差;但是在2021年的数据上,则是4 层的网络表现比较差,如图1.25 所示.模型在训练数据和测试数据上的结果不一致,这种情况称为过拟合(overfitting).

图1.25 模型有过拟合问题

到目前为止,我们还没有真正发挥这个模型的力量,2021年 2 月 14日之前的数据是已知的.要预测未知的数据,选 3 层的 网络还是 4 层的 网络 呢?假设今天是 2 月 26 日,今天的观看次数是未知的. 如果用已经训练出来的神经网络预测今天的观看次数,就要选 3 层的网络,虽然 4 层的网络在训练数据上的结果比较好,但模型对于它没看过的数据的预测结果更重要.

深度神经网络的训练会用到残差网络(Residual Network,ResNet),这是一种比较有效率的梯度计算方法.

1.2.3 机器学习框架

训练数据和测试数据如式(1.30) 所示. 对于模型来说,测试数据只有而没有,我们正是使用模型在测试数据上的预测结果来评估模型的性能.

  (1.30)

训练数据用来训练模型,训练过程如下.

(1) 写出一个有未知数的函数,代表一个模型里面所有的未知参数.这个函数记作,意思是函数名叫,输入的特征为 .

(2) 定义损失,损失是一个函数,其输入就是一组参数,旨在判断这组参数的好坏.

(3) 解一个优化的问题,找一个,让损失越小越好. 能让损失最小的记为,即

  (1.31)

有了以后,就可以把它拿来用在测试数据上,也就是把代入这些未知的参数. 本来里面就有一些未知的参数,现在用替代 ,输入测试数据,将输出的结果保存起来,就可以用来评估模型的性能.

相关图书

深度学习高手笔记 卷2:经典应用
深度学习高手笔记 卷2:经典应用
破解深度学习(核心篇):模型算法与实现
破解深度学习(核心篇):模型算法与实现
深度学习的数学——使用Python语言
深度学习的数学——使用Python语言
ChatGPT原理与应用开发
ChatGPT原理与应用开发
人工智能和深度学习导论
人工智能和深度学习导论
动手学深度学习(PyTorch版)
动手学深度学习(PyTorch版)

相关文章

相关课程