【FastAI】01_intro

Posted by ShawnD on January 10, 2022
1
2
3
4
#hide
!pip install -Uqq fastbook
import fastbook
fastbook.setup_book()
1
2
#hide
from fastbook import *

Your Deep Learning Journey

在本章中,我们将告诉你更多关于这本书的内容,介绍深度学习背后的关键概念,并在不同的任务中训练我们的第一个模型。如果你不是来自一个技术或数学背景也没关系(尽管如果你是!也没关系!)我们写这本书是为了让更多的人能够接触到深度学习。

Deep Learning Is for Everyone

很多人认为你需要各种各样难以找到的东西来获得深度学习的好结果,但正如你在本书中看到的,这些人都错了。

深度学习是一种利用多层神经网络提取和转换数据的计算机技术,从人类语音识别到动物图像分类。每一层都从前一层获取输入,并逐步对其进行细化。这些层是由算法训练的,这些算法可以将它们的误差最小化并提高它们的准确性。通过这种方式,网络学会执行特定的任务。我们将在下一节详细讨论训练算法。

深度学习具有强大的功能、灵活性和简单性。这就是为什么我们认为它应该应用于许多学科。这些学科包括社会科学、物理科学、艺术、医学、金融、科学研究等。举个个人的例子,尽管没有医学背景,杰里米创建了Enlitic,一家使用深度学习算法诊断疾病的公司。公司成立几个月后,就宣布其算法可以比放射科医生更准确地识别恶性肿瘤。

这里有一个列表,里面有现在是世界上最好的成千上万个不同领域的任务,深度学习,或者大量使用深度学习的方法:

  • 自然语言处理(NLP): 回答问题;语音识别;总结文件;分类文档;在文档中查找名称、日期等;搜索提到一个概念的文章
  • 计算机视觉: 卫星和无人机图像解读(例如,用于抗灾);人脸识别;图像字幕;阅读交通标志;在自动驾驶汽车中定位行人和车辆
  • 医学:发现影像学异常,包括CT、MRI和x线影像;病理切片计数特征;超声波的测量特征;诊断糖尿病性视网膜病变
  • 生物: 折叠蛋白质;蛋白质分类;许多基因组学任务,如肿瘤-正常测序和临床上可操作的基因突变分类;细胞分类;分析蛋白质/蛋白质相互作用
  • 图像生成::图像着色;提高图像分辨率;消除图像噪音;以著名艺术家的风格将图像转换为艺术
  • 推荐系统:网络搜索;产品推荐;主页布局
  • 游戏:国际象棋、围棋、大多数雅达利电子游戏和许多实时策略游戏
  • 机器人:处理难以定位的物体(例如透明、有光泽、缺乏纹理)或难以拾取的物体
  • 其他应用:财务和物流预测、文本到语音等…

值得注意的是,深度学习具有如此多样的应用,但几乎所有的深度学习都基于一种类型的模型,即神经网络。

但神经网络实际上并不完全新。为了更广泛地看待该领域,值得从一点历史开始。

Neural Networks: A Brief History

1943年,神经生理学家Warren McCulloch和逻辑学家Walter Pitts合作开发了人工神经元的数学模型。在他们的论文《A Logical Calculus of the Ideas Immanent in Nervous Activity》中,他们宣布:

:由于神经活动的“all-or-none”的性质,神经事件及其之间的关系可以通过命题逻辑来处理。人们发现,每个网络的行为都可以用这些术语来描述。

McCulloch和Pitts意识到,可以用简单的加法和阈值来表示真实神经元的简化模型。Pitts是自学成才的,12岁时,他收到了与伟大的伯特兰·罗素一起在剑桥大学学习的录取通知书。他没有接受这个邀请,事实上,他一生都没有接受任何高级学位或权威职位的提议。他的大部分著名作品都是在他无家可归的时候完成的。尽管他缺乏官方认可的职位,社会孤立度也越来越高,但他与McCulloch的工作很有影响力,并被一位名叫Frank Rosenblatt的心理学家采用。

Rosenblatt进一步发展了人工神经元,使其具有学习能力。更重要的是,他致力于构建第一个实际使用这些原则的设备,Mark I Perceptron。在《The Design of an Intelligent Automaton》中,Rosenblatt写道:“我们现在即将见证这样一台机器的诞生——一台能够在没有任何人类训练或控制的情况下感知、识别和识别周围环境的机器。” 感知器是构建的,能够成功识别简单的形状。

一位名叫Marvin Minsky的麻省理工学院教授(他在同一所高中落后于Rosenblatt!)和Seymour Papert写了一本关于Rosenblatt发明的书,名为Perceptrons(麻省理工学院出版社)。他们表明,这些设备的单层无法学习一些简单但关键的数学函数(如XOR)。在同一本书中,他们还表明,使用多层设备可以解决这些限制。不幸的是,这些见解中只有第一个得到了广泛认可。因此,未来二十年,全球学术界几乎完全放弃了神经网络。

也许过去50年来神经网络中最关键的工作是David Rumelhart、James McClellan和麻省理工学院出版社于1986年发布的PDP研究小组的 multi-volume Parallel Distributed Processing (PDP)。第1章提出了与Rosenblatt相似的希望:

人们比今天的计算机更聪明,因为大脑采用了一种基本的计算架构,更适合处理人们非常擅长的自然信息处理任务的核心方面。…我们将引入一个计算框架来建模认知过程,该框架似乎……比其他框架更接近于大脑可能完成的计算风格。

PDP在这里使用的前提是,传统计算机程序的工作原理与大脑非常不同,这可能是为什么计算机程序(当时)在做事情方面如此糟糕,以至于大脑发现很容易(例如识别图片中的物体)。作者声称,PDP方法“比其他框架更接近”大脑的工作方式,因此它可能更有能力处理此类任务。

事实上,PDP中列出的方法与当今神经网络中使用的方法非常相似。这本书将并行分布式处理定义为需要:

  • 一组处理单元
  • 一种激活状态
  • 每个单元的输出函数
  • 单元之间的连接模式
  • 一种通过连接网络传播活动模式的传播规则
  • 一种激活规则,用于将撞击单元的输入与该单元的当前状态相结合,为该单元产生输出
  • 一种学习规则,根据经验修改连接模式
  • 系统必须在其中运行的环境

我们将从这本书中看到,现代神经网络可以满足这些要求。

在20世纪80年代,大多数模型都是用二层神经元构建的,从而避免了Minsky和Papert发现的问题(使用上述框架,这是他们的“单位间连接模式”)。事实上,神经网络在80年代和90年代被广泛用于真实、实用的项目。然而,对理论问题的误解再次阻碍了该领域。 理论上,只增加一层神经元就足以让任何数学函数与这些神经网络近似,但在实践中,这些网络往往太大,太慢,没有用处。

尽管研究人员在30年前表明,要获得实际良好的性能,您需要使用更多的神经元层,但直到过去十年,这一原则才得到更广泛的赞赏和应用。由于使用了更多的层,再加上计算机硬件的改进、数据可用性的增加以及算法调整使神经网络更快、更轻松地训练,神经网络现在终于发挥了潜力。我们现在有了Rosenblatt的承诺:“一台能够在没有任何人类训练或控制的情况下感知、识别和识别周围环境的机器。”

这就是您将学习如何在这本书中构建的内容。但首先,既然我们将花很多时间在一起,让我们彼此了解一下……

Who We Are

我们是Sylvain和Jeremy,你们这次旅行的向导。我们希望您会发现我们非常适合这个职位。

Jeremy已经使用和教授机器学习大约30年了。25 年前,他开始使用神经网络。在此期间,他领导了许多以机器学习为核心的公司和项目,包括创办了第一家专注于深度学习和医学的公司,Enlitic,并担任世界上最大的机器学习社区Kagle的总裁兼首席科学家。他和 Rachel Thomas 博士是 fast.ai 联合创始人, 这是建立这本书基础课程的组织。

您不时会在像Jeremy这样的边栏中直接收到我们的消息:

J:大家好,我是杰里米!您可能有兴趣知道,我没有任何正规的技术教育。我完成了文学学士学位,主修哲学,成绩不高。我对做真正的项目比理论研究更感兴趣,所以我在大学期间在一家名为麦肯锡公司的管理咨询公司全职工作。如果你宁愿弄脏东西,也不愿花几年时间学习抽象概念,那么你就会明白我来自哪里!注意我的边栏,找到最适合数学或形式性较低技术背景的人的信息——即像我这样的人……

另一方面,Sylvain对正规技术教育了解很多。事实上,他写了10本数学教科书,涵盖了整个高级法语数学课程!

S: 与Jeremy不同,我没有花很多年时间编码和应用机器学习算法。相反,我最近通过观看Jeremy的fast.ai课程视频来到了机器学习世界。所以,如果你是一个没有在命令行打开终端并编写命令的人,那么你就会明白我来自哪里!注意我的边栏,找到最适合具有更数学或正式技术背景,但现实世界编码经验较少的人的信息——也就是说,像我这样的人……

来自世界各地的数十万各行各业的学生学习了fast.ai课程。Sylvain是Jeremy见过的最令人印象深刻的课程学生,这导致他加入了fast.ai,然后与Jeremy一起成为fastai软件库的合著者。

所有这些都意味着,在我们之间,你们拥有两个世界中最好的:对软件了解比任何人都多的人,因为他们写了它;数学专家,编码和机器学习专家;以及了解数学相对局外人和编码和机器学习相对局外人的感觉的人。

