🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
深度学习适合所有人
很多人认为你需要各种难以找到的东西才能通过深度学习获得好的结果,但正如你将在本书中看到的那样,这些人是错误的。 表 1-1列出了世界级深度学习绝对不需要的一些东西。
传说中(不需要) | 真实 |
---|---|
很多数学 | 高中数学就够了。 |
大量数据 | 我们已经看到了少于 50 项数据的破纪录结果。 |
很多昂贵的电脑 | 您可以免费获得最先进的工作所需的东西。 |
深度学习是一种提取和转换数据的计算机技术——用例从人类语音识别到动物图像分类——通过使用多层神经网络。这些层中的每一层都从先前的层中获取输入并逐步细化它们。这些层通过算法进行训练,以最大限度地减少错误并提高其准确性。通过这种方式,网络学习执行指定的任务。我们将在下一节详细讨论训练算法。
深度学习具有强大的功能、灵活性和简单性。这就是为什么我们认为它应该应用于许多学科。这些包括社会和物理科学、艺术、医学、金融、科学研究等等。举一个个人的例子,尽管杰里米没有医学背景,但他开始Enlitic,一家使用深度学习算法诊断疾病的公司。在公司成立后的几个月内,宣布其算法可以 比放射科医生更准确地识别恶性肿瘤。
以下是深度学习或大量使用深度学习的方法现在是世界上最好的不同领域的数千个任务的列表:
自然语言处理 (NLP)
回答问题;语音识别; 总结文件;分类文件;在文件中查找姓名、日期等;搜索提及概念的文章
计算机视觉
卫星和无人机图像解释(例如,用于抗灾)、人脸识别、图像 字幕,阅读交通标志,在自动驾驶汽车中定位行人和车辆
药物
在放射学图像中发现异常,包括 CT、MRI 和 X 射线图像;计数病理切片中的特征;测量超声波的特征;诊断糖尿病视网膜病变
生物学
折叠蛋白;分类蛋白质;许多基因组学任务,例如肿瘤正常测序和临床上可行的基因突变分类;细胞分类;分析蛋白质/蛋白质相互作用
图像生成
着色图像,提高图像分辨率,去除图像中的噪声,将图像转换为著名艺术家风格的艺术
推荐系统
网页搜索、产品推荐、首页布局
玩游戏
国际象棋、围棋、大多数 Atari 视频游戏和许多实时战略游戏
机器人技术
处理难以定位(例如透明、有光泽、缺乏纹理)或难以拾取的物体
其他应用
财务和后勤预测、文本转语音等等……
值得注意的是,深度学习有如此多样的应用,但几乎所有的深度学习都基于一种创新的模型:神经网络。
但事实上,神经网络并不是全新的。为了对该领域有更广阔的视野,值得从一点历史开始。
神经网络:简史
1943 年,神经生理学家 Warren McCulloch 和逻辑学家 Walter Pitts,联手开发了一个人工神经元的数学模型。在他们的论文“神经活动中内在思想的逻辑演算”中,他们宣布了以下内容:
由于神经活动的“全有或全无”特性,神经事件及其之间的关系可以用命题逻辑来处理。发现每个网络的行为都可以用这些术语来描述。
McCulloch 和 Pitts 意识到可以使用简单的加法和阈值化来表示真实神经元的简化模型, 如图 1-1所示。皮茨是自学成才的,到 12 岁时,他收到了剑桥大学的录取通知书,师从伟大的伯特兰·罗素。他没有接受这个邀请,实际上他一生都没有接受任何高级学位或权威职位的提议。他的大部分著名作品都是在他无家可归的时候完成的。尽管他缺乏官方认可的职位并且日益受到社会孤立,但他与 McCulloch 的合作颇具影响力,并被一位心理学家弗兰克·罗森布拉特。 图 1-1。自然和人工神经元
罗森布拉特进一步开发了人工神经元,使其具有学习能力。更重要的是,他致力于制造第一个使用这些原理的设备,Mark I 感知器。在“智能自动机的设计”中, 罗森布拉特对这项工作写道:“我们现在将见证这样一台机器的诞生——一台无需任何人工训练或控制就能感知、识别和识别周围环境的机器。” 感知器已构建并能够成功识别简单的形状。
麻省理工学院教授马文·明斯基(在同一所高中比罗森布拉特落后一个年级!),与 Seymour Papert 一起,写了一本书叫 感知器(麻省理工学院出版社)关于罗森布拉特的发明。他们表明,这些设备的单层无法学习一些简单但关键的数学函数(例如 XOR)。在同一本书中,他们还表明,使用多层设备可以解决这些限制。不幸的是,只有这些见解中的第一个被广泛认可。结果,在接下来的二十年里,全球学术界几乎完全放弃了神经网络。
在过去 50 年中,神经网络中最关键的工作可能是多卷并行分布式处理(PDP)David Rumelhart、James McClelland 和 PDP 研究小组,1986 年由麻省理工学院出版社出版。第 1 章提出了与 Rosenblatt 相似的希望:
人们比今天的计算机更聪明,因为大脑采用了一种基本的计算架构,该架构更适合处理人们非常擅长的自然信息处理任务的核心方面……我们将介绍一个用于建模认知过程的计算框架, …比其他框架更接近计算风格,因为它可能由大脑完成。
PDP 在这里使用的前提是传统计算机程序的工作方式与大脑非常不同,这可能就是为什么计算机程序(在那时)在做大脑认为容易的事情(例如识别图片中的物体)方面做得如此糟糕的原因。作者声称 PDP 方法“比其他框架更接近”大脑的工作方式,因此它可能能够更好地处理这些类型的任务。
事实上,PDP 中的方法与当今神经网络中使用的方法非常相似。该书将并行分布式处理定义为需要以下内容:
-
一组处理单元
-
激活状态
-
每个单元的输出功能
-
单元之间的连接模式
-
通过连接网络传播活动模式的传播规则
-
一种 激活规则,用于将冲击一个单元的输入与该单元的当前状态相结合,以产生该单元的输出
-
通过经验修改连接模式的学习 规则
-
系统必须运行的环境
我们将在本书中看到现代神经网络可以处理这些 要求中的每一个。
在 1980 年代,大多数模型都是用第二层神经元构建的,从而避免了 Minsky 和 Papert 发现的问题(这是他们的“单元之间的连接模式”,使用前面的框架)。事实上,神经网络在 80 年代和 90 年代被广泛用于实际项目。然而,对理论问题的误解再次阻碍了该领域的发展。理论上,只增加一层额外的神经元就足以让任何数学函数用这些神经网络来近似,但在实践中,这样的网络通常太大太慢而无法使用。
尽管 30 年前研究人员表明,要获得实用的良好性能,您需要使用更多层的神经元,但直到最近十年,这一原理才得到更广泛的认可和应用。由于使用了更多的层,再加上计算机硬件的改进、数据可用性的增加以及允许神经网络更快训练的算法调整,神经网络现在终于发挥了它们的潜力。更容易。我们现在拥有了 Rosenblatt 承诺的东西:“一台无需任何人工训练或控制即可感知、识别和识别周围环境的机器。”
这就是您将在本书中学习如何构建的内容。但首先,由于我们将要花很多时间在一起,让我们互相了解一下……
如何学习深度学习
哈佛大学教授大卫·珀金斯(David Perkins)撰写了《让学习整体》(Jossey-Bass)一书,他对教学有很多话要说。基本思想是教整场比赛。这意味着如果你在教棒球,你首先要带人们去看棒球比赛或让他们玩。你不会教他们如何缠绕麻线从头开始制作棒球、抛物线的物理学或球在球棒上的摩擦系数。
保罗洛克哈特,哥伦比亚数学博士,前布朗教授和 K-12 数学老师,在有影响力的文章“数学家的悲叹” 是一个噩梦般的世界,音乐和艺术的教学方式与数学的教学方式相同。在孩子们花了十多年时间掌握乐谱和理论之前,不允许孩子听或演奏音乐,通过课程将活页乐谱转换成不同的调。在艺术课上,学生学习颜色和涂抹器,但直到大学才允许实际绘画。听起来很荒谬?这就是数学的教学方式——我们要求学生花费数年时间死记硬背,学习枯燥的、不连贯的基础知识 ,我们声称这些基础知识将在他们中的大多数人退出这门学科很久之后才会得到回报。
不幸的是,这是许多深度学习教学资源的起点——要求学习者遵循 Hessian 的定义和损失函数的泰勒近似定理,而没有给出实际工作代码的示例。我们不是在敲击微积分。我们热爱微积分,Sylvain 甚至在大学阶段教授过微积分,但我们认为这不是学习深度学习的最佳起点!
在深度学习中,如果您有动力修复模型以使其做得更好,那真的很有帮助。那是你开始学习相关理论的时候。但是你首先需要有模型。我们通过真实的例子教授几乎所有的东西。随着我们构建这些示例,我们会越来越深入,我们将向您展示如何使您的项目越来越好。这意味着您将逐步学习所需的所有理论基础,在上下文中,您将了解它为什么重要以及它是如何工作的。
因此,这是我们对您的承诺。在本书中,我们遵循以下原则:
教学整个游戏
我们将首先向您展示如何使用一个完整的、有效的、可用的、最先进的深度学习网络,使用简单、富有表现力的工具来解决现实世界的问题。然后我们将逐渐深入了解这些工具是如何制造的,以及制造这些工具的工具是如何制造的,等等……
总是通过例子教学
我们将确保您可以直观地理解上下文和目的,而不是从代数符号操作开始。
尽可能简化
我们花了数年时间构建工具和教学方法,使以前复杂的主题变得简单。
消除障碍
到目前为止,深度学习一直是一种独家游戏。我们正在打破它并确保每个人都可以玩。
深度学习最难的部分是手工:你怎么知道你是否有足够的数据,它的格式是否正确,你的模型是否训练正确,如果不是,你应该怎么做?这就是为什么我们相信边做边学。与基本的数据科学技能一样,深度学习只有通过实践经验才能变得更好。试图在理论上花费太多时间可能会适得其反。关键是编写代码并尝试解决问题:理论可以稍后出现,当你有背景和动机时。
有时旅途会很艰难。感觉卡住的时候。不要放弃!倒回这本书,找到最后一点你肯定没有被卡住的地方,然后从那里慢慢阅读,找出第一个不清楚的地方。然后自己尝试一些代码实验,并在谷歌上搜索更多关于你遇到的任何问题的教程——通常你会发现材料的不同角度可能有助于点击。此外,在第一次阅读时不理解所有内容(尤其是代码)是正常的。在继续之前尝试连续理解材料有时会很困难。有时,在您从未来的部分中获得更多背景信息后,事情就会到位,从更大的图景来看。因此,如果您确实卡在某个部分,请尝试继续前进,并记下稍后再返回。
请记住,您不需要任何特定的学术背景即可在深度学习方面取得成功。没有博士学位的人在研究和工业领域取得了许多重要突破,例如论文 “Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks” ——过去十年中最有影响力的论文之一,被引用超过 5000 次 ——亚历克·拉德福 (Alec Radford) 读本科时写的。即使在特斯拉,他们正在努力解决制造自动驾驶汽车的极其艰巨的挑战,首席执行官 埃隆马斯克说:
绝对不需要博士学位。重要的是对人工智能的深刻理解和以实际有用的方式实施神经网络的能力(后一点是真正困难的)。就算高中毕业也没关系。
然而,要取得成功,你需要做的是将你在本书中学到的知识应用到个人项目中,并始终坚持下去。
你的项目和你的心态
无论您是兴奋地从叶子的照片中识别植物是否患病,自动生成针织图案,通过 X 射线诊断 TB,还是确定浣熊何时使用您的猫门,我们都会让您使用深度学习解决您自己的问题(通过其他人的预训练模型)尽快,然后将逐步深入研究更多细节。在下一章的前 30 分钟内,您将学习如何使用深度学习以最先进的准确性解决您自己的问题!(如果你很想马上开始编码,现在可以直接跳过。)有一个有害的神话,你需要拥有与谷歌一样大的计算资源和数据集才能进行深度学习,但事实并非如此。
那么,什么样的任务才能构成好的测试用例呢?你可以训练你的模型来区分毕加索和莫奈的画作,或者挑选出你女儿的照片而不是你儿子的照片。它有助于专注于你的爱好和激情——给自己设置四五个小项目,而不是努力解决一个大问题,当你开始时往往会更好地工作。由于很容易陷入困境,因此过早地过于雄心勃勃往往会适得其反。然后,一旦你掌握了基础知识,就努力完成你真正引以为豪的事情!
软件:PyTorch、fastai 和 Jupyter (以及为什么不重要)
我们已经使用几十个包和许多编程语言完成了数百个机器学习项目。在 fast.ai,我们使用当今使用的大多数主要深度学习和机器学习包编写了课程。PyTorch 于 2017 年问世后,我们花了一千多个小时对其进行测试,然后才决定将其用于未来的课程、软件开发和研究。从那时起,PyTorch 已经成为世界上增长最快的深度学习库,并且已经在顶级会议上用于大多数研究论文。这通常是工业使用的领先指标,因为这些纸张最终被用于商业产品和服务。我们发现 PyTorch 是深度学习最灵活、最具表现力的库。它不会为了简单而牺牲速度,但两者兼而有之。
PyTorch 最适合作为低级基础库,为高级功能提供基本操作。fastai 库是最受欢迎的库,用于在 PyTorch 之上添加这种更高级别的功能。它也特别适合本书的目的,因为它在提供深度分层的软件架构方面是独一无二的(甚至还有 一篇关于这种分层 API的同行评审的学术论文)。在本书中,随着我们对深度学习的基础越来越深入,我们也将越来越深入到 fastai 的各个层面。这本书涵盖fastai 库的第 2 版,这是一个从头开始的重写,提供了许多独特的功能。
但是,您学习什么软件并不重要,因为只需几天时间即可学会从一个库切换到另一个库。真正重要的是正确学习深度学习的基础和技术。我们的重点将是使用尽可能清晰地表达您需要学习的概念的代码。在我们教授高级概念的地方,我们将使用高级 fastai 代码。在我们教授低级概念的地方,我们将使用低级 PyTorch 甚至是纯 Python 代码。
尽管现在看起来新的深度学习库正在快速出现,但您需要为未来几个月和几年内更快的变化速度做好准备。随着越来越多的人进入这个领域,他们会带来更多的技能和想法,并尝试更多的东西。您应该假设您今天学习的任何特定库和软件都将在一两年内过时。想想在 Web 编程领域一直在发生的库和技术堆栈的变化——这是一个比深度 学习更成熟且增长缓慢的领域。我们坚信,学习的重点需要理解底层技术以及如何在实践中应用它们,以及如何在新工具和技术发布时快速建立专业知识。
在本书的最后,您将了解 fastai 中的几乎所有代码(以及 PyTorch 的大部分代码),因为在每一章中,我们将深入挖掘一个层次,以准确地向您展示我们构建和训练时发生了什么我们的模型。这意味着您将了解现代深度学习中使用的最重要的最佳实践——不仅仅是如何使用它们,还有它们是如何真正工作和实施的。如果您想在另一个框架中使用这些方法,那么您将拥有必要的知识。
由于学习深度学习最重要的事情是编写代码和进行实验,因此拥有一个很好的代码实验平台很重要。最流行的编程实验平台称为Jupyter。这就是我们将在本书中使用的内容。我们将向您展示如何使用 Jupyter 来训练和试验模型,并自省数据预处理和模型开发管道的每个阶段。Jupyter 是最流行的 Python 数据科学工具,有充分的理由。它功能强大、灵活且易于使用。我们认为您会喜欢它!
让我们在实践中看到它并训练我们的第一个模型。
您的第一个模型
正如我们之前所说,在解释它们为什么起作用之前,我们将教你如何做事。按照这种自上而下的方法,我们将从实际训练一个图像分类器以几乎 100% 的准确率识别狗和猫。要训练此模型并运行我们的实验,您需要进行一些初始设置。不用担心; 它并不像看起来那么难。
获取 GPU 深度学习服务器
要完成本书中的几乎所有内容,您需要使用配备 NVIDIA GPU的计算机(很遗憾,其他品牌的 GPU 并没有得到主要深度学习库的完全支持)。但是,我们不建议您购买;事实上,即使您已经拥有,我们也不建议您立即使用它!设置一台计算机需要时间和精力,你现在希望所有的精力都集中在深度学习上。因此,我们建议您租用一台已经预装了您需要的一切并准备就绪的计算机。使用它时,成本可能低至每小时 0.25 美元,有些选项甚至是免费的。
行话:图形处理单元 (GPU)
也称为显卡。计算机中的一种特殊处理器,可以同时处理数千个单一任务,特别设计用于在计算机上显示 3D 环境以进行游戏。这些相同的基本任务与神经网络的工作非常相似,因此 GPU 运行神经网络的速度比普通 CPU 快数百倍。所有现代计算机都包含 GPU,但很少有包含深度学习所需的正确类型的 GPU。
随着公司的来来去去和价格的变化,与本书一起使用的 GPU 服务器的最佳选择会随着时间的推移而改变。我们在本书的网站上维护了我们推荐的选项列表,所以现在就去那里并按照说明连接到 GPU 深度学习服务器。不用担心; 在大多数平台上设置只需大约两分钟,许多平台甚至不需要任何付款甚至信用卡即可开始使用。
网站上显示的每个选项都包含一个教程;完成本教程后,您将看到 如图 1-2 所示的屏幕。
图 1-2。Jupyter Notebook 的初始视图
您现在已准备好运行您的第一个 Jupyter 笔记本!
运行你的第一台笔记本
笔记本按章节编号本书中介绍的顺序。因此,您将看到的第一个笔记本是您现在需要使用的笔记本。您将使用此笔记本来训练可以识别狗和猫照片的模型。为此,您将 下载狗和猫照片的数据集,并用它来训练 一个模型。
数据集只是一堆数据——它可以是图像、电子邮件、财务指标、声音或其他任何东西。有许多免费提供的适用于训练模型的数据集。其中许多数据集是由学者创建的,以帮助推进研究,许多数据集可用于竞赛(数据科学家可以参加竞赛,看看谁拥有最准确的模型!),还有一些是其他过程的副产品(例如金融备案)。
完整和剥离的笔记本
笔记本有两个版本。回购的根源包含用于创建您现在正在阅读的书的确切笔记本,以及所有散文和输出。clean文件夹具有相同的标题和代码单元,但已删除所有输出和散文。阅读完本书的一部分后,我们建议您阅读干净的笔记本,合上书本,看看您是否可以在执行之前弄清楚每个单元格将显示什么。还要尝试回忆代码所演示的内容。
要打开一个笔记本,只需单击它。笔记本会打开,它看起来类似于图 1-3(请注意,不同平台的细节可能存在细微差异;您可以忽略这些差异)。
图 1-3。一个 Jupyter 笔记本
Jupyter 笔记本可以处于以下两种模式之一:编辑模式或命令模式。在编辑模式下,在键盘上键入以通常的方式将字母输入单元格。但是,在命令模式下,您不会看到任何闪烁的光标,并且键盘上的每个键都有特殊功能。
在继续之前,请按键盘上的 Escape 键切换到命令模式(如果您已经处于命令模式,这没有任何作用,所以现在按下它以防万一)。要查看所有可用功能的完整列表,请按 H;按 Escape 删除此帮助屏幕。请注意,在命令模式下,与大多数程序不同,命令不需要您按住 Control、Alt 或类似键,您只需按下所需的字母键即可。
可以通过按C来复制一个单元格(需要先选中单元格,用轮廓表示周围; 如果尚未选择,请单击一次)。然后按 V 粘贴它的副本。
单击以“# CLICK ME”行开头的单元格以将其选中。其中的第一个字符 line 表示后面是 Python 中的注释,因此在执行单元格时将被忽略。信不信由你,细胞的其余部分是一个完整的系统,用于创建和训练用于识别猫与狗的最先进模型。所以,让我们现在训练它!为此,只需按键盘上的 Shift-Enter,或单击工具栏上的“播放”按钮。然后等待几分钟,同时发生以下事情:
-
一个数据集称为 Oxford-IIIT Pet Dataset包含来自 37 个品种的 7,349 张猫狗图像,将从 fast.ai 数据集集合下载到您正在使用的 GPU 服务器,然后将被提取。
前两个步骤只需要在您的 GPU 服务器上运行一次。如果再次运行该单元,它将使用已经下载的数据集和模型,而不是再次下载它们。我们来看看单元格的内容及结果(表1-2):
# CLICK ME
from fastai.vision.all import *
path = untar_data(URLs.PETS)/'images'
def is_cat(x): return x[0].isupper()
dls = ImageDataLoaders.from_name_func(
path, get_image_files(path), valid_pct=0.2, seed=42,
label_func=is_cat, item_tfms=Resize(224))
learn = cnn_learner(dls, resnet34, metrics=error_rate)
learn.fine_tune(1)
时代 | train_loss | 有效损失 | 错误率 | 时间 |
---|---|---|---|---|
0 | 0.169390 | 0.021388 | 0.005413 | 00:14 |
时代 | train_loss | 有效损失 | 错误率 | 时间 |
---|---|---|---|---|
0 | 0.058748 | 0.009240 | 0.002706 | 00:19 |
您可能不会看到此处显示的完全相同的结果。训练模型中涉及许多小的随机变化来源。然而,在这个例子中,我们通常看到的错误率远低于 0.02。
训练时间
根据您的网络速度,下载预训练模型和数据集可能需要几分钟时间。跑步fine_tune
可能需要一分钟左右。本书中的模型通常需要几分钟的时间来训练,你自己的模型也是如此,所以最好想出好的技术来充分利用这段时间。例如,在您的模型训练时继续阅读下一部分,或者打开另一个笔记本并将其用于一些编码实验。
这本书是用 JUPYTER NOTEBOOKS 写的
我们使用 Jupyter 笔记本编写了本书,因此对于本书中的几乎所有图表、表格和计算,我们将向您展示自己复制它所需的确切代码。这就是为什么在本书中,你经常会看到一些代码紧跟在表格、图片或只是一些文本之后。如果您访问 本书的网站,您会找到所有代码,您可以尝试自己运行和修改每个示例。
您刚刚看到了输出表格的单元格在书中的外观。下面是一个输出文本的单元格示例:
1+1
2
Jupyter 将始终打印或显示最后一行的结果(如果有的话)。例如,这是一个输出图像的单元格示例:
img = PILImage.create(image_cat())
img.to_thumb(192)
那么,我们怎么知道这个模型好不好呢?在表格的最后一列,您可以看到错误率,即被错误识别的图像的比例。错误率作为我们的指标——我们对模型质量的衡量,选择直观和易于理解。如您所见,该模型几乎是完美的,尽管训练时间只有几秒钟(不包括数据集的一次性下载和预训练模型)。事实上,你已经达到的准确度比任何人在 10 年前达到的要好得多!
最后,让我们检查一下这个模型是否真的有效。去拍一张狗或猫的照片;如果您手边没有,只需搜索 Google 图片并下载您在那里找到的图片。现在执行已uploader
定义的单元格。它将输出一个您可以单击的按钮,因此您可以选择要分类的图像:
uploader = widgets.FileUpload()
uploader
现在您可以将上传的文件传递给模型。确保它是单只狗或猫的清晰照片,而不是线条画、卡通或类似内容。笔记本会告诉你它认为自己是狗还是猫,以及它的自信程度。希望您会发现您的模型做得很好:
img = PILImage.create(uploader.data[0])
is_cat,_,probs = learn.predict(img)
print(f"Is this a cat?: {is_cat}.")
print(f"Probability it's a cat: {probs[1].item():.6f}")
Is this a cat?: True. Probability it's a cat: 0.999986
祝贺你的第一个分类器!
但是,这是什么意思?你实际上做了什么?为了解释这一点,让我们再次缩小以了解全局。
什么是机器学习?
您的分类器是一个深度学习模型。如前所述,深度学习模型使用神经网络,它最初可以追溯到 1950 年代,并且由于最近的进步而在最近变得强大。
另一个关键的背景是深度学习只是机器学习更一般学科中的一个现代领域。要了解您在训练自己的分类模型时所做的事情的本质,您无需了解深度学习。了解您的模型和训练过程如何成为一般适用于机器学习的概念示例就足够了。
所以在本节中,我们将描述机器学习。我们将探索关键概念,并了解如何将它们追溯到介绍它们的原始文章。
与常规编程一样,机器学习是一种让计算机完成特定任务的方法。但是我们如何使用常规编程来完成我们在上一节中所做的事情:识别照片中的狗和猫?我们必须为计算机写下完成任务所需的确切步骤。
通常,我们在编写程序时很容易写下完成任务的步骤。我们只是考虑如果我们必须手动完成任务会采取的步骤,然后我们将它们转换为代码。例如,我们可以编写一个对列表进行排序的函数。一般来说,我们会编写一个类似于图 1-4的函数(其中输入可能是一个未排序的列表,结果是一个排序的列表)。
图 1-4。一个传统的节目
但是要识别照片中的物体,这有点棘手。当我们识别图片中的物体时,我们会采取哪些 步骤?我们真的不知道,因为这一切都发生在我们的大脑中,而我们没有意识到!
早在 1949 年计算刚开始时,一位名叫 亚瑟·塞缪尔开始研究一种不同的方法来让计算机 完成任务,他称之为机器学习。在他 1962 年的经典文章《人工智能:自动化的前沿》中,他写道:
为此类计算编程计算机充其量是一项艰巨的任务,这主要不是因为计算机本身存在任何固有的复杂性,而是因为需要以最令人恼火的细节详细说明该过程的每一分钟步骤。正如任何程序员都会告诉你的那样,计算机是巨大的白痴,而不是巨大的大脑。
他的基本想法是:而不是告诉计算机确切的步骤 需要解决问题,向它展示要解决的问题的示例,并让它自己弄清楚如何解决它。结果证明这是非常有效的:到 1961 年,他的跳棋程序已经学到了很多东西,以至于它击败了康涅狄格州冠军!他是这样描述他的想法的(来自前面提到的同一篇文章):
假设我们安排了一些自动方法来测试任何当前权重分配在实际性能方面的有效性,并提供一种改变权重分配的机制以最大化性能。我们不需要深入了解这样一个程序的细节,就可以看到它可以完全自动化,并看到这样编程的机器会从它的经验中“学习”。
在这个简短的声明中嵌入了许多强大的概念:
-
“权重分配”的想法
-
每个重量分配都有一些“实际性能”的事实
-
要求有一种“自动方法”来测试该性能
-
需要通过改变权重分配来提高性能的“机制”(即另一个自动过程)
让我们一一了解这些概念,以了解它们在实践中是如何结合在一起的。首先,我们需要了解 Samuel 所说的权重分配是什么意思。
权重只是变量,权重分配是这些变量的特定值选择。程序的输入是它为产生结果而处理的值——例如,将图像像素作为输入,并返回分类“狗”作为结果。程序的权重分配是定义程序如何运行的其他值。
因为它们会影响程序,它们在某种意义上是另一种输入。我们将更新图 1-4中的基本图片 并将其替换为图 1-5以考虑到这一点。
图 1-5。使用权重分配的程序
我们将盒子的名称从program更改为model。这是为了遵循现代术语并反映该模型是一种特殊的程序:它可以做很多不同的事情,具体取决于重量。它可以以许多不同的方式实现。例如,在 Samuel 的跳棋程序中,不同的权重值会导致不同的跳棋策略。
(顺便说一下,Samuel 所谓的“权重”现在最常被称为模型参数,以防你遇到 学期。权重一词是为特定类型的模型参数保留的。)
接下来,Samuel 说我们需要一种自动测试有效性的方法 任何当前的权重分配在实际表现方面。就他的跳棋程序而言,模型的“实际表现”将是它的表现如何。您可以通过设置两个模型相互对战并查看哪个模型通常获胜来自动测试两个模型的性能。
最后,他说我们需要一种改变权重分配的机制,以最大限度地提高性能。例如,我们可以查看获胜模型和失败模型之间的权重差异,并在获胜方向上进一步调整权重。
我们现在可以明白为什么他说这样的程序可以完全自动化,而且……这样编程的机器会从它的经验中“学习”。当权重的调整也是自动的时,学习将变得完全自动化——我们不是通过手动调整权重来改进模型,而是依靠一种基于性能进行调整的自动化机制。
图 1-6展示了 Samuel 训练机器学习模型的想法的全貌。
图 1-6。训练机器学习模型
注意模型结果之间的区别(例如,跳棋游戏中的移动)以及它的表现(例如,它是否赢得了比赛,或者它获胜的速度)。
还要注意,一旦模型被训练——也就是说,一旦我们选择了我们最终的、最好的、最喜欢的权重分配——那么我们可以将权重视为模型的一部分,因为我们不再改变它们。
因此,实际使用经过训练的模型如图 1-7 所示。
图 1-7。使用经过训练的模型作为程序
这看起来与 图 1-4中的原始图相同,只是将单词program替换为 model。这是一个重要的见解:经过训练的模型可以像普通计算机程序一样对待。
什么是神经网络?
不难想象该模型对于跳棋程序会是什么样子。可能有一系列跳棋策略 编码,以及某种搜索机制,然后权重可能会改变策略的选择方式,搜索过程中关注的板的哪些部分等等。但是,对于图像识别程序、理解文本或我们可能想象的许多其他有趣问题,模型看起来是什么样子的,这一点并不明显。
我们想要的是某种非常灵活的函数,它可以用来解决任何给定的问题,只需改变它的权重。 令人惊讶的是,这个功能确实存在!这是我们已经讨论过的神经网络。也就是说,如果您将神经网络视为一个数学函数,那么它会变成一个非常灵活的函数,具体取决于其权重。一种称为通用逼近定理的数学证明表明这个函数理论上可以解决任何问题,达到任何精度水平。神经网络如此灵活的事实意味着,在实践中,它们通常是一种合适的模型,您可以将精力集中在训练它们的过程上——即找到好的权重分配。
但是那个过程呢?可以想象,您可能需要找到一种新的“机制”来自动更新每个问题的权重。这会很费力。我们在这里也想要一种完全通用的方法来更新神经网络的权重,以使其在任何给定的任务中得到改进。方便的是,这也存在!
这称为随机梯度下降(SGD)。我们将在下面详细了解神经网络和 SGD 的工作原理 第 4 章,以及解释通用逼近定理。然而,现在,我们将改为使用塞缪尔自己的话:我们不需要深入了解这样一个程序的细节,看看它是否可以完全自动化,并且看到这样编程的机器会从它的经验中“学习”。
不用担心; SGD 和神经网络在数学上都不是复杂的。两者几乎完全依赖加法和乘法来完成他们的工作(但他们做了很多加法和乘法!)。当学生看到细节时,我们听到的主要反应是:“就是这样吗?”
换句话说,回顾一下,神经网络是一种特殊的机器学习模型,完全符合 Samuel 的原始概念。神经网络很特别,因为它们非常灵活,这意味着它们可以通过找到正确的权重来解决异常广泛的问题。这很强大,因为随机梯度下降为我们提供了一种自动找到这些权重值的方法。
缩小后,现在让我们重新放大并使用 Samuel 的框架重新审视我们的图像分类问题。
我们的输入是图像。我们的权重是 神经网络。我们的模型是一个神经网络。我们的结果是由神经网络计算的值,例如“狗”或“猫”。
下一篇文章呢,一种自动测试任何当前权重分配在实际性能方面的有效性的方法?确定“实际性能”很容易:我们可以简单地将模型的性能定义为其预测正确答案的准确性。
综上所述,假设 SGD 是我们更新权重分配的机制,我们可以看到我们的图像分类器是一个机器学习模型,就像 Samuel 所设想的那样。
一点深度学习术语
Samuel 在 1960 年代工作,从那时起术语发生了变化。以下是我们讨论过的所有部分的现代深度学习术语:
-
模型的结果称为预测。
进行这些更改后,我们在图 1-6中的图表 类似于图 1-8。
图 1-8。详细的训练循环
机器学习固有的局限性
从这张图片中,我们现在可以看到一些关于训练深度学习模型的基本知识:
-
没有数据就无法创建模型。
-
模型可以学习仅对用于训练它的输入数据中看到的模式进行操作。
-
这种学习方法只创建预测,而不是推荐 操作。
-
仅仅有输入数据的例子是不够的;我们也需要该数据的标签(例如,狗和猫的图片不足以训练模型;我们需要为每个人一个标签,说明哪些是狗,哪些是猫)。
一般来说,我们已经看到大多数声称他们没有足够数据的组织实际上意味着他们没有足够的标签数据。如果任何组织有兴趣在实践中使用模型做某事,那么大概他们有一些他们计划运行模型的输入。并且大概他们已经以其他方式这样做了一段时间(例如,手动或使用一些启发式程序),所以他们有来自这些过程的数据!例如,放射学实践几乎肯定会有医学扫描档案(因为他们需要能够检查患者随着时间的推移如何进展),但这些扫描可能没有包含诊断或干预列表的结构化标签(因为放射科医生通常会创建自由文本的自然语言报告,而不是结构化数据)。我们将在本书中大量讨论标记方法,因为它在实践中是一个非常重要的问题。
由于这些机器学习模型只能做出预测 (即尝试复制标签),这可能导致组织目标和模型能力之间存在显着差距。例如,在本书中,您将学习如何创建一个 可以预测用户可能购买哪些产品的推荐系统。这是 常用于电子商务,例如通过显示排名最高的项目来自定义主页上显示的产品。但是这样的模型通常是通过查看用户及其购买历史(输入)以及他们继续购买或查看的内容(标签)来创建的,这意味着该模型可能会告诉您用户已经拥有的产品,或已经知道,而不是他们最有可能感兴趣的新产品。这与当地书商的专家可能会做的事情非常不同,他们会提出问题以了解您的品味,然后告诉您您以前从未听说过的作者或系列。
另一个重要的见解来自考虑模型如何与其环境交互。这可以创建反馈循环,如下所述:
-
根据过去的逮捕地点创建预测性警务模型。在实践中,这实际上并不是预测犯罪,而是预测逮捕,因此部分只是反映了现有警务 过程中的偏见。
-
然后,执法人员可能会使用该模型来决定将他们的警务活动集中在哪里,从而增加在这些地区的逮捕人数。
-
然后将反馈这些额外逮捕的数据,以重新训练模型的未来版本。
这是一个正反馈循环:模型使用得越多, 数据的偏差越大,模型的偏差就越大,等等。
反馈回路也会在商业环境中产生问题。例如,视频推荐系统可能会偏向于推荐最大的视频观看者消费的内容(例如,阴谋论者和极端分子倾向于观看比平均水平更多的在线视频内容),导致这些用户增加他们的视频消费,从而导致更多此类视频被推荐。我们将在第 3 章中更详细地讨论这个主题。
现在您已经了解了理论的基础,让我们回到我们的代码示例,详细了解代码与我们刚刚描述的过程的对应关系。
我们的图像识别器如何工作
让我们看看我们的图像识别器代码如何映射到这些想法。我们将每一行放入一个单独的单元格中,然后查看 每个人在做什么(我们不会解释每个参数的每一个细节,但会给出重要位的描述;完整的细节将在本书后面提供)。第一行导入所有 fastai.vision 库:
from fastai.vision.all import *
这为我们提供了创建各种计算机视觉模型所需的所有函数和类。
许多 Python 编码人员建议避免像这样(使用import *
语法)导入整个库,因为在大型软件项目中它可能会导致问题。但是,对于像 Jupyter notebook 这样的交互式工作,它的效果很好。fastai 库是专门为支持这种交互使用而设计的,它只会将必要的部分导入您的环境。
第二行从 fast.ai 数据集集合(如果之前未下载)到您的服务器,提取它(如果之前未提取),并返回Path
具有提取位置的对象:
path = untar_data(URLs.PETS)/'images'
在我在 fast.ai 学习的整个过程中,直到今天,我都学到了很多关于高效编码实践的知识。fastai 库和 fast.ai 笔记本充满了很棒的小技巧,这些小技巧帮助我成为了一个更好的程序员。例如,请注意 fastai 库不仅返回包含数据集路径的字符串,还返回一个Path
对象。这是 Python 3 标准库中一个非常有用的类,它使访问文件和目录变得更加容易。如果您以前没有遇到过它,请务必查看它的文档或教程并尝试一下。请注意,本书的网站包含指向每章推荐教程的链接。我会不断地让你知道一些我发现有用的小编码技巧,因为我们遇到了它们。
在第三行中,我们定义了一个函数 ,is_cat
它根据数据集的创建者提供的文件名规则来标记猫:
def is_cat(x): return x[0].isupper()
我们在第四行使用该函数,它告诉 fastai 我们拥有什么样的数据集以及它是如何构建的:
dls = ImageDataLoaders.from_name_func(
path, get_image_files(path), valid_pct=0.2, seed=42,
label_func=is_cat, item_tfms=Resize(224))
对于不同类型的深度学习数据集和问题,有各种类——我们在这里使用 ImageDataLoaders
. 类名的第一部分通常是您拥有的数据类型,例如图像或文本。
我们必须告诉 fastai 的另一条重要信息是如何从数据集中获取标签。计算机视觉数据集通常以这样一种方式构建,即图像的标签是文件名或路径的一部分——最常见的是父文件夹名称。fastai 带有许多标准化的标签方法,以及编写自己的方法。在这里,我们告诉 fastai 使用is_cat
我们刚刚定义的函数。
最后,我们定义Transform
我们需要的 s。一个Transform
包含 在训练期间自动应用的代码;fastai 包含许多预定义Transform
的,添加新的就像创建 Python 函数一样简单。有两种:item_tfms
应用于每个项目(在这种情况下,每个项目都调整为 224 像素的正方形),同时 使用 GPU 一次batch_tfms
应用于一批项目, 所以它们特别快(我们将在本书中看到很多这样的例子)。
为什么是 224 像素?由于历史原因,这是标准尺寸(旧的预训练模型完全需要这个尺寸),但你几乎可以通过任何东西。如果你增加尺寸,你通常会得到一个效果更好的模型(因为它可以专注于更多细节),但代价是速度和内存消耗;如果减小尺寸,则相反。
行话:分类和回归
分类和回归在机器学习中有非常具体的含义。这是我们将在本书中研究的两种主要模型类型。分类模型是试图预测一个类别或类别的模型。也就是说,它从许多离散的可能性中进行预测,例如“狗”或“猫”。回归模型是一种尝试预测一个或多个数字量的模型,例如温度或位置。有时人们使用回归一词来指代一种称为线性回归模型的特定模型;这是一种不好的做法,我们不会在本书中使用该术语!
Pet 数据集包含 7,390 张狗和猫的图片,包括 37个品种。每个图像都使用其文件名进行标记:例如,文件great_pyrenees_173.jpg是数据集中大比利牛斯犬品种图像的第 173 个示例。如果图像是猫,则文件名以大写字母开头,否则以小写字母开头。我们必须告诉 fastai 如何从文件名中获取标签,我们通过调用from_name_func
(这意味着可以使用应用于文件名的函数来提取标签)并传递 is_cat
,它返回x[0].isupper()
,它评估True
第一个字母是否为大写 (即,它是一只猫)。
这里要提到的最重要的参数是valid_pct=0.2
. 这告诉 fastai 保留 20% 的数据,根本不使用它来训练模型。这 20% 的数据称为验证集; 剩下的 80% 称为训练集。验证集用于衡量模型的准确性。 默认情况下,保留的 20% 是随机选择的。每次运行此代码时,该参数都会seed=42
将随机种子设置为相同的值,这意味着每次运行它都会获得相同的验证集——这样,如果我们更改模型并重新训练它,我们就会知道任何差异都是由于对模型的更改,而不是由于具有不同的随机验证集。
fastai 将始终仅使用验证集而不是训练集向您展示模型的准确性 。这一点非常关键,因为如果你训练一个足够大的模型足够长的时间,它最终会记住数据集中每个项目的标签!结果将不是一个有用的模型,因为我们关心的是我们的模型在以前看不见的图像上的工作情况。在创建模型时,这始终是我们的目标:在模型经过训练之后,它对模型仅在未来才能看到的数据有用。
即使您的模型没有完全记住您的所有数据,在训练的早期它也可能已经记住了其中的某些部分。因此,你训练的时间越长,你在训练集上的准确率就越高;这验证集的准确性也会在一段时间内提高,但随着模型开始记忆训练集而不是在数据中找到可概括的潜在模式,最终它会开始变得更糟。发生这种情况时,我们说模型过度拟合。
图 1-9显示了当你过拟合时会发生什么,使用一个简化的例子,我们只有一个参数和一些基于函数随机生成的数据x**2
。如您所见,尽管过拟合模型中的预测对于观察到的数据点附近的数据是准确的,但当超出该范围时,它们就相差甚远。
图 1-9。过拟合的例子
过度拟合是最重要和最具挑战性的问题 为所有机器学习从业者和所有算法提供培训。正如您将看到的那样,创建一个模型很容易,该模型在对其已训练的确切数据进行预测方面做得很好,但对模型从未见过的数据进行准确预测要困难得多。当然,这是在实践中很重要的数据。例如,如果您创建了一个手写数字分类器(我们很快就会这样做!)并使用它来识别支票上的数字,那么您将永远不会看到模型训练时使用的任何数字——每张支票都会有轻微的不同的写作变体要处理。
在本书中,您将学习许多避免过度拟合的方法。但是,只有在确认发生过拟合后(即,如果您观察到在训练期间验证准确度变差),您才应该使用这些方法。我们经常看到从业者使用过拟合避免技术,即使他们有足够的数据,他们不需要这样做,最终得到的模型可能不如他们可以实现的准确。
验证集
训练模型时,必须始终同时拥有训练集和验证集,并且您必须仅在验证集上测量模型的准确性。如果你训练的时间太长,没有足够的数据,你会看到你的模型的准确性开始变差;这称为过拟合。fastai 默认valid_pct
为0.2
,所以即使你忘记了,fastai 也会为你创建一个验证集!
训练我们的图像识别器的代码的第五行告诉 fastai 创建一个卷积神经网络 (CNN)并指定要使用的架构(即要创建什么样的模型)、我们想要训练它的数据以及要使用的指标:
learn = cnn_learner(dls, resnet34, metrics=error_rate)
为什么是CNN?这是当前最先进的创建方法 计算机视觉模型。我们将在本书中全面了解 CNN 的工作原理。它们的结构受到人类视觉系统工作方式的启发。
fastai 中有很多架构,我们将在本书中介绍(以及讨论如何创建自己的架构)。然而,大多数时候,选择架构并不是深度学习过程中非常重要的部分。这是学者们喜欢谈论的话题,但在实践中,这不太可能是您需要花费大量时间的话题。有一些标准架构在大多数情况下都可以工作,在这种情况下,我们使用的是一种称为ResNet的架构 我们将在书中谈论很多;对于许多数据集和问题,它既快速又准确。34
in 指的resnet34
是该架构变体中的层数(其他选项是18
、50
、101
和152
)。使用具有更多层的架构的模型需要更长的时间来训练并且更容易过度拟合(即,在验证集的准确性开始变差之前,您不能训练它们尽可能多的时期)。另一方面,当使用更多数据时,它们可能会更加准确。
什么是指标?度量是衡量质量的函数 模型使用验证集的预测,并将在每个 epoch 结束时打印。在这种情况下,我们使用error_rate
,这是 fastai 提供的一个函数,它按照它所说的做:告诉你验证集中有多少百分比的图像被错误地分类。另一个常见的分类指标是accuracy
(只是1.0 - error_rate
)。fastai 提供了更多,这将在本书中进行讨论。
度量的概念可能会让你想起损失,但有一个 重要区别。损失的全部目的是定义训练系统可以用来自动更新权重的“性能度量”。换句话说,一个好的损失选择是一个易于随机梯度下降使用的选择。但是一个指标是为人类消费定义的,所以一个好的指标是一个易于理解的指标,并且尽可能接近您希望模型执行的操作。有时,您可能会认为损失函数是一个合适的指标,但不一定如此。
cnn_learner
还有一个参数pretrained
,默认为 True
(因此在这种情况下使用它,即使我们没有指定它),它将模型中的权重设置为已经由专家训练的值,以识别 130 万张照片中的一千个不同类别(使用著名的ImageNet数据集)。具有已经在另一个数据集上训练过的权重的模型称为预训练模型。您几乎应该始终使用预训练模型,因为这意味着您的模型在您向其展示任何数据之前就已经非常有能力了。正如您将看到的,在深度学习模型中,其中许多功能都是您需要的,几乎不管您的项目细节如何。例如,部分预训练模型将处理边缘、梯度和颜色检测,这些都是许多任务所必需的。
使用预训练模型时,cnn_learner
将删除最后一层, 因为它总是专门针对原始训练任务(即 ImageNet 数据集分类)进行定制,并将其替换为一个或多个具有随机权重的新层,其大小适合您正在使用的数据集。模型的最后一部分称为头部。
使用预训练模型是我们必须训练更准确模型的最重要方法,更快,更少的数据,更少的时间和金钱。你可能认为这意味着使用预训练模型将是学术深度学习中研究最多的领域……但你错了!预训练模型的重要性在大多数课程、书籍或软件库功能中通常没有得到认可或讨论,也很少在学术论文中考虑。当我们在 2020 年初撰写本文时,情况才刚刚开始发生变化,但可能需要一段时间。所以要小心:与你交谈的大多数人可能会大大低估你在使用少量资源的情况下可以做的深度学习,因为他们可能不会深入了解如何使用预训练模型。
将预训练模型用于不同于最初训练的任务的任务称为迁移学习。不幸的是,由于迁移学习的研究如此之少,因此很少有领域有可用的预训练模型。例如,很少预训练模型目前可用于医学,这使得迁移学习在该领域的使用具有挑战性。此外,如何将迁移学习用于时间序列分析等任务还不是很清楚。
行话:迁移学习
将预训练模型用于不同于最初训练的任务。
learn.fine_tune(1)
正如我们所讨论的,该架构只描述了一个模板 数学函数;在我们为其包含的数百万个参数提供值之前,它实际上并没有做任何事情。
这是深度学习的关键——确定如何拟合模型的参数 得到它来解决你的问题。为了拟合模型,我们必须提供至少一条信息:查看每张图像的次数(称为epochs数)。您选择的 epoch 数量在很大程度上取决于您有多少可用时间,以及您发现在实践中需要多长时间才能适合您的模型。如果你选择的数字太小,你总是可以在以后训练更多的 epoch。
但是为什么方法被调用fine_tune
,而不是fit
?fastai 确实有一个方法叫做fit
,这确实适合模型(即,多次查看训练集中的图像,每次更新参数以使预测越来越接近目标标签)。但在这种情况下,我们从一个预训练模型开始,我们不想丢弃它已经拥有的所有功能。正如您将在本书中学到的那样,有一些重要的技巧可以让预训练模型适应新数据集——这个过程称为微调。
当您使用该fine_tune
方法时,fastai 将使用这些技巧 你。您可以设置一些参数(我们稍后会讨论),但在此处显示的默认形式中,它执行两个步骤:
-
使用一个 epoch 来拟合模型的那些必要部分,以使新的随机头与您的数据集正确工作。
-
使用调用该方法时请求的 epoch 数来拟合整个模型,更新后面层(尤其是头部)的权重比前面的层更快(正如我们将看到的,通常不需要从预训练的权重)。
模型的头部是新添加的特定于 新的数据集。一个纪元是对数据集的一次完整遍历。 在调用fit
之后,每个 epoch 之后的结果都会被打印出来,显示 epoch 编号、训练和验证集损失(用于训练模型的“性能度量”)以及 您请求的任何指标(错误率,在这种情况下)。
我们的图像识别器学到了什么
在这个阶段,我们有一个运行良好的图像识别器,但是 我们不知道它在做什么!尽管许多人抱怨深度学习会导致难以理解的“黑匣子”模型(即给出预测但没人能理解的东西),但事实并非如此。有大量研究表明如何深入检查深度学习模型并从中获得丰富的见解。话虽如此,要完全理解各种机器学习模型(包括深度学习和传统统计模型)可能具有挑战性,尤其是在考虑遇到与用于训练它们的数据截然不同的数据时它们的行为方式时。我们将在整本书中讨论这个问题。
2013 年,博士生 Matt Zeiler 和他的导师 Rob Fergus 发表了“Visualizing and Understanding Convolutional Networks”,它展示了如何可视化在模型的每一层中学习到的神经网络权重。他们仔细分析了赢得 2012 年 ImageNet 比赛的模型,并利用这种分析极大地改进了模型,使他们能够继续赢得 2013 年的比赛!图 1-10是他们发布的第一层权重的图片。
图 1-10。CNN 第一层的激活(由 Matthew D. Zeiler 和 Rob Fergus 提供)
这张照片需要一些解释。对于每一层,浅灰色背景的图像部分显示了重建的权重,底部较大的部分显示了训练图像中与每组权重最匹配的部分。对于第 1 层,我们可以看到模型发现了代表对角线、水平和垂直边缘以及各种梯度的权重。(请注意,对于每一层,只显示了特征的一个子集;实际上,所有层都有数千个。)
这些是模型为计算机视觉学习的基本构建块。神经科学家和计算机视觉研究人员对它们进行了广泛分析,事实证明,这些学习到的构建块与人眼中的基本视觉机制以及在深度学习。下一层 如图 1-11 所示。
图 1-11。CNN 第二层的激活(由 Matthew D. Zeiler 和 Rob Fergus 提供)
对于第 2 层,模型找到的每个特征都有 9 个权重重建示例。我们可以看到该模型已经学会创建特征检测器来寻找角落、重复线、圆圈和其他简单模式。这些是从第一层开发的基本构建块构建的。对于其中的每一个,图片的右侧显示了这些特征最匹配的实际图像中的小块。例如,第 2 行第 1 列中的特定图案与日落相关的渐变和纹理相匹配。
图 1-12显示了论文中的图像,显示了重建第 3 层特征的结果。
图 1-12。CNN 第三层的激活(由 Matthew D. Zeiler 和 Rob Fergus 提供)
从这张图片的右侧可以看出,这些特征现在能够识别和匹配更高级别的语义组件,例如车轮、文本和花瓣。使用这些组件,第 4 层和第 5 层可以识别更高级别的概念,如图 1-13所示。
图 1-13。CNN 第四层和第五层的激活(由 Matthew D. Zeiler 和 Rob Fergus 提供)
这篇文章正在研究一个名为AlexNet的旧模型,它只包含五层。从那时起开发的网络可以有数百层——因此您可以想象这些模型开发的功能有多么丰富!
当我们早些时候微调我们的预训练模型时,我们调整了最后一层关注的内容(花、人类、动物),以专注于猫与狗的问题。更一般地说,我们可以将这种预训练模型专门用于许多不同的任务。让我们看一些例子。
图像识别器可以处理非图像任务
顾名思义,图像识别器只能识别图像。 但是很多东西都可以表示为图像,这意味着图像识别器可以学习完成很多任务。
例如,声音可以转换为频谱图,这是一个 显示音频文件中每个时间的每个频率的数量的图表。Fast.ai 的学生 Ethan Sutin 使用这种方法,使用 8,732 个城市声音的数据集轻松击败了已发布的最先进环境声音检测模型的准确性。fastaishow_batch
清楚地显示了每个声音如何具有非常独特的频谱图, 如图 1-14 所示。
图 1-14。带有声音频谱图的 show_batch
通过简单地绘制时间序列可以很容易地转换为图像 图上的时间序列。但是,尝试以一种尽可能容易地提取最重要组件的方式来表示数据通常是一个好主意。在时间序列中,像季节性和异常这样的东西最有可能引起人们的兴趣。
各种转换可用于时间序列数据。例如,fast.ai 的学生 Ignacio Oguiza 使用称为 Gramian Angular Difference Field (GADF) 的技术从时间序列数据集中创建用于橄榄油分类的图像;您可以在图 1-15中看到结果。然后,他将这些图像输入到图像分类模型中,就像您在本章中看到的那样。他的结果尽管只有 30 张训练集图像,但准确率远远超过 90%,接近最先进的水平。
图 1-15。将时间序列转换为图像
另一个有趣的 fast.ai 学生项目示例来自 Gleb Esman。他在 Splunk 从事欺诈检测工作,使用用户鼠标移动和鼠标点击的数据集。他把这些变成图片,用彩色线条画出鼠标指针的位置、速度和加速度,并用彩色 小圆圈显示点击,如图1-16所示。他将其输入到图像识别模型中,就像我们在本章中使用的模型一样,并且效果非常好,以至于为这种欺诈分析方法获得了专利!
图 1-16。将计算机鼠标行为转换为图像
另一个例子来自 Mahmoud Kalash 等人的论文“Malware Classification with Deep Convolutional Neural Networks” ,该论文解释了 “恶意软件二进制文件被分成 8 位序列,然后转换为等效的十进制值。这个十进制向量被重新整形,并生成了代表恶意软件样本的 [a] 灰度图像,”在图 1-17中。
图 1-17。恶意软件分类过程
然后作者展示了不同类别的恶意软件通过这个过程生成的“图片”,如图 1-18所示。
图 1-18。恶意软件示例
如您所见,不同类型的恶意软件在人眼中看起来非常独特。研究人员基于此图像表示训练的模型在恶意软件分类方面比学术文献中显示的任何先前方法更准确。这表明了将数据集转换为图像表示的一个很好的经验法则:如果人眼可以从图像中识别类别,那么深度学习模型也应该能够做到这一点。
一般来说,如果您在表示数据的方式上有点创意,您会发现深度学习中的少数通用方法可以走很长一段路!您不应将此处描述的方法视为“hacky workarounds”,因为它们经常(如此处)击败以前最先进的结果。这些确实是思考这些问题领域的正确方法。
行话回顾
我们刚刚介绍了很多信息,所以让我们简要回顾一下。 表 1-3提供了一个方便的词汇表。
学期 | 意义 |
---|---|
Label | |
Architecture | |
Model | |
Parameters | |
Fit | |
Train | |
Pretrained model | |
Fine-tune | |
Epoch | |
Loss | |
Metric | |
Training set | |
Training set | |
Overfitting | |
CNN |
有了这个词汇表,我们现在可以将迄今为止介绍的所有关键概念汇总在一起。花点时间查看这些定义并阅读以下摘要。如果您可以按照解释进行操作,那么您就可以很好地理解即将进行的讨论。
机器学习是一门学科,我们在其中定义程序而不是通过 完全由我们自己编写,但通过从数据中学习。深度学习是机器学习中的一门专业,它使用多层神经网络。图像分类是一个有代表性的例子(也称为图像识别)。我们从标记数据开始——一组图像,我们为每个图像分配了一个 标签,表明它代表什么。我们的目标是生成一个程序,称为模型,给定一张新图像,该程序将准确预测该新图像所代表的内容。
每个模型都从架构的选择开始,这是该模型在内部如何工作的通用模板。训练 (或拟合)模型的过程是找到一组参数值(或权重)的过程,这些参数值(或权重)将通用架构专门化为适用于我们特定类型数据的模型。为了定义一个模型在单个预测上的表现如何,我们需要定义一个 损失函数,它决定了我们如何对预测进行评分。
为了让训练过程更快,我们可能会从一个 预训练模型开始——一个已经在其他人的数据上训练过的模型。然后,我们可以通过对我们的数据进行更多的训练来使其适应我们的数据,这个过程称为微调。
当我们训练一个模型时,一个关键的问题是确保我们的模型 泛化:它从我们的数据中学习一般的经验教训 这也适用于它将遇到的新项目,因此它可以对这些项目做出良好的预测。风险在于,如果我们训练我们的模型不好,而不是学习一般课程,它会有效地记住它已经看到的内容,然后它会对新图像做出糟糕的预测。这种失败称为过拟合。
为了避免这种情况,我们总是将数据分成两部分,训练集和 验证集。我们通过仅显示训练集来训练模型,然后通过查看模型在验证集中的项目上的表现来评估模型的表现。通过这种方式,我们检查模型从训练集中学到的课程是否是推广到验证集的课程。为了让人们评估模型在整个验证集上的表现如何,我们定义了一个 metric。在训练过程中,当模型看到训练集中的每个项目时,我们称之为epoch。
所有这些概念通常都适用于机器学习。它们适用于通过数据训练来定义模型的各种方案。使深度学习与众不同的是一类特殊的架构:基于神经网络的架构。特别是,像图像分类这样的任务在很大程度上依赖于 卷积神经网络,我们将在稍后讨论。
深度学习不仅仅用于图像分类
近年来,深度学习对图像分类的有效性得到了广泛的讨论,甚至在复杂的任务中表现出超人的 结果,比如在 CT 扫描中识别恶性肿瘤。但它可以做的远不止这些,我们将在这里展示。
例如,让我们谈谈对自动驾驶汽车至关重要的事情:定位图片中的对象。如果一个 自动驾驶汽车不知道行人在哪里,那就不知道如何避开!创建一个可以识别图像中每个单独像素内容的模型称为 分割。以下是我们如何使用Gabriel J. Brostow 等人的论文 “视频中的语义对象类:高清地面实况数据库”中的CamVid数据集的子集,使用 fastai 训练分割模型的方法:
path = untar_data(URLs.CAMVID_TINY)
dls = SegmentationDataLoaders.from_label_func(
path, bs=8, fnames = get_image_files(path/"images"),
label_func = lambda o: path/'labels'/f'{o.stem}_P{o.suffix}',
codes = np.loadtxt(path/'codes.txt', dtype=str)
)
learn = unet_learner(dls, resnet34)
learn.fine_tune(8)
epoch | train_loss | valid_loss | time |
---|---|---|---|
0 | 2.906601 | 2.347491 | 00:02 |
epoch | train_loss | valid_loss | time |
---|---|---|---|
0 | 1.988776 | 1.765969 | 00:02 |
1 | 1.703356 | 1.265247 | 00:02 |
2 | 1.591550 | 1.309860 | 00:02 |
3 | 1.459745 | 1.102660 | 00:02 |
4 | 1.324229 | 0.948472 | 00:02 |
5 | 1.205859 | 0.894631 | 00:02 |
6 | 1.102528 | 0.809563 | 00:02 |
7 | 1.020853 | 0.805135 | 00:02 |
我们甚至不打算逐行浏览此代码,因为它与我们之前的示例几乎相同!(我们将在第 15 章中深入探讨分割模型 ,以及我们在本章中简要介绍的所有其他模型以及许多其他模型。)
我们可以通过要求模型对图像的每个像素进行颜色编码来可视化它完成任务的效果。如您所见,它几乎完美地分类了每个对象中的每个像素。例如,注意所有的汽车都覆盖了相同的颜色,所有的树都覆盖了相同的颜色(在每对图像中,左边的图像是地面实况标签,右边是来自该模型):
learn.show_results(max_n=6, figsize=(7,8))
另一个深度学习在过去得到显着改善的领域 几年是自然语言处理(NLP)。计算机现在可以生成文本、自动从一种语言翻译成另一种语言、分析评论、在句子中标记单词等等。以下是训练模型所需的所有代码,该模型可以比五年前世界上存在的任何东西更好地对电影评论的情绪进行分类:
from fastai.text.all import *
dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test')
learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5, metrics=accuracy)
learn.fine_tune(4, 1e-2)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.594912 | 0.407416 | 0.823640 | 01:35 |
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.268259 | 0.316242 | 0.876000 | 03:03 |
1 | 0.184861 | 0.246242 | 0.898080 | 03:10 |
2 | 0.136392 | 0.220086 | 0.918200 | 03:16 |
3 | 0.106423 | 0.191092 | 0.931360 | 03:15 |
该模型使用Andrew Maas 等人的“Learning Word Vectors for Sentiment Analysis”中的IMDb Large Movie Review 数据集。它适用于成千上万字的电影评论,但让我们用一个简短的评论来测试它,看看它是如何工作的:
learn.predict("I really liked that movie!")
('pos', tensor(1), tensor([0.0041, 0.9959]))
在这里我们可以看到模型认为评论是积极的。结果的第二部分是“pos”在我们的数据词汇表中的索引,最后一部分是归因于每个类的概率(“pos”为 99.6%,“neg”为 0.4%)。
现在轮到你了!写你自己的迷你影评,或者从网上复制一个,你可以看看这个模型是怎么想的。
订单很重要
在 Jupyter 笔记本中,执行每个单元的顺序很重要。它不像 Excel,只要您在任何地方键入内容,所有内容都会立即更新 - 它具有每次执行单元格时都会更新的内部状态。例如,当您运行笔记本的第一个单元格时(带有“CLICK ME”注释),您 创建一个名为的对象learn
,其中包含图像分类问题的模型和数据。
如果我们要立即运行文本中刚刚显示的单元格(预测评论是否良好的单元格),我们会得到一个错误,因为该learn
对象不包含文本分类模型。此单元格需要在包含以下内容的单元格之后运行:
from fastai.text.all import *
dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test')
learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5,
metrics=accuracy)
learn.fine_tune(4, 1e-2)
输出本身可能具有欺骗性,因为它们包括上次执行单元格的结果;如果您更改单元格内的代码而不执行它,旧的(误导性)结果将保留。
除非我们明确提及,否则本书网站上提供的笔记本是按顺序运行的,从上到下。通常,在进行实验时,您会发现自己以任意顺序执行单元以快速运行(这是 Jupyter Notebook 的一个超级简洁的功能),但是一旦您探索并到达了代码的最终版本,请确保您可以运行按顺序排列笔记本中的单元格(你未来的自己不一定会记得你走的错综复杂的道路!)。
在命令模式下,键入0
两次将重新启动内核(即为笔记本电脑提供动力的引擎)。这将清除您的状态并使其就像您刚刚开始使用笔记本一样。从“单元格”菜单中选择“运行所有以上”以运行您所在位置上方的所有单元格。我们发现这在开发 fastai 库时很有用。
如果您对 fastai 方法有任何疑问,您应该使用 function doc
,将方法名称传递给它:
doc(learn.predict)
弹出一个窗口,其中包含简短的单行说明。“在文档中显示”链接将带您进入完整文档,您可以在其中找到所有详细信息和大量示例。还, fastai 的大多数方法都只是几行代码,因此您可以单击“源”链接以查看幕后发生的确切情况。
让我们继续做一些不那么性感,但可能在商业上更有用的东西:从简单的表格数据构建模型。
行话:表格
表格形式的数据,例如来自电子表格、数据库或逗号分隔值 (CSV) 文件的数据。表格模型是一种尝试根据表中其他列中的信息来预测表中的一列的模型。
事实证明,这看起来也非常相似。以下是训练一个模型所必需的代码,该模型将根据一个人的社会经济背景预测一个人是否是高收入者:
from fastai.tabular.all import *
path = untar_data(URLs.ADULT_SAMPLE)
dls = TabularDataLoaders.from_csv(path/'adult.csv', path=path, y_names="salary",
cat_names = ['workclass', 'education', 'marital-status', 'occupation',
'relationship', 'race'],
cont_names = ['age', 'fnlwgt', 'education-num'],
procs = [Categorify, FillMissing, Normalize])
learn = tabular_learner(dls, metrics=accuracy)
如您所见,我们必须告诉 fastai 哪些列是分类的(包含作为离散选择集之一的值,例如occupation
)与连续的(包含表示数量的数字,例如age
)。
没有可用于此任务的预训练模型(通常,预训练模型不适用于任何表格建模任务,尽管一些组织已经创建它们供内部使用),fine_tune
所以我们在这种情况下 不使用。相反,我们使用 fit_one_cycle
最常用的从头开始训练 fastai 模型的方法(即,没有迁移学习):
learn.fit_one_cycle(3)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.359960 | 0.357917 | 0.831388 | 00:11 |
1 | 0.353458 | 0.349657 | 0.837991 | 00:10 |
2 | 0.338368 | 0.346997 | 0.843213 | 00:10 |
该模型使用Ron Kohavi的论文 “Scaling Up the Accuracy of Naive-Bayes Classifiers: a Decision-Tree Hybrid”中的成人数据集,其中包含一些 有关个人的人口统计数据(例如他们的教育、婚姻状况、种族、性别以及他们的年收入是否超过 5 万美元)。该模型的准确率超过 80%,训练时间约为 30 秒。
让我们再看一个。推荐系统很重要,尤其是在电子商务中。亚马逊和 Netflix 等公司努力推荐用户可能喜欢的产品或电影。这是训练预测电影人的模型的方法 可能会根据他们之前的观看习惯,使用MovieLens数据集:
from fastai.collab import *
path = untar_data(URLs.ML_SAMPLE)
dls = CollabDataLoaders.from_csv(path/'ratings.csv')
learn = collab_learner(dls, y_range=(0.5,5.5))
learn.fine_tune(10)
epoch | train_loss | valid_loss | time |
---|---|---|---|
0 | 1.554056 | 1.428071 | 00:01 |
epoch | train_loss | valid_loss | time |
---|---|---|---|
0 | 1.393103 | 1.361342 | 00:01 |
1 | 1.297930 | 1.159169 | 00:00 |
2 | 1.052705 | 0.827934 | 00:01 |
3 | 0.810124 | 0.668735 | 00:01 |
4 | 0.711552 | 0.627836 | 00:01 |
5 | 0.657402 | 0.611715 | 00:01 |
6 | 0.633079 | 0.605733 | 00:01 |
7 | 0.622399 | 0.602674 | 00:01 |
8 | 0.629075 | 0.601671 | 00:00 |
9 | 0.619955 | 0.601550 | 00:01 |
该模型在 0.5 到 5.0 的范围内预测电影收视率,平均误差在 0.6 左右。由于我们预测的是一个连续的数字,而不是一个类别,我们必须使用y_range
参数告诉 fastai 我们的目标有什么范围。
尽管我们实际上并没有使用预训练模型(与我们没有使用表格模型的原因相同),这个例子表明 fastai 让我们在这种情况下无论如何都可以使用(你将在第 5 章fine_tune
了解它的工作原理和原因 )。有时最好试验一下vs看看哪个最适合您的数据集。fine_tune
fit_one_cycle
我们可以使用之前看到的相同show_results
调用来查看一些用户和电影 ID、实际评分和预测的示例:
learn.show_results()
userId | movieID | ratimg | rating_pred | |
---|---|---|---|---|
0 | 157 | 1200 | 4.0 | 3.558502 |
1 | 23 | 344 | 2.0 | 2.700709 |
2 | 19 | 1221 | 5.0 | 4.390801 |
3 | 430 | 592 | 3.5 | 3.944848 |
4 | 547 | 858 | 4.0 | 4.076881 |
5 | 292 | 39 | 4.5 | 3.753513 |
6 | 529 | 1265 | 4.0 | 3.349463 |
7 | 19 | 231 | 3.0 | 2.881087 |
8 | 475 | 4963 | 4.0 | 4.023387 |
9 | 130 | 260 | 4.5 | 3.979703 |
数据集:模型的食物
您已经在本节中看到了很多模型,每个模型都使用不同的数据集进行训练以执行不同的任务。在机器学习和深度学习中,没有数据我们什么都做不了。因此,为我们创建数据集以训练我们的模型的人是(通常被低估的)英雄。一些最有用和最重要的数据集是那些成为重要学术基线的数据集—— 研究人员广泛研究并用于比较算法变化的数据集。其中一些成为家喻户晓的名字(至少在训练模型的家庭中!),例如 MNIST、CIFAR-10 和 ImageNet。
之所以选择本书中使用的数据集,是因为它们提供了您可能遇到的数据类型的很好示例,并且学术文献中有许多使用这些数据集的模型结果示例,您可以将其与您的工作进行比较。
本书中使用的大多数数据集都花费了创建者大量的工作来构建。例如,在本书的后面,我们将向您展示如何创建一个可以在法语和英语之间进行翻译的模型。钥匙 对此的输入是宾夕法尼亚大学的 Chris Callison-Burch 教授于 2009 年编写的法语/英语平行文本语料库。该数据集包含超过 2000 万个句子对 法语和英语。他以一种非常聪明的方式构建了数据集:通过爬取数百万加拿大网页(通常是多语言的),然后使用一组简单的启发式方法将法语内容的 URL 转换为指向相同英语内容的 URL。
当你在本书中查看数据集时,想想它们可能来自哪里以及它们可能是如何被整理的。然后想想你可以为自己的项目创建什么样的有趣数据集。(我们甚至会很快带您逐步完成创建自己的图像数据集的过程。)
fast.ai 花了很多时间创建流行数据集的缩减版本,这些数据集专门用于支持快速原型设计和 实验,更容易学习。在本书中,我们通常会从使用其中一个缩小版开始,然后放大到完整版(就像我们在本章中所做的那样!)。这就是世界顶级从业者在实践中的建模方式;他们使用数据子集进行大部分实验和原型设计,并且只有在充分了解自己必须做什么时才使用完整的数据集。
我们训练的每个模型都显示了训练和验证损失。一个好的验证集是训练过程中最重要的部分之一。让我们看看为什么并学习如何创建一个。
验证集和测试集
正如我们所讨论的,模型的目标是对数据进行预测。但是模型训练过程从根本上说是愚蠢的。如果我们使用所有数据训练模型,然后使用相同的数据评估模型,我们将无法判断我们的模型在它未见过的数据上的表现如何。如果没有这条非常有价值的信息来指导我们训练我们的模型,它很有可能会很好地预测该数据,但在新数据上表现不佳。
为了避免这种情况,我们的第一步是将我们的数据集分成两组:训练集(我们的模型在训练中看到)和验证集,也称为开发集 (仅用于评估)。这让我们可以测试模型是否从训练数据中吸取教训,这些数据可以推广到新数据,即验证数据。
理解这种情况的一种方法是,从某种意义上说,我们不希望我们的模型通过“作弊”来获得好的结果。如果它对一个数据项做出了准确的预测,那应该是因为它已经学习了该类项的特征,而不是因为模型是通过实际看到该特定项而形成的。
分离我们的验证数据意味着我们的模型在训练中永远不会看到它,因此完全不受它的污染,也没有以任何方式作弊。正确的?
事实上,不一定。情况更加微妙。这是因为在现实场景中,我们很少只通过训练一次参数来构建模型。相反,我们可能会通过关于网络架构、学习率、数据增强策略以及我们将在接下来的章节中讨论的其他因素的各种建模选择来探索模型的许多版本。许多这些选择可以描述为超参数的选择。这个词反映了 它们是关于参数的参数,因为它们是控制权重参数含义的更高级别的选择。
问题在于,即使普通的训练过程在学习权重参数值时只查看对训练数据的预测,但我们的情况并非如此。当我们决定探索新的超参数值时,作为建模者,我们正在通过查看对验证数据的预测来评估模型!因此,模型的后续版本间接地由我们看到验证数据形成。正如自动训练过程存在过度拟合训练数据的危险一样,我们也存在通过人工试错和探索过度拟合验证数据的危险。
这个难题的解决方案是引入另一个级别更高的保留数据:测试集。正如我们在训练过程中保留验证数据一样,我们必须保留测试 甚至来自我们自己的数据。不能用于改进模型;它只能用于在我们努力的最后阶段评估模型。实际上,我们定义了数据切割的层次结构,基于我们希望将其从训练和建模过程中隐藏的程度:训练数据完全公开,验证数据公开较少,测试数据完全隐藏。这种层次结构与不同类型的建模和评估过程本身平行——带有反向传播的自动训练过程,在训练会话之间尝试不同超参数的更多手动过程,以及对我们最终结果的评估。
测试和验证集应该有足够的数据来确保你 对您的准确性有一个很好的估计。例如,如果您正在创建一个猫检测器,您通常希望验证集中至少有 30 只猫。这意味着,如果您有一个包含数千个项目的数据集,则使用默认的 20% 验证集大小可能超出您的需要。另一方面,如果您有大量数据,使用其中的一些进行验证可能没有任何缺点。
拥有两个级别的“保留数据”——一个验证集和一个测试集,其中一个级别代表你实际上对自己隐藏的数据——可能看起来有点极端。但这通常是必要的,因为模型倾向于使用最简单的方法来进行良好的预测(记忆),作为易犯错误的人类,我们往往倾向于自欺欺人,因为我们的模型表现如何。测试集的纪律帮助我们在智力上保持诚实。这并不意味着我们总是需要一个单独的测试集——如果你的数据很少,你可能只需要一个验证集——但通常最好尽可能使用一个。
如果您打算聘请第三方代表您执行建模工作,那么同样的纪律也很重要。第三方可能无法准确理解您的要求,或者他们的激励措施甚至可能鼓励他们误解它们。一个好的测试集可以大大降低这些风险,并让您评估他们的工作是否解决了您的实际问题。
坦率地说,如果您是组织中的高级决策者(或者您正在为高级决策者提供建议),那么最重要的一点是:如果您确保您真正了解测试和验证集是什么以及为什么它们'很重要,当组织决定使用 AI 时,您将避免我们看到的最大的单一失败源。例如,如果您正在考虑引入外部供应商或服务,请确保您提供一些供应商永远无法看到的测试数据。然后,您根据您的测试数据检查他们的模型,使用您根据实践中对您真正重要的因素选择的指标,然后您决定什么水平的性能是足够的。(您自己尝试简单的基线也是一个好主意,这样您就知道一个真正简单的模型可以实现什么。通常会证明您的简单模型的性能与外部“专家”产生的模型一样好! )
在定义测试集时使用判断
要做好定义验证集(也可能是测试集)的工作, 您有时会想做的不仅仅是随机抓取原始数据集的一小部分。请记住:验证集和测试集的一个关键属性是它们必须代表您将来会看到的新数据。这听起来像是一个不可能的命令!根据定义,您还没有看到这些数据。但你通常仍然知道一些事情。
看几个例子很有启发意义。其中许多示例来自预测建模竞赛在 Kaggle平台上,它很好地代表了你在实践中可能会看到的问题和方法。
一种情况可能是您正在查看时间序列数据。对于时间序列,选择数据的随机子集都太容易了(您 可以查看您尝试预测的日期之前和之后的数据)并且不代表大多数业务用例(您使用历史数据构建模型以供将来使用)。如果您的数据包含日期并且您正在构建一个模型以供将来使用,您将需要选择具有最新日期的连续部分作为您的验证集(例如,最近两周或上个月的可用数据)。
假设您要将图 1-19中的时间序列数据拆分 为训练集和验证集。
图 1-19。一个时间序列
正如我们在图 1-20中看到的那样,随机子集是一个糟糕的选择(太容易填补空白,并且不能说明您在生产中需要什么)。
图 1-20。一个糟糕的训练子集
相反,使用较早的数据作为您的训练集(以及较晚的数据作为验证集),如图 1-21所示。
图 1-21。一个好的训练子集
例如,Kaggle 举办了一场 预测厄瓜多尔连锁杂货店销售额的比赛。卡格尔的 训练数据从 2013 年 1 月 1 日到 2017 年 8 月 15 日,测试数据从 2017 年 8 月 16 日到 2017 年 8 月 31 日。这样,比赛组织者确保参赛者 在未来,从他们的模型的角度来看。这类似于量化对冲基金交易员根据过去的数据进行回测以检查他们的模型是否可以预测未来时期的方式。
第二种常见情况是,您可以轻松预测在生产中预测的数据可能与您必须用来训练模型的数据在质量上不同的方式。
在 Kaggle 分心驾驶员比赛中,自变量是驾驶汽车的驾驶员的照片,因变量是诸如 发短信、吃饭或安全地向前看。很多图片都是相同的司机在不同的位置, 如图 1-22 所示。如果您是一家保险公司,根据这些数据构建模型,请注意,您最感兴趣的是模型在以前从未见过的驾驶员身上的表现(因为您可能只有一小部分人的训练数据)。认识到这一点,比赛的测试数据由未出现在训练集中的人的图像组成。
图 1-22。来自训练数据的两张图片
如果将图 1-22中的一张图像放入训练集中,另一张放入验证集中,您的模型将很容易对验证集中的一张进行预测,因此它的性能似乎比它会在新人身上。另一种观点是,如果你使用所有人来训练你的模型,你的模型可能会过度拟合这些特定人的特殊性,而不仅仅是学习状态(发短信、吃饭等)。
Kaggle 渔业竞赛中也有类似的动态, 以确定渔船捕获的鱼类种类,以减少对濒危种群的非法捕捞。这 测试集由未出现在训练数据中的船只图像组成,因此在这种情况下,您希望验证集也包括不在训练集中的船只。
有时可能不清楚您的验证数据将有何不同。例如,对于使用卫星图像的问题,您需要收集有关训练集是仅包含某些地理位置还是来自地理上分散的数据的更多信息。
现在您已经了解了如何构建模型,您可以决定接下来要深入研究什么。
进一步的研究
每章还有一个“进一步研究”部分,提出了一些文本中没有完全回答的问题,或者给出了更高级的作业。这些问题的答案不在本书的网站上。你需要自己做研究!
-
为什么 GPU 对深度学习有用?CPU 有何不同,为什么它对深度学习的效果较差?
-
尝试考虑反馈循环可能影响机器学习使用的三个领域。看看您是否可以找到在实践中发生的记录示例。