任何看过体育节目的人都知道,如果你有一个两人评论团队,那么你还需要第三个人来做“特别评论”。我们的特别评论员是亚历克西斯·加拉格尔。亚历克西斯的背景非常多样化:他曾是数学生物学研究员、剧本作家、即兴表演者、麦肯锡顾问(如杰里米!)、斯威夫特编码员和首席技术官。

A:我决定是时候了解这些人工智能的东西了!毕竟,我几乎尝试了其他一切……但我在构建机器学习模型方面没有真正的背景。尽管如此……这有多难?我会像你一样整本书学习。注意我的边栏,了解我发现在旅途中有帮助的学习技巧,希望您也会发现有帮助。

How to Learn Deep Learning

哈佛大学教授David Perkins写了《让学习变得完整》(Jossey-Bass),他对教学有很多话要说。基本思想是教整个游戏。这意味着,如果你教棒球,你首先带人们去看棒球比赛或让他们玩棒球比赛。你不会教他们如何从头开始缠绕线来打棒球,也不会教抛物线的物理原理,也不会教球在球棒上的摩擦系数。

哥伦比亚数学博士、前布朗教授和K-12数学老师保罗·洛克哈特在有影响力的论文《数学家的哀叹》中想象了一个以数学教学方式教授音乐和艺术的噩梦世界。孩子们在花了十多年的时间掌握音乐符号和理论,花时间将乐谱转换为不同的调子之前,不允许听或演奏音乐。在艺术课上,学生学习颜色和涂抹器,但直到大学才被允许实际绘画。听起来很荒谬?这就是数学的教学方式——我们要求学生花数年时间死记硬背,学习枯燥、脱节的基本知识,我们声称,在他们大多数人退出该学科很久后,这些基本原理稍后会有回报。

不幸的是,这就是许多深度学习教学资源的起点——要求学习者遵循黑森的定义和泰勒损失函数近似定理,而从未给出实际工作代码的示例。我们不是在敲微积分。我们喜欢微积分,Sylvain甚至在大学里教过它,但我们认为这不是学习深度学习的最佳起点!

在深度学习中,如果你有动力修复模型,让它做得更好,这真的很有帮助。那时你开始学习相关理论。但你首先需要有模型。我们几乎通过真实的例子教导一切。当我们构建这些示例时,我们会越来越深入,我们将向您展示如何让您的项目越来越好。这意味着您将在上下文中逐步学习您需要的所有理论基础,以便您了解它为什么重要以及它是如何工作的。

所以,这是我们对你的承诺。在这本书中,我们将遵循以下原则:

  • 教整个游戏。我们将首先展示如何使用完整、有效、非常有用、最先进的深度学习网络,使用简单、富有表现力的工具来解决现实世界的问题。然后,我们将逐渐越来越深入地了解这些工具是如何制造的,以及制造这些工具的工具是如何制造的,等等……
  • 总是通过示例进行教学。我们将确保有一个上下文和目标,您可以直观地理解,而不是从代数符号操作开始。
  • 尽可能地简化。我们花了数年时间构建工具和教学方法,使之前复杂的主题变得非常简单。
  • 消除障碍。到目前为止,深度学习一直是一场非常独家的游戏。我们正在打破它,并确保每个人都能玩。

深度学习最困难的部分是手工学习:你如何知道你是否有足够的数据,它是否格式正确,你的模型是否正在正确训练,如果不是,你应该怎么做?这就是为什么我们相信边做边学。与基本数据科学技能一样,通过深度学习,只有通过实践经验才能变得更好。试图在理论上花费太多时间可能会适得其反。关键是只需编写代码并尝试解决问题:当你有上下文和动机时,理论可以稍后出现。

有时旅程会感到艰难。当你感到被困住了的时候。别放弃!翻阅这本书,找到你肯定没有卡住的最后一点,然后从那里慢慢读完,找到第一件不清楚的东西。然后自己尝试一些代码实验,然后在谷歌上搜索更多关于您遇到的问题的教程——通常您会发现材料上的一些不同角度可能会帮助它单击。此外,一读时不理解所有内容(特别是代码)是意料之中的,也是正常的。在继续之前,试图连续理解材料有时可能很困难。有时,在您从道路上的部分获得更多上下文后,从拥有更大的画面中,事情就会点击到位。因此,如果您确实被困在一个部分,无论如何都要尝试继续前进,并做个便条,稍后再回到它。

请记住,您不需要任何特定的学术背景就能在深度学习中取得成功。没有博士学位的人在研究和工业领域取得了许多重要的突破,例如”Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks”——过去十年最有影响力的论文之一——引用了5000多次,这是亚历克·拉德福德本科时撰写的。即使在特斯拉,首席执行官埃隆·马斯克也表示,他们正试图解决制造自动驾驶汽车的极其严峻的挑战:

绝对不需要博士学位。重要的是对人工智能的深刻理解&以真正有用的方式实现NN的能力(后一点才是真正困难的)。不在乎你是否高中毕业。

然而,要取得成功,你需要做的就是将你在这本书中学到的东西应用到个人项目中,并始终坚持不懈。

Your Projects and Your Mindset

无论您是想从叶子的照片中识别植物是否患有疾病,自动生成编织图案,从X光中诊断结核病,还是确定浣熊何时使用您的猫门,我们都会让您尽快(通过他人预先训练的模型)对自己的问题进行深度学习,然后逐步深入了解更多详细信息。在下一章的前30分钟内,您将学习如何使用深度学习以最先进的准确性解决自己的问题!(如果您渴望立即获得编码,请随时直接跳过那里。)有一个有害的神话,你需要有谷歌大小的计算资源和数据集才能进行深度学习,但事实并非如此。

那么,什么样的任务可以造就好的测试用例?你可以训练你的模特区分毕加索和莫奈的画作,或者挑选你女儿的照片,而不是你儿子的照片。专注于你的爱好和激情是有帮助的——为自己设定四五个小项目,而不是努力解决一个大而宏大的问题,在你开始的时候往往效果更好。由于很容易陷入困境,过早试图野心勃勃往往适得其反。然后,一旦你掌握了基础知识,就瞄准完成你真正引以为豪的事情!

深度学习几乎可以解决任何问题。例如,我的第一家初创公司是一家名为FastMail的公司,该公司在1999年推出时提供了增强的电子邮件服务(至今仍然存在)。2002年,我将其设置为使用原始形式的深度学习单层神经网络,以帮助对电子邮件进行分类并阻止客户接收垃圾邮件。

擅长深度学习的人的共同性格特征包括顽皮和好奇心。已故物理学家理查德·费曼(Richard Feynman)是一个我们期望擅长深度学习的人的例子:他对亚原子粒子运动的理解源于他对板块在空气中旋转时如何晃动的乐趣。

现在让我们从软件开始,专注于您将学到的东西。

The Software: PyTorch, fastai, and Jupyter

我们使用数十种不同的软件包和许多不同的编程语言完成了数百个机器学习项目。在fast.ai,我们使用今天使用的大多数主要深度学习和机器学习包编写了课程。PyTorch于2017年问世后,我们花了1000多个小时对其进行测试,然后决定将其用于未来的课程、软件开发和研究。从那时起,PyTorch已成为世界上增长最快的深度学习库,并已用于大多数顶级会议的研究论文。这通常是工业使用的主要指标,因为这些论文最终用于商业产品和服务。我们发现PyTorch是深度学习最灵活、最具表现力的库。它不以速度换取简单,而是两者兼而有之。

PyTorch作为低级基础库效果最佳,为高级功能提供基本操作。Fastai库是最受欢迎的在PyTorch上添加此更高功能的库。它也特别适合这本书的目的,因为它在提供深度分层软件架构方面是独一无二的(甚至还有一篇关于这个分层API的同行评审学术论文)。在这本书中,随着我们越来越深入地深入学习的基础,我们还将越来越深入地深入fastai的层次。这本书涵盖了fastai库的第2版,这是一个从零开始的重写,提供了许多独特的功能。

然而,你学习什么软件并不重要,因为学习从一个库切换到另一个库只需要几天。真正重要的是正确学习深度学习基础和技术。我们的重点是使用清晰表达您需要学习的概念的代码。在我们教授高级概念的地方,我们将使用高级fastai代码。当我们教授低级概念时,我们将使用低级PyTorch,甚至纯Python代码。

如果现在感觉新的深度学习库正在以快速的速度出现,那么您需要为未来几个月和几年更快的变化速度做好准备。随着越来越多的人进入该领域,他们将带来更多的技能和想法,并尝试更多的事情。您应该假设您今天学习的任何特定库和软件都将在一两年内过时。想想网络编程世界中一直发生的库和技术堆栈的变化数量——这是一个比深度学习更成熟、增长缓慢的领域。我们坚信,学习的重点需要放在了解基本技术以及如何在实践中应用它们,以及如何在新工具和技术发布时快速积累专业知识。

在这本书的结尾,您将了解fastai(以及PyTorch的大部分内容)中的几乎所有代码,因为在每一章中,我们将深入挖掘一个级别,向您展示我们在构建和训练模型时到底发生了什么。这意味着您将学习现代深度学习中使用的最重要的最佳做法——不仅仅是如何使用它们,还包括它们如何真正工作和实施。如果您想在另一个框架中使用这些方法,如果需要,您将拥有这样做所需的知识。

由于学习深度学习最重要的事情是编写代码和实验,所以拥有一个很好的代码实验平台很重要。最受欢迎的编程实验平台称为Jupyter。这就是我们将在整个书中使用的内容。我们将向您展示如何使用Jupyter来训练和实验模型,并内省数据预处理和模型开发管道的每个阶段。Jupyter Notebook是Python中最常见的数据科学工具,这是有充分理由的。它功能强大、灵活且易于使用。我们认为你会喜欢它的!

让我们在实践中看看,并训练我们的第一个模型。

Your First Model

正如我们之前所说,在解释为什么事情有效之前,我们会教你如何做。按照这种自上而下的方法,我们将从实际训练图像分类器开始,以几乎100%的准确性识别狗和猫。要训练这个模型并运行我们的实验,您需要进行一些初始设置。别担心,没看起来那么难。

S:不要跳过设置部分,即使它一开始看起来很吓人,特别是如果您很少或根本没有使用终端或命令行等东西的经验。其中大部分实际上没有必要,你会发现最简单的服务器只能使用您通常的网页浏览器进行设置。为了学习,你必须与这本书并行进行自己的实验。

Getting a GPU Deep Learning Server

要完成本书中的几乎所有事情,您需要访问一台配备NVIDIA GPU的计算机(不幸的是,主要深度学习库不完全支持其他品牌的GPU)。然而,我们不建议你买一个;事实上,即使你已经有了,我们也不建议你现在使用它!设置计算机需要时间和精力,您希望现在将所有精力集中在深度学习上。因此,我们建议您租用一台已经预装并准备就绪的计算机。当您使用它时,每小时的费用可能只有0.25美元,一些选项甚至是免费的。

jargon: 图形处理单元(GPU):也称为图形卡。计算机中的一种特殊处理器,可以同时处理数千个单个任务,专为在计算机上显示用于玩游戏的3D环境而设计。这些基本任务与神经网络的工作非常相似,因此GPU运行神经网络的速度可以比普通CPU快数百倍。所有现代计算机都包含GPU,但很少有计算机包含深度学习所需的正确GPU。

随着公司的来来往往和价格的变化,这本书中使用的GPU服务器的最佳选择将随着时间的推移而变化。我们在这本书的网站上维护了我们推荐的选项列表,所以现在就去那里,按照说明连接到GPU深度学习服务器。别担心,在大多数平台上设置只需要大约两分钟,许多平台甚至不需要任何付款,甚至不需要信用卡即可开始。

A: 听从这个建议!如果你喜欢电脑,你会忍不住要设置自己的盒子。当心!这是可行的,但令人惊讶的是,参与和分散了注意力。这本书没有标题是“你想知道的关于Ubuntu系统管理、NVIDIA驱动程序安装、apt-get、conda、pip和Jupyter笔记本配置的一切”是有充分理由的。那将是一本自己的书。在设计和部署了我们的生产机器学习基础设施后,我可以证明它令人满意,但它与建模无关,就像维护飞机与驾驶飞机一样无关。

jargon: Jupyter笔记本:一款软件,允许您将格式化的文本、代码、图像、视频等包含在单个交互式文档中。Jupyter因其在许多学术领域和行业中的广泛使用和巨大影响而获得了软件的最高荣誉ACM软件系统奖。Jupyter Notebook是数据科学家最广泛用于开发和与深度学习模型交互的软件。

Running Your First Notebook

笔记本按章节标记,然后按笔记本编号标记,因此它们与本书中的顺序相同。因此,您将看到的第一个Notebook是您现在需要使用的Notebook。您将使用此笔记本训练一种可以识别狗和猫照片的模型。为此,您将下载狗和猫的照片数据集,并使用它来训练模型。数据集只是一堆数据——可以是图像、电子邮件、财务指标、声音或其他任何东西。有许多免费提供的数据集适合训练模型。其中许多数据集是由学者创建的,以帮助推进研究,许多数据集可用于竞争(有些数据科学家可以竞争,看看谁拥有最准确的模型!),还有一些是其他流程(如财务申报)的副产品。

注:全套和分离的笔记本:有两个文件夹包含不同版本的Notebook。完整的文件夹包含用于创建您现在正在阅读的书的确切笔记本,以及所有散文和输出。剥离的版本具有相同的标题和代码单元格,但所有输出和散文都已被删除。阅读了这本书的一部分后,我们建议您翻阅剥离的笔记本,关闭这本书,看看您是否能在执行之前弄清楚每个单元格将显示什么。另请尝试回忆代码正在演示的内容。

Jupyter笔记本可以采用两种模式之一:编辑模式或命令模式。在编辑模式下,在键盘上键入以通常的方式将字母输入单元格。但是,在命令模式下,您将看不到任何闪烁的光标,键盘上的按键将具有特殊功能。

在继续之前,请按下键盘上的Escape键切换到命令模式(如果您已经处于命令模式,这什么都不做,所以现在按下它以防万一)。要查看所有可用功能的完整列表,请按H;按Escape删除此帮助屏幕。请注意,在命令模式下,与大多数程序不同,命令不需要您按住Control、Alt或类似功能——您只需按下所需的字母键。

您可以通过按C来复制单元格(需要先选择单元格,并用轮廓指示;如果尚未选择,请单击一次)。然后按V粘贴副本。

单击以“#单击我”行开头的单元格进行选择。该行中的第一个字符表示以下内容是Python中的注释,因此在执行单元格时会忽略它。信不信由你,牢房的其余部分是一个完整的系统,用于创建和训练识别猫和狗的最先进模型。所以,我们现在就训练它吧!为此,只需按下键盘上的Shift-Enter,或按下工具栏上的播放按钮。然后在发生以下事情时等待几分钟:

  • 一个名为Oxford-IIIT宠物数据集的数据集将从fast.ai数据集下载到您正在使用的GPU服务器,该数据集包含来自37个不同品种的7349张猫狗图像
  • 使用赢得比赛的模型,将从互联网下载已经在130万张图像上训练的预训练模型。
  • 预训练模型将利用转移学习的最新进展进行微调,以创建一个专门为识别狗和猫而定制的模型。

前两个步骤只需要在GPU服务器上运行一次。如果您再次运行单元格,它将使用已下载的数据集和模型,而不是再次下载它们。让我们看看单元格的内容和结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
#id first_training
#caption Results from the first training
# 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)

您可能不会看到与书中完全相同的结果。训练模型中涉及许多小随机变化的来源。然而,在本例中,我们通常看到误差率远低于0.02。

重要信息:训练时间:根据您的网络速度,下载预训练的模型和数据集可能需要几分钟。运行 fine_tune 可能需要一分钟左右。这本书中的模型通常需要几分钟来训练,你自己的模型也是如此,所以想出充分利用这段时间的技巧是个好主意。例如,在模型训练时继续阅读下一节,或者打开另一个笔记本并用于一些编码实验。

Sidebar: This Book Was Written in Jupyter Notebooks

我们使用Jupyter笔记本写了这本书,因此对于这本书中的几乎每个图表、表格和计算,我们将向您展示自己复制它所需的确切代码。这就是为什么在这本书中,你经常会看到一些代码,然后是表格、图片或只是一些文本。如果您访问该书的网站,您将找到所有代码,您可以尝试自己运行和修改每个示例。

你刚刚看到了输出表格的单元格在书中的样子。以下是输出文本的单元格示例:

1
2
3
1+1

2

Jupyter将始终打印或显示最后一行的结果(如果有的话)。例如,以下是输出图像的单元格示例:

1
2
img = PILImage.create(image_cat())
img.to_thumb(192)

End sidebar

那么,我们如何知道这个模型是否有用?在表格的最后一列中,您可以看到错误率,即错误识别图像的比例。错误率是我们的指标——我们衡量模型质量的指标,选择模型质量是直观和可理解的。如您所见,即使训练时间只有几秒钟(不包括一次性下载数据集和预训练模型),但模型几乎完美无缺。事实上,你已经达到的准确性比10年前的任何人都好得多!

实际上,让我们看看这个模型是否真的有效。去拿一张狗或猫的照片;如果你没有方便的照片,只需搜索谷歌图像并下载你在那里找到的图像。现在在定义上传器的情况下执行单元格。它将输出一个您可以单击的按钮,以便您可以选择要分类的图像:

1
2
3
#hide_output
uploader = widgets.FileUpload()
uploader

现在您可以将上传的文件传递给模型。确保这是一张清晰的狗或一只猫的照片,而不是线条画、卡通或类似的东西。笔记本会告诉你它是狗还是猫,以及它有多自信。希望您会发现您的模型做得很好:

1
2
3
#hide
# For the book, we can't actually click an upload button, so we fake it
uploader = SimpleNamespace(data = ['images/chapter1_cat_example.jpg'])
1
2
3
4
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}")

恭喜你的第一个分类器!

但这是什么意思?你到底做了什么?为了解释这一点,让我们再次缩小一下大局。

What Is Machine Learning?

您的分类器是一个深度学习模型。如前所述,深度学习模型使用神经网络,神经网络最初可以追溯到20世纪50年代,最近由于最近的进步而变得强大。

另一个关键的背景是,深度学习只是机器学习这一更一般学科中的一个现代领域。要了解您在训练自己的分类模型时所做事情的本质,您不需要理解深度学习。只需看看您的模型和训练流程如何是适用于机器学习的概念示例就足够了。

因此,在本节中,我们将描述什么是机器学习。我们将研究关键概念,并展示如何将它们追溯到介绍它们的原始文章中。

与常规编程一样,机器学习是让计算机完成特定任务的一种方式。但是,我们将如何使用常规编程来做我们在最后一节中刚刚做的事情:在照片中识别狗和猫?我们必须为计算机写下完成任务所需的确切步骤。

通常,当我们编写程序时,我们很容易写下完成任务的步骤。我们只是想一下如果我们必须手工完成任务,我们会采取哪些步骤,然后把它们翻译成代码。例如,我们可以编写对列表进行排序的函数。一般来说,我们会写一个看起来像<>的函数(其中输入可能是未排序的列表,结果是排序列表)。

1
2
3
4
5
6
#hide_input
#caption A traditional program
#id basic_program
#alt Pipeline inputs, program, results
gv('''program[shape=box3d width=1 height=0.7]
inputs->program->results''')

但对于识别照片中有点棘手的物体;当我们识别图片中的物体时,我们采取了哪些步骤?我们真的不知道,因为这一切都发生在我们的大脑中,而我们却没有意识到这一点!

早在计算之初,1949年,一位名叫Arthur Samuel的IBM研究人员就开始以另一种方式让计算机完成任务,他称之为机器学习。在1962年的经典文章《人工智能:自动化的前沿》中,他写道:

为计算机编程进行此类计算充其量只是一项艰巨的任务,这主要是因为计算机本身的任何固有复杂性,而是因为需要以最令人恼火的细节来阐述过程的每一分钟步骤。正如任何程序员都会告诉你的那样,计算机是巨大的白痴,而不是巨大的大脑。

他的基本思想是:与其告诉计算机解决问题所需的确切步骤,不如向它展示要解决问题的示例,并让它自己想办法解决问题。事实证明,这非常有效:到1961年,他的跳棋项目学到了很多东西,以至于它击败了康涅狄格州冠军!以下是他描述自己想法的方式(来自上面的同一篇文章):

假设我们安排了一些自动方法,从实际性能方面测试任何当前权重分配的有效性,并提供更改权重分配的机制,以最大限度地提高性能。我们不需要深入研究这样一个程序的细节,看看它可以完全自动化,也不需要看到这样编程的机器会从其经验中“学习”。

这个简短的陈述中嵌入了许多强大的概念:

  • “分配权重”的想法
  • 每个权重分配都有一些“实际性能”的事实
  • 要求有“自动方式”来测试该性能,
  • 需要一种“机制”(即另一个自动流程),通过更改权重分配来提高性能

让我们逐一讨论这些概念,以了解它们在实践中是如何结合在一起的。首先,我们需要通过分配权重理解 Samuel 是什么意思。

权重只是变量,权重分配是这些变量的特定值选择。程序的输入是它为产生结果而处理的值——例如,将图像像素作为输入,并因此返回分类“狗”。程序的权重分配是定义程序如何运行的其他值。

由于它们会影响程序,它们在某种意义上是另一种输入,因此我们将在<>中更新我们的基本图片,并将其替换为<>,以便考虑到这一点。

1
2
3
4
5
#hide_input
#caption A program using weight assignment
#id weight_assignment
gv('''model[shape=box3d width=1 height=0.7]
inputs->model->results; weights->model''')

我们已经将盒子的名称从程序更改为模型。这是为了遵循现代术语,并反映模型是一种特殊的程序:它可以根据权重做许多不同的事情。它可以通过许多不同的方式实现。例如,在塞缪尔的跳棋程序中,权重的不同值将导致不同的跳棋玩法策略。

(顺便说一句,塞缪尔所谓的“权重”现在通常被称为模型参数,以防您遇到该术语。术语权重保留给特定类型的模型参数。)

其次,Samuel说,我们需要一种自动的方法来测试当前任何重量分配在实际性能方面的有效性。就他的跳棋程序而言,模型的“实际性能”将是它演奏得有多好。你可以通过将两个模型设置为相互比赛,并查看哪个通常获胜,自动测试它们的表现。

最后,他说我们需要一个改变权重分配的机制,以最大限度地提高性能。例如,我们可以查看获胜模型和失败模型之间的权重差异,并在获胜方向上进一步调整权重。

我们现在明白他为什么说这样的程序可以完全自动化,而且……这样编程的机器会从其经验中“学习”。当权重调整也是自动的时,学习将变得完全自动化——当我们没有通过手动调整模型的权重来改进模型时,我们依赖于一种自动机制,该机制根据性能进行调整。

注意模型的结果(例如,跳棋游戏中的动作)与其性能(例如,它是否赢得比赛或获胜的速度)之间的区别。

另请注意,一旦模型经过训练——即一旦我们选择了最终的、最佳的、最喜欢的权重分配——我们就可以将权重视为模型的一部分,因为我们不再改变它们了。

jargon: 机器学习:通过允许计算机从其经验中学习,而不是通过手动编码单个步骤来开发的程序。

What Is a Neural Network?

可能存在一系列编码的检查器策略,以及某种搜索机制,然后权重可能会改变策略的选择方式、在搜索期间关注棋盘的哪些部分,等等。但对于图像识别程序、理解文本或我们可能想象的许多其他有趣的问题来说,这个模型可能是什么样子一点也不明显。 不难想象这个模型对于一个跳棋程序来说会是什么样子。

我们想要某种功能,它是如此灵活,只需改变其权重,就可以用于解决任何给定的问题。令人惊讶的是,这个函数实际上存在!我们已经讨论过的是神经网络。也就是说,如果您将神经网络视为数学函数,它原来是一个根据其权重而极其灵活的函数。一个被称为万能逼近定理的数学证明表明,从理论上讲,这个函数可以解决任何问题的准确性。神经网络如此灵活的事实意味着,在实践中,它们通常是一种合适的模型,您可以集中精力训练它们的过程——即找到良好的体重分配。

但那个过程呢?你可以想象,你可能需要找到一种新的“机制”,来自动更新每个问题的权重。这将很费力。我们在这里还希望是一种完全通用的方法来更新神经网络的权重,使其在任何给定的任务中得到改进。方便的是,这也存在!

这被称为随机梯度下降(SGD)。我们将在<>中详细了解神经网络和SGD的工作原理,并解释通用逼近定理。然而,就目前而言,我们将使用Samuel自己的话:我们不需要深入研究这样一个程序的细节,看看它可以完全自动化,并看到如此编程的机器将从其经验中“学习”。

J:别担心,SGD和神经网络在数学上都不复杂。两者几乎完全依赖加法和乘法来完成他们的工作(但他们做了很多加法和乘法!)。当学生看到细节时,我们听到的主要反应是:“仅此而已吗?”

换句话说,概括地说,神经网络是一种特殊的机器学习模型,它正好符合塞缪尔的原始概念。神经网络之所以特殊,是因为它们非常灵活,这意味着它们只需找到合适的权重,就可以解决异常广泛的问题。这是强大的,因为随机梯度下降为我们提供了一种自动找到这些权重值的方法。

缩小后,现在让我们放大并使用Samuel的框架重新讨论我们的图像分类问题。

我们的输入是图像。我们的权重是神经网中的权重。我们的模型是一个神经网络。我们的结果是由神经网络计算的值,如“狗”或“猫”。

下一件呢,一种从实际性能角度测试当前任何重量分配有效性的自动方法?确定“实际性能”很容易:我们可以简单地将模型的性能定义为预测正确答案的准确性。

综上加,假设SGD是我们更新权重分配的机制,我们可以看到我们的图像分类器如何是一个机器学习模型,就像塞缪尔设想的那样。

A Bit of Deep Learning Jargon

Samuel在20世纪60年代工作,从那时起,术语发生了变化。以下是我们讨论的所有部分的现代深度学习术语:

  • 模型的功能形式被称为其架构(但要小心——有时人们使用模型作为架构的同义词,因此这可能会令人困惑)。
  • 权重称为参数。
  • 预测是根据独立变量计算的,即不包括标签的数据。
  • 该模型的结果称为预测。
  • 性能衡量标准称为损失。
  • 损失不仅取决于预测,还取决于正确的标签(也称为目标或因变量);例如,“狗”或“猫”。

Limitations Inherent To Machine Learning

从这张图片中,我们现在可以看到一些关于训练深度学习模式的基本内容:

  • 没有数据就无法创建模型。
  • 模型只能学习根据用于训练它的输入数据中看到的模式进行操作。
  • 这种学习方法只创建预测,而不是推荐的操作。
  • 仅仅有输入数据的例子是不够的;我们也需要这些数据的标签(例如,狗和猫的照片不足以训练模型;我们需要每个模型的标签,说明哪些是狗,哪些是猫)

一般来说,我们看到,大多数组织说他们没有足够的数据,实际上意味着他们没有足够的标签数据。如果任何组织有兴趣在实践中使用模型做一些事情,那么他们大概有一些投入计划运行模型。据推测,他们已经以其他方式这样做了一段时间(例如,手动或使用一些启发式程序),所以他们有来自这些进程的数据!例如,放射学实践几乎肯定会有医学扫描档案(因为他们需要能够检查患者随着时间的推移的发展情况),但这些扫描可能没有包含诊断或干预列表的结构化标签(因为放射科医生通常创建自由文本自然语言报告,而不是结构化数据)。我们将在本书中经常讨论标签方法,因为它在实践中是一个非常重要的问题。

由于此类机器学习模型只能做出预测(即尝试复制标签),这可能导致组织目标和模型能力之间的巨大差距。例如,在这本书中,您将学习如何创建一个可以预测用户可能购买哪些产品的推荐系统。这通常用于电子商务,例如通过显示排名最高的项目来自定义主页上显示的产品。但这种模型通常是通过查看用户及其购买历史记录(输入)以及他们购买或查看的内容(标签)来创建的,这意味着模型可能会告诉您用户已经拥有或已经知道的产品,而不是他们最有兴趣听到的新产品。这与(比如)当地书商的专家可能做的事情大不相同,他们提出问题来了解你的品味,然后告诉你你以前从未听说过的作者或系列。

另一个关键见解来自考虑模型如何与环境交互。这可以创建反馈循环,如下所述:

  • 根据过去的逮捕地点,建立了一个预测性警务模型。在实践中,这实际上不是预测犯罪,而是预测逮捕,因此部分只是反映了现有警务过程中的偏见。
  • 然后,执法人员可能会使用该模式来决定其警察活动的重点,导致这些地区的逮捕人数增加。
  • 然后,关于这些额外逮捕的数据将被反馈回来,以重新训练该模型的未来版本。

这是一个积极的反馈循环,使用模型越多,数据就越有偏见,使模型更有偏见,等等。

反馈循环也可能在商业环境中造成问题。例如,视频推荐系统可能偏向于推荐最大视频观看者消费的内容(例如,阴谋论者和极端分子倾向于观看比平均水平更多的在线视频内容),导致这些用户增加视频消费,导致推荐更多此类视频。

现在您已经看到了理论的基础,让我们回到我们的代码示例,详细了解代码如何与我们刚才描述的进程相对应。

How Our Image Recognizer Works

让我们看看我们的图像识别器代码如何映射到这些想法。我们将把每行放入一个单独的单元格中,看看每行都在做什么(我们还不会解释每个参数的每个细节,但会给出重要位的描述;完整的细节将在书的后面出现)。

第一行导入所有fastai.vision库。

1
from fastai.vision.all import *

这为我们提供了创建各种计算机视觉模型所需的所有功能和类。

J: 许多Python编码器建议避免导入这样的整个库(使用导入*语法),因为在大型软件项目中,这可能会导致问题。然而,对于Jupyter笔记本等交互式工作来说,它非常有效。Fastai库专为支持这种交互式使用而设计,它只会将必要的部件导入您的环境。

第二行将标准数据集从fast.ai数据集集合(如果之前未下载)下载到服务器,将其提取(如果之前未提取),并返回具有提取位置的 Path 对象:

1
path = untar_data(URLs.PETS)/'images'

S:在fast.ai学习的整个过程中,甚至今天,我学到了很多关于生产性编码实践的知识。Fastai库和fast.ai笔记本充满了很棒的小技巧,帮助我成为一个更好的程序员。例如,请注意,fastai库不仅返回包含数据集路径的字符串,还返回路径对象。这是Python 3标准库中一个非常有用的类,使访问文件和目录变得更加容易。如果您以前从未遇到过它,请务必查看其文档或教程并试用。请注意,https://book.fast.ai[website]包含每章推荐教程的链接。当我们遇到一些编码技巧时,我会一直告诉你我发现有用的小技巧。

在第三行中,我们定义了一个函数 is_cat,根据数据集创建者提供的文件名规则标记猫:

1
def is_cat(x): return x[0].isupper()

我们在第四行使用该函数,该函数告诉fastai我们拥有哪种数据集,以及它的结构:

1
2
3
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 函数。

最后,我们定义了我们需要的 TransformTransform 包含训练期间自动应用的代码;fastai包含许多预定义的 Transform,添加新 Transform 就像创建Python函数一样简单。有两种类型:item_tfms 应用于每个项目(在这种情况下,每个项目大小调整为224像素正方形),而 batch_tfms 使用GPU一次应用于一批项目,因此它们特别快(我们将在整本书中看到许多示例)。

为什么是224像素?这是出于历史原因的标准尺寸(旧的预训练型号完全需要这个尺寸),但您几乎可以通过任何东西。如果你增加尺寸,你通常会得到一个效果更好的模型(因为它能够专注于更多细节),但代价是速度和内存消耗;如果你缩小尺寸,情况正好相反。

注:分类和回归:分类和回归在机器学习中有非常具体的含义。这是我们将在这本书中调查的两种主要类型的模型。分类模型是试图预测类或类别的模型。也就是说,它是从一些离散的可能性中预测的,例如“狗”或“猫”。回归模型是试图预测一个或多个数值的模型,如温度或位置。有时人们使用回归这个词来指一种叫做线性回归模型的特定模型;这是一个糟糕的做法,我们不会在这本书中使用这个词!

宠物数据集包含7390张狗和猫的照片,包括37个不同品种。每个图像都使用其文件名进行标记:例如,文件 great_pyrenees_173.jpg 是数据集中大比利牛斯犬繁殖狗图像的第173个示例。如果图像是猫,文件名以大写字母开头,否则小写字母。我们必须告诉fastai如何从文件名中获取标签,我们通过调用 from_name_func(这意味着可以使用应用于文件名的函数提取标签)和传递 is_cat 来做到这一点,is_cat 返回 x[0].isupper(),如果第一个字母是大写(即是猫),则计算为True。

这里需要提及的最重要参数是 valid_pct=0.2。这告诉fastai保留20%的数据,根本不用它来训练模型。这20%的数据称为验证集;其余80%称为训练集。验证集用于测量模型的准确性。默认情况下,保留的20%是随机选择的。参数 seed=42 每次运行此代码时都会将随机种子设置为相同的值,这意味着我们每次运行时都会获得相同的验证集——这样,如果我们更改模型并重新训练它,我们知道任何差异都是由于模型的更改,而不是由于拥有不同的随机验证集。

Fastai将始终仅使用验证集,而不是训练集来向您展示模型的准确性。这绝对至关重要,因为如果您训练足够大的模型足够长的时间,它最终会记住数据集中每个项目的标签!结果实际上不是一个有用的模型,因为我们关心的是我们的模型在以前看不见的图像上工作得有多好。在创建模型时,这始终是我们的目标:为了让它对模型在未来训练后才看到的数据有用。

即使您的模型尚未完全记住您的所有数据,在培训的早期,它也可能已经记住了某些部分。因此,您训练的时间越长,您在训练集中的准确性就越高;验证集的准确性也会在一段时间内提高,但最终随着模型开始记住训练集,而不是在数据中找到可推广的基础模式,情况将开始恶化。当这种情况发生时,我们说模型过拟合了。

使用简化示例,其中我们只有一个参数,以及一些基于函数 x**2 的随机生成数据。如您所见,尽管过拟合模型中的预测对观测到的数据点附近的数据是准确的,但当它们超出该范围时,它们相去不远。

在训练所有机器学习从业人员和所有算法时,过度拟合是一个最重要和最具挑战性的问题。正如您将看到的,创建一个模型非常容易,该模型在对训练的确切数据进行很好的预测方面做得很好,但对该模型从未见过的数据进行准确的预测要困难得多。当然,这些数据在实践中实际上很重要。例如,如果您创建一个手写的数字分类器(因为我们很快就会创建!)并使用它来识别支票上写的数字,这样您就永远不会看到模型训练的任何数字——支票的书写变化将略有不同。在这本书中,您将学习许多避免过度拟合的方法。然而,您只有在确认确实发生了过度拟合后才应使用这些方法(即,您实际上观察到在培训期间验证准确性越来越差)。我们经常看到从业者使用避免过拟合的技术,即使他们有足够的数据不需要这样做,最终得出了一个可能不如他们所能实现的模型。

重要信息:验证集:当您训练模型时,您必须始终同时拥有训练集和验证集,并且必须仅在验证集上测量模型的准确性。如果您训练时间太长,数据不足,您将看到模型的准确性开始恶化;这被称为过拟合。fastai默认为valid_pct为0.2,因此即使您忘记了,fastai也会为您创建一个验证集!

我们的图像识别器训练代码的第五行告诉fastai创建一个卷积神经网络(CNN),并指定使用什么架构(即创建哪种模型),我们想训练它什么数据,以及使用什么指标:

1
learn = cnn_learner(dls, resnet34, metrics=error_rate)

为什么是CNN?这是当前创建计算机视觉模型的最先进方法。我们将从这本书中了解CNN的工作原理。他们的结构受到人类视觉系统运作方式的启发。

Fastai中有许多不同的架构,我们将在这本书中介绍这些架构(以及讨论如何创建自己的架构)。然而,在大多数情况下,选择架构并不是深度学习过程中非常重要的一部分。这是学者们喜欢谈论的事情,但在实践中,它不太可能是你需要花很多时间在上面的事情。有一些标准体系结构大部分时间都有效,在这种情况下,我们使用的是一个名为ResNet的体系结构,我们将在书中谈论很多;它对于许多数据集和问题来说既快速又准确。Resnet34中的34指的是架构此变体中的层数(其他选项是18、50、101和152)。使用层次较多的体系结构的模型需要更长的训练时间,并且更容易过度拟合(即,在验证集的准确性开始恶化之前,您无法训练它们超过那么多的时代)。另一方面,当使用更多数据时,它们可以更加准确。

什么是指标?指标是使用验证集测量模型预测质量的函数,并将在每个 epoch 结束时打印。在这种情况下,我们使用的是fastai提供的错误率函数,它完全按照它所说的去做:告诉你验证集中有多少百分比的图像被错误分类。另一个常见的分类指标是准确性(仅为1.0 - error_rate)。fastai提供了更多,本书将对此进行讨论。

指标的概念可能会提醒你损失,但有一个重要的区别。损失的全部目的是定义一个“性能指标”,训练系统可以使用它来自动更新权重。换句话说,一个好的损失选择是一个易于随机梯度下降的选择。但指标是为人类消费定义的,因此一个好的指标是您易于理解的指标,并尽可能与您希望模型做什么紧密地联系起来。有时,您可能会决定损失函数是一个合适的指标,但情况不一定如此。

cnn_learner 还有一个预训练的参数,默认为 True(因此在这种情况下使用它,即使我们没有指定它),它将模型中的权重设置为专家已经训练的值,以识别130万张照片中的一千个不同类别(使用著名的ImageNet数据集)。具有已在其他数据集上训练的权重的模型称为预训练模型。您几乎应该始终使用预训练模型,因为它意味着您的模型在您向它显示任何数据之前就已经非常强大了。而且,正如您将看到的,在深度学习模型中,这些功能中有许多是您需要的,几乎无论您的项目细节如何。例如,预训练模型的部分内容将处理边缘、渐变和颜色检测,这是许多任务所需的。

使用预训练模型时,cnn_learner 将删除最后一层,因为这总是专门针对原始训练任务(即ImageNet数据集分类),并将其替换为一个或多个具有随机权重的新层,大小适合您正在处理的数据集。模型的最后一部分被称为 head

使用预训练模型是最重要的方法,我们必须使我们能够以更快的速度训练更准确的模型,更少的数据,更少的时间和金钱。你可能认为这意味着使用预训练模型将是学术深度学习中研究最多的领域……但你会非常非常错误!大多数课程、书籍或软件库功能通常不承认或讨论预训练模型的重要性,学术论文也很少考虑。当我们在2020年初写这篇文章时,情况才刚刚开始改变,但可能需要一段时间。所以要小心:与你交谈的大多数人可能会大大低估你在资源很少的情况下在深度学习中可以做的事情,因为他们可能不会深刻理解如何使用预训练模型。

对与最初训练的任务不同的任务使用预训练模型称为迁移学习。不幸的是,由于迁移学习研究不足,很少有领域有预训练的模型可用。例如,目前医学中可用的预训练模型很少,这使得迁移学习在该领域使用具有挑战性。此外,如何将迁移学习用于时间序列分析等任务尚不清楚。

jargon: 迁移学习:将预训练模型用于与最初训练不同的任务。

我们代码的第六行告诉fastai如何 fit 模型:

1
learn.fine_tune(1)

正如我们所讨论的,该结构只描述了数学函数的模板;在我们为其包含的数百万个参数提供值之前,它实际上不会做任何事情。

这是深度学习的关键——确定如何拟合模型的参数,使其能够解决您的问题。为了适应模型,我们必须提供至少一条信息:查看每张图像的次数(称为 epoch 数量)。您选择的 epoch 数量在很大程度上取决于您有多少时间可用,以及您在实践中发现适合模型需要多长时间。如果您选择的数字太小,您以后总是可以训练更多 epoch。

但为什么这个方法叫做 fine_tune, 而不叫做 fit?Fastai实际上确实有一个叫做 fit 的方法,它确实拟合模型(即多次查看训练集中的图像,每次更新参数,使预测越来越接近目标标签)。但在这种情况下,我们从预训练模型开始,我们不想放弃它已经拥有的所有功能。正如您将在这本书中学到的,有一些重要的技巧可以根据新数据集调整预训练的模型——这个过程被称为微调。

jargon: 微调:一种迁移学习技术,通过使用与预训练任务不同的任务来更新预训练模型的参数。

当您使用 fine_tune 方法时,fastai 会为您使用这些技巧。您可以设置几个参数(我们稍后将讨论),但在此处显示的默认表单中,它有两个步骤:

  • 使用一个 epoch 来拟合模型中使新的随机 head 正确处理数据集所需的部分。
  • 使用调用方法时请求的 epoch 数来拟合整个模型,更新后层(特别是 head)的权重比早期层更快(正如我们将看到的,这通常不需要从预训练的权重中进行许多更改)。

模型的 head 是新添加的特定于新数据集的部分。epoch 是完全通过数据集。调用fit后,打印每个 epoch 后的结果,显示 epoch 编号、训练和验证集损失(用于训练模型的“性能指标”)以及您要求的任何指标(在这种情况下是错误率)。

因此,有了所有这些代码,我们的模型只从标签示例中学会了识别猫和狗。但它是如何做到的?

What Our Image Recognizer Learned

在这个阶段,我们有一个运行良好的图像识别器,但我们不知道它实际上在做什么!尽管许多人抱怨深度学习会导致无法穿透的“黑匣子”模型(即给出预测但没人能理解的东西),但这真的离事实再远了。大量研究表明,如何深入检查深度学习模型,并从中获得丰富的见解。尽管如此,各种机器学习模型(包括深度学习和传统统计模型)可能很难完全理解,特别是在考虑它们在遇到与用于训练它们的数据非常不同的数据时的行为时。我们将在整个书中讨论这个问题。

2013年,一名博士生Matt Zeiler和他的导师Rob Fergus发表了一篇论文 “Visualizing and Understanding Convolutional Networks”,展示了如何在模型的每一层中可视化神经网络权重。他们仔细分析了赢得2012年ImageNet比赛的模型,并利用这一分析极大地改进了模型,以便能够继续赢得2013年的比赛!下图是他们发布的第一层权重图片。

这幅画需要一些解释。对于每个图层,浅灰色背景的图像部分显示重建的权重图片,底部较大的部分显示训练图像中与每组权重最匹配的部分。对于第1层,我们可以看到模型发现了代表对角线、水平和垂直边缘的权重,以及各种不同的梯度。(请注意,每个图层只显示一个特征的子集;在实践中,所有图层都有数千个。)这些是模型为计算机视觉学到的基本组成部分。神经科学家和计算机视觉研究人员对此进行了广泛分析,事实证明,这些学习的基石与人眼的基本视觉机制以及深度学习时代之前开发的手工计算机视觉特征非常相似。

对于第2层,模型发现的每个特征都有九个权重重建示例。我们可以看到,该模型已经学会了创建查找角落、重复线、圆圈和其他简单模式的功能检测器。这些是由第一层开发的基本积木构建的。对于其中的每个,图片的右侧显示来自实际图像的小补丁,这些功能最匹配。例如,第2行第1列中的特定模式与日落相关的渐变和纹理匹配。

正如您从这张图片的右侧看到的,这些功能现在可以识别和匹配更高级的语义组件,如车轮、文本和花瓣。使用这些组件,第四层和第五层可以识别更高级别的概念。

本文正在研究一个名为AlexNet的旧模型,该模型仅包含五层。自那时以来开发的网络可以有数百个层——因此您可以想象这些模型开发的功能有多丰富!

当我们早些时候微调预训练模型时,我们调整了最后几层的重点(花朵、人类、动物),以专门研究猫与狗的问题。更一般地说,我们可以将这种预先训练的模型专门用于许多不同的任务。让我们看看一些例子。

Image Recognizers Can Tackle Non-Image Tasks

顾名思义,图像识别器只能识别图像。但许多东西可以表示为图像,这意味着图像识别器可以学习完成许多任务。

例如,声音可以转换为光谱图,光谱图是显示音频文件中每次频率的图表。Fast.ai学生Ethan Sutin使用这种方法,使用8732个城市声音的数据集轻松击败了最先进的环境声音检测模型的公开准确性。fastai的 show_batch 清楚地显示了每种不同声音如何具有相当独特的光谱图。

只需在图表上绘制时间序列,就可以轻松地将时间序列转换为图像。然而,尝试以尽可能轻松地提取最重要的组件的方式表示您的数据通常是一个好主意。在一个时间序列中,季节性和异常等事情最有可能引起关注。时间序列数据有各种转换可供选择。例如,fast.ai学生Ignacio Oguiza使用一种名为Gramian Angular Difference Field(GADF)的技术,从时间序列数据集中创建了橄榄油分类图像。然后,他将这些图像输入图像分类模型,就像您在本章中看到的模型一样。尽管他的结果只有30张训练集图像,但准确度远远超过90%,接近最新水平。

另一个有趣的fast.ai学生项目示例来自Gleb Esman。他在Splunk从事欺诈检测工作,使用用户鼠标移动和鼠标点击的数据集。他通过绘制图像将这些图像转换为图片,其中鼠标指针的位置、速度和加速度使用彩色线条显示,点击使用彩色小圆圈显示。然后,他把它输入了图像识别模型,就像我们在本章中使用的模型一样,它运行得很好,以至于为这种欺诈分析方法获得了专利!

另一个例子来自Mahmoud Kalash等人的论文 “Malware Classification with Deep Convolutional Neural Networks”,该论文解释说,“恶意软件二进制文件分为8位序列,然后转换为等效的小数值。这个十进制矢量被重塑,并生成一个表示恶意软件示例的灰度图像”

然后,作者展示了通过这个不同类别的恶意软件过程生成的“图片”

如您所见,不同类型的恶意软件在人眼中看起来非常独特。研究人员基于此图像表示训练的模型在恶意软件分类方面比学术文献中显示的任何先前方法都更准确。这表明将数据集转换为图像表示是一个很好的经验法则:如果人眼可以从图像中识别类别,那么深度学习模型也应该能够识别。

一般来说,如果您在表示数据方面有点创造性,你会发现深度学习中的少数通用方法可以大有裨益!你不应该想到像这里描述的“陈腐的变通办法”的方法,因为实际上它们经常(如这里)击败以前最先进的结果。这些真的是思考这些问题领域的正确方法。

Jargon Recap

机器学习是一门学科,我们定义程序不是完全自己编写,而是从数据中学习。深度学习是机器学习中的一个专业,使用多层神经网络。图像分类是一个有代表性的例子(也称为图像识别)。我们从标记数据开始;即一组图像,我们在其中为每张图像分配了一个标签,指示它代表什么。我们的目标是生成一个名为模型的程序,在给定新图像的情况下,该模型将准确预测该新图像代表的内容。

每个模型都从结构的选择开始,这是该模型如何在内部工作的一般模板。训练(或拟合)模型的过程是找到一组参数值(或权重)的过程,这些参数值(或权重)将该参数值(或权重)专门化为适合我们特定类型数据的模型。为了定义模型在单个预测上的表现,我们需要定义一个损失函数,该函数决定了我们如何将预测评分为好是坏。

为了加快训练过程,我们可能会从预训练模型开始——一个已经根据他人数据训练的模型。然后,我们可以通过在数据上对其进行更多训练来调整它以适应我们的数据,这个过程被称为微调。

当我们训练模型时,一个关键问题是确保我们的模型进行概括——也就是说,它从我们的数据中吸取一般教训,这些教训也适用于它将遇到的新项目,以便它能够对这些项目做出良好的预测。风险在于,如果我们对模型进行糟糕的训练,而不是吸取一般教训,而是有效地记住它已经看到的东西,然后它会对新图像做出糟糕的预测。这种失败被称为过度拟合。为了避免这种情况,我们总是将数据分为两部分,训练集和验证集。我们通过只显示训练集来训练模型,然后通过查看模型在验证集中的项目上的表现来评估模型的表现。通过这种方式,我们检查模型从培训集学到的课程是否是推广到验证集的课程。为了让一个人评估模型在验证集中的总体表现如何,我们定义了一个指标。在培训过程中,当模型看到训练集中的每个项目时,我们称之为时代。

所有这些概念都适用于机器学习。也就是说,它们适用于通过数据训练模型来定义模型的各种方案。使深度学习与众不同的是一类特殊的体系结构:基于神经网络的体系结构。特别是,图像分类等任务在很大程度上依赖于卷积神经网络,我们很快就会讨论。

Deep Learning Is Not Just for Image Classification

近年来,深度学习对图像进行分类的有效性得到了广泛讨论,甚至在CT扫描中识别恶性肿瘤等复杂任务中显示了超人的结果。但正如我们将在这里展示的那样,它可以做得更多。

例如,让我们谈谈对自动驾驶汽车至关重要的事情:在图片中定位物体。如果一辆自动驾驶汽车不知道行人在哪里,那么它不知道如何避开行人!创建一个可以识别图像中每个像素内容的模型称为分割。以下是我们如何使用Gabruel J的论文“视频中的语义对象类:高清地面真相数据库”中的Camvid数据集的子集,使用fastai训练分割模型。Brostow、Julien Fauqueur和Roberto Cipolla:

1
2
3
4
5
6
7
8
9
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)

我们甚至不会逐行浏览这个代码,因为它与我们之前的例子几乎完全相同!(尽管我们将深入研究分割模型,以及我们在本章中简要介绍的所有其他模型,以及许多其他模型。)

通过要求模型对图像的每个像素进行颜色编码,我们可以想象它完成任务的程度。如您所见,它几乎完美地对每个对象中的每个像素进行分类。例如,请注意,所有汽车都用相同的颜色覆盖,所有树木都用相同的颜色覆盖(在每对图像中,左侧图像是地面真相标签,右侧是模型的预测):

1
learn.show_results(max_n=6, figsize=(7,8))

在过去几年中,深度学习显著改善的另一个领域是自然语言处理(NLP)。计算机现在可以生成文本,从一种语言自动翻译到另一种语言,分析评论,在句子中标记单词,等等。以下是训练模型所需的所有代码,该模型可以比五年前世界上存在的任何模型更好地分类电影评论的情绪:

1
2
3
4
5
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)

clean

如果您在运行此单元格后遇到“CUDA内存耗尽错误”,请单击菜单内核,然后重新启动。与其执行上面的单元格,不如复制并粘贴以下代码:

1
2
3
4
5
from fastai.text.all import *

dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test', bs=32)
learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5, metrics=accuracy)
learn.fine_tune(4, 1e-2)

这将批处理大小减少到32(我们稍后会对此进行解释)。如果您一直遇到相同的错误,请将32更改为16。

该模型使用Andrew Maas等人论文《Learning Word Vectors for Sentiment Analysis》中的 “IMDb Large Movie Review dataset” 。它适用于数千字的电影评论,但让我们在非常简短的电影评论中进行测试,看看它是如何做到的:

1
2
3
learn.predict("I really liked that movie!")

('neg', tensor(0), tensor([0.8786, 0.1214]))

在这里,我们可以看到模型认为审查是积极的。结果的第二部分是我们数据词汇中的“pos”指数,最后一部分是归因于每个类的概率(“pos”为99.6%,“neg”为0.4%)。

现在轮到你了!写你自己的迷你电影评论,或者从互联网上复制一个,你可以看到这个模型是怎么想的。

Sidebar: The Order Matters

在Jupyter笔记本中,您执行每个单元格的顺序非常重要。它不像Excel,一旦您在任何地方键入内容,一切都会更新——它有一个内部状态,每次执行单元格都会更新。例如,当您运行笔记本电脑的第一个单元格(带有“单击我”注释)时,您创建一个名为 learn 的对象,该对象包含图像分类问题的模型和数据。如果我们直接运行文本中刚刚显示的单元格(预测评论是否好),我们将收到错误,因为此学习对象不包含文本分类模型。此单元格需要在包含以下内容的单元格之后运行:

1
2
3
4
5
6
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 两次将重新启动内核(这是为 notebook 供电的引擎)。这会把你的状态擦干净,就像你刚从笔记本上开始一样。从“单元格”菜单中选择“全部运行上面”,以运行您所在点上方的所有单元格。我们发现这在开发fastai库时非常有用。

End sidebar

如果您对fastai方法有任何疑问,您应该使用函数文档,并传递方法名称:

1
doc(learn.predict)

这将弹出一个小窗口,其中包含以下内容:

文档提供了简短的一行说明。“在文档中显示”链接将带您访问完整的文档,在那里您可以找到所有详细信息和许多示例。此外,fastai的大多数方法只是几行,因此您可以单击 source 链接,以准确查看幕后发生的事情。

让我们继续一些不那么性感,但商业上可能更普遍的东西:根据普通表格数据构建模型。

jargon: 表格:表格形式的数据,例如来自电子表格、数据库或CSV文件的数据。表格模型是一种试图根据表其他列中的信息预测表的一列的模型。

事实证明,这也看起来很相似。以下是训练模型所需的代码,该模型将根据一个人的社会经济背景预测一个人是否是高收入者:

1
2
3
4
5
6
7
8
9
10
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 模型的最常用方法(即没有迁移学习):

1
learn.fit_one_cycle(3)

该模型使用Rob Kohavi的论文《Scaling Up the Accuracy of Naive-Bayes Classifiers: a Decision-Tree Hybrid》中的 Adult dataset,其中包含一些关于个人的人口数据(如他们的教育、婚姻状况、种族、性别,以及他们的年收入是否超过5万美元)。该模型准确率超过80%,训练时间约为30秒。

让我们再看一个。建议系统非常重要,特别是在电子商务中。亚马逊和Netflix等公司努力推荐用户可能喜欢的产品或电影。以下是如何使用MovieLens数据集训练模型,该模型将根据人们之前的观看习惯预测他们可能喜欢的电影:

1
2
3
4
5
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)

该模型预测电影收视率为0.5至5.0,平均误差约为0.6。由于我们预测的是连续数,而不是类别,因此我们必须使用y_range参数告诉fastai我们的目标有多大范围。

虽然我们实际上没有使用预训练模型(原因与我们没有使用表格模型相同),但这个例子表明,fastai无论如何都允许我们在这种情况下使用 fine_tune。有时,最好尝试 fine_tune 与 fit_one_cycle ,看看哪个最适合您的数据集。

我们可以使用之前看到的相同的 show_results 调用来查看一些用户和电影ID、实际评级和预测示例:

1
learn.show_results()

Sidebar: Datasets: Food for Models

在本节中,您已经看到了相当多的模型,每个模型都使用不同的数据集进行训练来完成不同的任务。在机器学习和深度学习中,没有数据我们什么都做不了。因此,为我们训练模型而创建数据集的人是(经常被低估的)英雄。一些最有用和最重要的数据集是那些成为重要学术基线的数据集;即研究人员广泛研究并用于比较算法变化的数据集。其中一些成为家喻户晓的名字(至少在训练模型的家庭中!),如MNIST、CIFAR-10和ImageNet。

本书中使用的数据集之所以被选中,是因为它们提供了您可能会遇到的数据类型的绝佳示例,学术文献中有许多使用这些数据集的模型结果示例,您可以将其进行比较。

这本书中使用的大多数数据集需要创作者做很多工作来构建。例如,在书的后面,我们将向您展示如何创建一个可以在法语和英语之间翻译的模型。这方面的关键输入是宾夕法尼亚大学的Chris Callison-Burch教授早在2009年编写的法语/英语并行文本语料库。该数据集包含超过2000万对法语和英语句子。他以非常聪明的方式构建了数据集:爬行数百万个加拿大网页(通常是多语言的),然后使用一组简单的启发式方法将法语内容的URL转换为指向相同英语内容的URL。

当您查看整本书的数据集时,请思考它们可能来自哪里,以及它们可能是如何策划的。然后想想你可以为自己的项目创建什么样的有趣的数据集。(我们甚至很快就会带您逐步完成创建您自己的图像数据集的过程。)

Fast.ai花费了大量时间创建热门数据集的精简版本,这些数据集专为支持快速原型和实验而设计,并更容易学习。在这本书中,我们通常从使用其中一个删减版本开始,然后扩展到全尺寸版本(就像我们在这一章中所做的那样!)。事实上,这就是世界顶尖从业者在实践中进行建模的方式;他们的大部分实验和原型都是用数据的子集进行的,并且只有在他们很好地理解他们必须做什么时才使用完整的数据集。

End sidebar

我们训练的每个模型都表现出训练和验证损失。良好的验证集是训练过程中最重要的部分之一。让我们看看原因,并学习如何创建一个。

Validation Sets and Test Sets

正如我们所讨论的,模型的目标是对数据进行预测。但模型训练过程从根本上说是愚蠢的。如果我们用我们所有的数据训练一个模型,然后使用相同的数据评估模型,我们将无法判断我们的模型在它没有看到的数据上的表现如何。如果没有这条非常有价值的信息来指导我们训练模型,它很有可能变得善于预测这些数据,但在新数据上表现不佳。

为了避免这种情况,我们的第一步是将我们的数据集分为两组:训练集(我们的模型在训练中看到)和验证集,也称为开发集(仅用于评估)。这让我们测试模型从推广到新数据(验证数据)的训练数据中吸取了经验教训。

了解这种情况的一种方法是,从某种意义上说,我们不希望我们的模型通过“作弊”获得良好结果。如果它对一个数据项进行了准确的预测,那应该是因为它已经了解了此类项的特征,而不是因为模型是通过实际看到该特定项来塑造的。

拆分我们的验证数据意味着我们的模型永远不会在训练中看到它,因此完全没有受到它的污染,并且没有以任何方式作弊。对吗?

事实上,不一定。情况更微妙。这是因为在现实场景中,我们很少仅仅通过训练一次重量参数来构建模型。相反,我们可能会通过有关网络架构、学习率、数据增强策略以及我们将在未来章节中讨论的其他因素的各种建模选择来探索模型的许多版本。其中许多选择可以描述为超参数的选择。这个词反映了它们是关于参数的参数,因为它们是控制权重参数含义的更高层次的选择。

问题在于,即使普通训练过程只在学习权重参数的值时查看训练数据的预测,但我们的情况并非如此。作为建模人员,当我们决定探索新的超参数值时,我们正在通过查看验证数据的预测来评估模型!因此,模型的后续版本是由我们看到验证数据间接塑造的。正如自动训练过程存在过度拟合训练数据的危险一样,我们也存在通过人工试验、错误和探索过度拟合验证数据的危险。

这个难题的解决方案是引入另一个更保守的数据级别,即测试集。正如我们从训练过程中保留验证数据一样,我们必须从自己那里保留测试集数据。它不能用于改进模型;它只能用于在我们努力的最后评估模型。实际上,我们根据我们希望在训练和建模过程中隐藏数据的程度来定义数据的层次结构:训练数据完全暴露,验证数据暴露较少,测试数据完全隐藏。这种层次结构与不同类型的建模和评估过程本身平行——带有反向传播的自动训练过程,在两次训练之间尝试不同超参数的更手动的过程,以及对最终结果的评估。

测试和验证集应该有足够的数据来确保您获得对准确性的良好估计。例如,如果您正在创建猫探测器,您通常希望验证集中至少有30只猫。这意味着,如果您有一个包含数千个项目的数据集,使用默认的20%验证集大小可能超出了您的需求。另一方面,如果您有很多数据,使用其中一些数据进行验证可能没有任何缺点。

拥有两个级别的“保留数据”——一个验证集和一个测试集,一个级别代表您实际上对自己隐瞒的数据——可能看起来有点极端。但这通常是必要的,因为模型倾向于以最简单的方式进行良好的预测(记忆),而我们作为容易犯错的人,倾向于在模型的表现上愚弄自己。测试集的纪律有助于我们在智力上保持诚实。这并不意味着我们总是需要单独的测试集——如果您的数据很少,您可能只需要一个验证集——但如果可能的话,通常最好使用一个。

如果您打算聘请第三方代表您进行建模工作,同一学科可能至关重要。第三方可能不准确理解您的要求,或者他们的激励措施甚至可能会鼓励他们误解这些要求。一套好的测试可以大大降低这些风险,并让您评估他们的工作是否解决了您的实际问题。

坦率地说,如果您是组织中的高级决策者(或您正在为高级决策者提供咨询),最重要的收获是:如果您确保您真正了解什么是测试和验证集以及它们为什么重要,那么您将避免组织决定使用人工智能时我们看到的最大故障来源。例如,如果您正在考虑引入外部供应商或服务,请确保您持有一些供应商从未见过的测试数据。然后,您根据测试数据检查他们的模型,使用您根据实践中对您实际重要的指标选择的指标,并决定性能水平是否足够。(你自己尝试一些简单的基线也是一个好主意,这样你就知道一个真正简单的模型可以实现什么。通常情况下,您的简单模型的性能与外部“专家”生成的模型一样好!)

Use Judgment in Defining Test Sets

为了很好地定义验证集(可能还有测试集),您有时会想做的不仅仅是随机抓取原始数据集的一小部分。请记住:验证和测试集的一个关键属性是,它们必须代表您将来会看到的新数据。这听起来可能是一个不可能的命令!根据定义,您尚未看到这些数据。但你通常仍然知道一些事情。

看看几个例子很有启发性。这些例子中有许多来自Kaggle平台上的预测建模比赛,很好地代表了您可能在实践中看到的问题和方法。

一种情况可能是,如果您正在查看时间序列数据。对于时间序列,选择数据的随机子集既太容易(您可以在您试图预测的日期之前和之后查看数据),也不代表大多数业务用例(您正在使用历史数据构建模型以供将来使用)。如果您的数据包含日期,并且您正在构建模型以供将来使用,则您需要选择一个连续的部分,其中包含最新日期作为验证集(例如,可用数据的最后两周或最后一个月)。

假设您想将下图中的时间序列数据拆分为训练和验证集

正如我们在下图中看到的,随机子集是一个糟糕的选择(太容易填补空白,而不是表明您在生产中需要什么)。

相反,请使用早期数据作为训练集(以及验证集的后期数据),如下图所示。

例如,卡格尔在预测厄瓜多尔连锁杂货店的销售额方面进行了竞赛。Kaggle的训练数据从2013年1月1日持续到2017年8月15日,测试数据从2017年8月16日持续到2017年8月31日。这样,竞赛组织者确保参赛者从他们的模型角度来看,对未来的一段时间做出预测。这类似于量化对冲基金交易员根据过去的数据进行回测以检查其模型是否预测未来时期的方式。

第二个常见情况是,您可以轻松预测您在生产中预测的数据可能与您训练模型的数据在质量上有所不同。

在Kaggle分心驾驶员竞争中,独立变量是驾驶汽车的司机的照片,而依赖变量是发短信、进食或safely looking ahead 等类别。正如我们所看到的,许多照片都是不同位置的相同司机。如果您是一家根据这些数据构建模型的保险公司,请注意,您最感兴趣的是模型在它以前从未见过的司机上的表现(因为您可能只有一小部分人的训练数据)。认识到这一点,比赛的测试数据包括训练集中没有出现的人的图像。

如果您将上图中的一张图像放在训练集中,将一张放在验证集中,您的模型将很容易地预测验证集中的图像,因此它的表现似乎比新手更好。另一种观点是,如果您在训练模型时使用所有人员,您的模型可能过于适合这些特定人群的特殊性,而不仅仅是学习状态(发短信、饮食等)。

Kaggle渔业竞赛也在进行类似的情况,识别渔船捕获的鱼种,从而减少对濒危人口的非法捕捞。测试集由训练数据中没有显示的船只组成。这意味着您希望您的验证集包括不在悬链集中的船只。

有时可能不清楚您的验证数据会有什么不同。例如,对于使用卫星图像的问题,您需要收集更多信息,说明训练集是否仅包含某些地理位置,或者它是否来自地理上分散的数据。

现在你已经尝到了如何构建模型的滋味,你可以决定接下来要深入研究什么。

A Choose Your Own Adventure moment

如果您想了解更多关于在实践中如何使用深度学习模型的信息,包括如何识别和修复错误,创建真正的工作Web应用程序,并避免模型对您的组织或社会造成更普遍的意外伤害,请继续阅读接下来的两章。如果您想开始学习深度学习如何在引擎盖下工作的基础,请跳过。(你小时候读过《选择你自己的冒险》书籍吗?嗯,这有点像那样……除了比那本书系列更深入的学习。)

您需要阅读所有这些章节才能在书中取得进一步进展,但阅读顺序完全取决于您。他们不依赖对方。如果您跳过后面两章,我们将在最后提醒您回来阅读您跳过的章节,然后再继续。