FastAI 之书(面向程序员的 FastAI)(一)(3)

简介: FastAI 之书(面向程序员的 FastAI)(一)(3)

FastAI 之书(面向程序员的 FastAI)(一)(2)https://developer.aliyun.com/article/1482924

图 1-20. 一个糟糕的训练子集

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

图 1-21. 一个好的训练子集

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

第二种常见情况是,当你可以很容易地预见到你将用来训练模型的数据与你将在生产中进行预测的数据可能在质量上有所不同时。

在 Kaggle 分心司机比赛中,自变量是司机在车轮上的照片,因变量是文本、吃东西或安全地向前看等类别。很多照片是同一司机在不同位置的照片,正如我们在图 1-22 中所看到的。如果你是一家保险公司根据这些数据构建模型,注意你最感兴趣的是模型在未见过的司机身上的表现(因为你可能只有一小部分人的训练数据)。为此,比赛的测试数据包括那些在训练集中没有出现的人的图像。

图 1-22. 训练数据中的两张图片

如果你将图 1-22 中的一张图片放入训练集,另一张放入验证集,你的模型将更容易预测验证集中的那张图片,因此它看起来表现得比在新人身上更好。另一个角度是,如果你在训练模型时使用了所有人,你的模型可能会过度拟合这些特定人的特点,而不仅仅是学习状态(发短信、吃东西等)。

Kaggle 渔业比赛中,也存在类似的动态,目的是识别渔船捕捞的鱼类物种,以减少对濒临灭绝种群的非法捕捞。测试集包括来自训练数据中没有出现的船只的图像,因此在这种情况下,你希望你的验证集也包括训练集中没有的船只。

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

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

一个选择你自己的冒险时刻

如果你想了解如何在实践中使用深度学习模型,包括如何识别和修复错误、创建一个真正的工作网络应用程序,并避免你的模型对你的组织或社会造成意外伤害,那么请继续阅读接下来的两章。如果你想开始学习深度学习在幕后是如何工作的基础知识,请跳到第四章。(你小时候有读过选择你自己的冒险系列书吗?嗯,这有点像那个……只不过比那本书系列包含更多的深度学习。)

你需要阅读所有这些章节才能在书中进一步前进,但你阅读它们的顺序完全取决于你。它们不相互依赖。如果你跳到第四章,我们会在最后提醒你回来阅读你跳过的章节,然后再继续前进。

问卷调查

阅读了一页又一页的散文之后,很难知道你真正需要专注和记住的关键事项。因此,我们准备了一份问题列表和建议的步骤清单,供你在每章末完成。所有答案都在章节的文本中,所以如果你对这里的任何事情不确定,重新阅读文本的那部分,并确保你理解了它。所有这些问题的答案也可以在书的网站上找到。如果你遇到困难,也可以访问论坛寻求其他学习这些材料的人的帮助。

  1. 你需要这些来进行深度学习吗?
  • 很多数学 T/F
  • 很多数据 T/F
  • 很多昂贵的电脑 T/F
  • 一个博士学位 T/F
  1. 列出深度学习现在是世界上最好的工具的五个领域。
  2. 第一个基于人工神经元原理的设备的名称是什么?
  3. 根据同名书籍,分布式并行处理(PDP)的要求是什么?
  4. 是什么两个理论误解阻碍了神经网络领域的发展?
  5. 什么是 GPU?
  6. 打开一个笔记本并执行包含:1+1 的单元格。会发生什么?
  7. 跟随本章笔记本的精简版本中的每个单元格。在执行每个单元格之前,猜测会发生什么。
  8. 完成Jupyter Notebook 在线附录
  9. 为什么使用传统计算机程序来识别照片中的图像很困难?
  10. 塞缪尔所说的“权重分配”是什么意思?
  11. 在深度学习中,我们通常用什么术语来表示塞缪尔所说的“权重”?
  12. 画一幅总结塞缪尔对机器学习模型看法的图片。
  13. 为什么很难理解深度学习模型为什么会做出特定的预测?
  14. 展示了一个定理的名称,该定理表明神经网络可以解决任何数学问题并达到任何精度水平是什么?
  15. 为了训练模型,您需要什么?
  16. 反馈循环如何影响预测性警务模型的推出?
  17. 我们在猫识别模型中总是需要使用 224×224 像素的图像吗?
  18. 分类和回归之间有什么区别?
  19. 什么是验证集?什么是测试集?为什么我们需要它们?
  20. 如果不提供验证集,fastai 会怎么做?
  21. 我们总是可以使用随机样本作为验证集吗?为什么或为什么不?
  22. 什么是过拟合?举个例子。
  23. 什么是度量?它与损失有什么不同?
  24. 预训练模型如何帮助?
  25. 模型的“头”是什么?
  26. CNN 的早期层找到了什么样的特征?后期层呢?
  27. 图像模型仅对照片有用吗?
  28. 什么是架构?
  29. 什么是分割?
  30. y_range 用于什么?什么时候需要它?
  31. 什么是超参数?
  32. 在组织中使用 AI 时避免失败的最佳方法是什么?

进一步研究

每章还有一个“进一步研究”部分,提出了一些在文本中没有完全回答的问题,或者给出了更高级的任务。这些问题的答案不在书的网站上;您需要自己进行研究!

  1. 为什么 GPU 对深度学习有用?CPU 有什么不同之处,为什么对深度学习效果不佳?
  2. 试着想出三个反馈循环可能影响机器学习使用的领域。看看是否能找到实践中发生这种情况的文档示例。

第二章:从模型到生产

原文:www.bookstack.cn/read/th-fastai-book/fc07273d062b4173.md

译者:飞龙

协议:CC BY-NC-SA 4.0

我们在第一章中看到的六行代码只是在实践中使用深度学习过程的一小部分。在本章中,我们将使用一个计算机视觉示例来查看创建深度学习应用的端到端过程。更具体地说,我们将构建一个熊分类器!在这个过程中,我们将讨论深度学习的能力和限制,探讨如何创建数据集,在实践中使用深度学习时可能遇到的问题等等。许多关键点同样适用于其他深度学习问题,例如第一章中的问题。如果您解决的问题在关键方面类似于我们的示例问题,我们期望您可以快速获得极好的结果,而只需很少的代码。

让我们从如何构建您的问题开始。

深度学习的实践

我们已经看到深度学习可以快速解决许多具有挑战性的问题,并且只需很少的代码。作为初学者,有一些问题与我们的示例问题足够相似,以便您可以非常快速地获得极其有用的结果。然而,深度学习并不是魔法!同样的六行代码不会适用于今天任何人可以想到的每个问题。

低估深度学习的限制并高估其能力可能导致令人沮丧的糟糕结果,至少在您获得一些经验并能解决出现的问题之前。相反,高估深度学习的限制并低估其能力可能意味着您不会尝试可解决的问题,因为您自己否定了它。

我们经常与低估深度学习的限制和能力的人交谈。这两者都可能是问题:低估能力意味着您可能甚至不会尝试可能非常有益的事情,而低估限制可能意味着您未能考虑和应对重要问题。

最好的做法是保持开放的心态。如果您对深度学习可能以比您预期的更少的数据或复杂性解决部分问题持开放态度,您可以设计一个过程,通过该过程您可以找到与您特定问题相关的特定能力和限制。这并不意味着进行任何冒险的赌注-我们将向您展示如何逐渐推出模型,以便它们不会带来重大风险,并且甚至可以在投入生产之前对其进行回测。

开始您的项目

那么您应该从哪里开始深度学习之旅呢?最重要的是确保您有一个要处理的项目-只有通过处理自己的项目,您才能获得构建和使用模型的真实经验。在选择项目时,最重要的考虑因素是数据的可用性。

无论您是为了自己的学习还是为了在组织中的实际应用而进行项目,您都希望能够快速开始。我们看到许多学生、研究人员和行业从业者在试图找到他们完美的数据集时浪费了几个月甚至几年的时间。目标不是找到“完美”的数据集或项目,而只是开始并从那里迭代。如果您采取这种方法,您将在完美主义者仍处于规划阶段时进行第三次迭代学习和改进!

我们还建议您在项目中端到端迭代;不要花几个月来微调您的模型,或打磨完美的 GUI,或标记完美的数据集……相反,尽可能在合理的时间内完成每一步,一直到最后。例如,如果您的最终目标是一个在手机上运行的应用程序,那么每次迭代后您都应该拥有这个。但也许在早期迭代中您会采取捷径;例如,在远程服务器上进行所有处理,并使用简单的响应式 Web 应用程序。通过完成项目的端到端,您将看到最棘手的部分在哪里,以及哪些部分对最终结果产生最大影响。

当您阅读本书时,我们建议您完成许多小实验,通过运行和调整我们提供的笔记本,同时逐渐开发自己的项目。这样,您将获得所有我们解释的工具和技术的经验,同时我们讨论它们。

Sylvain 说

为了充分利用这本书,花时间在每一章之间进行实验,无论是在您自己的项目上还是通过探索我们提供的笔记本。然后尝试在新数据集上从头开始重写这些笔记本。只有通过大量练习(和失败),您才能培养出如何训练模型的直觉。

通过使用端到端迭代方法,您还将更好地了解您实际需要多少数据。例如,您可能会发现您只能轻松获得 200 个标记数据项,而在尝试之前,您无法真正知道这是否足以使您的应用在实践中良好运行。

在组织环境中,您可以通过展示一个真实的工作原型来向同事展示您的想法是可行的。我们反复观察到,这是获得项目良好组织支持的秘诀。

由于最容易开始的项目是您已经有数据可用的项目,这意味着最容易开始的项目可能与您已经在做的事情相关,因为您已经有关于您正在做的事情的数据。例如,如果您在音乐行业工作,您可能可以访问许多录音。如果您是放射科医生,您可能可以访问大量医学图像。如果您对野生动物保护感兴趣,您可能可以访问大量野生动物图像。

有时您必须有点创造性。也许您可以找到一个先前的机器学习项目,比如一个与您感兴趣的领域相关的 Kaggle 竞赛。有时您必须做出妥协。也许您找不到您所需的确切数据来完成您心中的项目;但您可能会找到一些来自类似领域的数据,或者以不同方式测量的数据,解决一个略有不同的问题。在这些类似项目上工作仍然会让您对整个过程有很好的理解,并可能帮助您识别其他捷径、数据来源等。

特别是当您刚开始学习深度学习时,最好不要涉足非常不同的领域,不要涉足深度学习之前未应用的领域。因为如果您的模型一开始就不起作用,您将不知道是因为您犯了错误,还是您试图解决的问题根本无法用深度学习解决。您也不知道从哪里寻求帮助。因此,最好首先找到在线的一个例子,该例子已经取得了良好的结果,并且至少与您尝试实现的目标有些相似,通过将您的数据转换为其他人以前使用过的格式(例如从您的数据创建图像)。让我们看看深度学习的现状,这样您就知道深度学习目前擅长的领域。

深度学习的现状

让我们首先考虑深度学习是否能够解决您要解决的问题。本节概述了 2020 年初深度学习的现状。然而,事情发展得非常快,当您阅读本文时,其中一些限制可能已经不存在。我们将尽力保持本书网站的最新信息;此外,搜索“AI 现在能做什么”可能会提供当前信息。

计算机视觉

深度学习尚未用于分析图像的许多领域,但在已经尝试过的领域中,几乎普遍表明计算机可以至少与人类一样好地识别图像中的物品,甚至是经过专门训练的人,如放射科医生。这被称为物体识别。深度学习还擅长识别图像中物体的位置,并可以突出它们的位置并命名每个找到的物体。这被称为物体检测(在我们在第一章中看到的变体中,每个像素根据其所属的对象类型进行分类—这被称为分割)。

深度学习算法通常不擅长识别结构或风格与用于训练模型的图像明显不同的图像。例如,如果训练数据中没有黑白图像,模型可能在黑白图像上表现不佳。同样,如果训练数据不包含手绘图像,模型可能在手绘图像上表现不佳。没有一般方法可以检查训练集中缺少哪些类型的图像,但我们将在本章中展示一些方法,以尝试识别当模型在生产中使用时数据中出现意外图像类型的情况(这被称为检查域外数据)。

物体检测系统面临的一个主要挑战是图像标记可能会很慢且昂贵。目前有很多工作正在进行中,旨在开发工具以尝试使这种标记更快速、更容易,并且需要更少的手工标签来训练准确的物体检测模型。一个特别有帮助的方法是合成生成输入图像的变化,例如通过旋转它们或改变它们的亮度和对比度;这被称为数据增强,并且对文本和其他类型的模型也很有效。我们将在本章中详细讨论这一点。

另一个要考虑的问题是,尽管您的问题可能看起来不像是一个计算机视觉问题,但通过一点想象力可能可以将其转变为一个。例如,如果您要分类的是声音,您可以尝试将声音转换为其声学波形的图像,然后在这些图像上训练模型。

自然语言处理

计算机擅长基于类别对短文档和长文档进行分类,例如垃圾邮件或非垃圾邮件、情感(例如,评论是积极的还是消极的)、作者、来源网站等。我们不知道在这个领域是否有任何严格的工作来比较计算机和人类,但从经验上看,我们认为深度学习的性能在这些任务上与人类的性能相似。

深度学习还擅长生成与上下文相关的文本,例如回复社交媒体帖子,并模仿特定作者的风格。它还擅长使这些内容对人类具有吸引力—事实上,甚至比人类生成的文本更具吸引力。然而,深度学习不擅长生成正确的回应!例如,我们没有可靠的方法来将医学信息知识库与深度学习模型结合起来,以生成医学上正确的自然语言回应。这是危险的,因为很容易创建对外行人看来具有吸引力但实际上完全不正确的内容。

另一个问题是,社交媒体上的上下文适当、高度引人入胜的回应可能被大规模使用——比以前见过的任何喷子农场规模大几千倍——来传播虚假信息,制造动荡,鼓励冲突。一般来说,文本生成模型总是在技术上略领先于识别自动生成文本的模型。例如,可以使用一个能够识别人工生成内容的模型来实际改进创建该内容的生成器,直到分类模型无法完成其任务为止。

尽管存在这些问题,深度学习在自然语言处理中有许多应用:可以用来将文本从一种语言翻译成另一种语言,将长篇文档总结为更快消化的内容,找到感兴趣概念的所有提及等。不幸的是,翻译或总结可能包含完全错误的信息!然而,性能已经足够好,许多人正在使用这些系统——例如,谷歌的在线翻译系统(以及我们所知道的每个其他在线服务)都是基于深度学习的。

结合文本和图像

深度学习将文本和图像结合成一个单一模型的能力通常比大多数人直觉期望的要好得多。例如,一个深度学习模型可以在输入图像上进行训练,输出用英语编写的标题,并且可以学会为新图像自动生成令人惊讶地适当的标题!但是,我们再次提出与前一节讨论的相同警告:不能保证这些标题是正确的。

由于这个严重问题,我们通常建议深度学习不要作为完全自动化的过程,而是作为模型和人类用户密切互动的过程的一部分。这可能使人类的生产力比完全手动方法高出几个数量级,并且比仅使用人类更准确。

例如,自动系统可以直接从 CT 扫描中识别潜在的中风患者,并发送高优先级警报,以便快速查看这些扫描。治疗中风只有三个小时的时间窗口,因此这种快速的反馈循环可以挽救生命。同时,所有扫描仍然可以按照通常的方式发送给放射科医生,因此不会减少人类的参与。其他深度学习模型可以自动测量扫描中看到的物品,并将这些测量结果插入报告中,警告放射科医生可能错过的发现,并告诉他们可能相关的其他病例。

表格数据

对于分析时间序列和表格数据,深度学习最近取得了巨大进展。然而,深度学习通常作为多种模型集成的一部分使用。如果您已经有一个正在使用随机森林或梯度提升机(流行的表格建模工具,您很快将了解)的系统,那么切换到或添加深度学习可能不会带来任何显著的改进。

深度学习确实大大增加了您可以包含的列的种类——例如,包含自然语言(书名、评论等)和高基数分类列(即包含大量离散选择的内容,如邮政编码或产品 ID)。不过,与随机森林或梯度提升机相比,深度学习模型通常需要更长的训练时间,尽管由于提供 GPU 加速的库(如RAPIDS),情况正在改变。我们在第九章中详细介绍了所有这些方法的优缺点。

推荐系统

推荐系统实际上只是一种特殊类型的表格数据。特别是,它们通常具有代表用户的高基数分类变量,以及代表产品(或类似物品)的另一个变量。像亚马逊这样的公司将客户所做的每一次购买都表示为一个巨大的稀疏矩阵,其中客户是行,产品是列。一旦他们以这种格式拥有数据,数据科学家们会应用某种形式的协同过滤来填充矩阵。例如,如果客户 A 购买产品 1 和 10,客户 B 购买产品 1、2、4 和 10,引擎将推荐 A 购买 2 和 4。

由于深度学习模型擅长处理高基数分类变量,它们非常擅长处理推荐系统。尤其是当将这些变量与其他类型的数据(如自然语言或图像)结合时,它们就像处理表格数据一样发挥作用。它们还可以很好地将所有这些类型的信息与其他元数据(如用户信息、先前交易等)表示为表格进行组合。

然而,几乎所有的机器学习方法都有一个缺点,那就是它们只告诉你一个特定用户可能喜欢哪些产品,而不是对用户有用的推荐。用户可能喜欢的产品的许多种推荐可能根本不会有任何帮助——例如,如果用户已经熟悉这些产品,或者如果它们只是用户已经购买过的产品的不同包装(例如,当他们已经拥有该套装中的每一件物品时,推荐一个小说的套装)。Jeremy 喜欢读特里·普拉切特的书,有一段时间亚马逊一直在向他推荐特里·普拉切特的书(见图 2-1),这实际上并不是有用的,因为他已经知道这些书了!

图 2-1. 一个不太有用的推荐

其他数据类型

通常,您会发现特定领域的数据类型非常适合现有的类别。例如,蛋白质链看起来很像自然语言文档,因为它们是由复杂关系和意义贯穿整个序列的离散令牌组成的长序列。事实上,使用 NLP 深度学习方法是许多类型蛋白质分析的最先进方法。另一个例子,声音可以表示为频谱图,可以被视为图像;标准的图像深度学习方法在频谱图上表现得非常好。

驱动系统方法

许多准确的模型对任何人都没有用,而许多不准确的模型却非常有用。为了确保您的建模工作在实践中有用,您需要考虑您的工作将如何使用。2012 年,Jeremy 与 Margit Zwemer 和 Mike Loukides 一起提出了一种称为驱动系统方法的思考这个问题的方法。

驱动系统方法,如图 2-2 所示,详细介绍在“设计出色的数据产品”中。基本思想是从考虑您的目标开始,然后考虑您可以采取哪些行动来实现该目标以及您拥有的(或可以获取的)可以帮助的数据,然后构建一个模型,您可以使用该模型确定为实现目标而采取的最佳行动。

图 2-2. 驱动系统方法

考虑自动驾驶汽车中的模型:您希望帮助汽车安全地从 A 点驾驶到 B 点,而无需人为干预。出色的预测建模是解决方案的重要组成部分,但它并不是独立存在的;随着产品变得更加复杂,它会消失在管道中。使用自动驾驶汽车的人完全不知道使其运行的数百(甚至数千)个模型和海量数据。但随着数据科学家构建越来越复杂的产品,他们需要一种系统化的设计方法。

我们使用数据不仅仅是为了生成更多数据(以预测的形式),而是为了产生可操作的结果。这是 Drivetrain 方法的目标。首先要明确定义一个明确的目标。例如,当谷歌创建其第一个搜索引擎时,考虑了“用户在输入搜索查询时的主要目标是什么?”这导致了谷歌的目标,即“显示最相关的搜索结果”。下一步是考虑您可以拉动的杠杆(即您可以采取的行动)以更好地实现该目标。在谷歌的情况下,这是搜索结果的排名。第三步是考虑他们需要什么新数据来生成这样的排名;他们意识到关于哪些页面链接到哪些其他页面的隐含信息可以用于此目的。

只有在完成了这前三个步骤之后,我们才开始考虑构建预测模型。我们的目标和可用的杠杆,我们已经拥有的数据以及我们需要收集的额外数据,决定了我们可以构建的模型。这些模型将以杠杆和任何不可控变量作为输入;模型的输出可以结合起来预测我们的目标的最终状态。

让我们考虑另一个例子:推荐系统。推荐引擎的目标是通过推荐客户不会在没有推荐的情况下购买的物品来推动额外的销售。杠杆是推荐的排名。必须收集新数据以生成将导致新销售的推荐。这将需要进行许多随机实验,以收集关于各种客户的各种推荐的数据。这是很少有组织采取的一步;但是没有它,您就没有所需的信息来根据您的真正目标(更多销售!)优化推荐。

最后,您可以为购买概率构建两个模型,条件是看到或没有看到推荐。这两个概率之间的差异是给定推荐给客户的效用函数。在算法推荐客户已经拒绝的熟悉书籍(两个组成部分都很小)或者他们本来就会购买的书籍(两个组成部分都很大并互相抵消)的情况下,效用函数会很低。

正如您所看到的,在实践中,您的模型的实际实施通常需要比仅仅训练一个模型更多!您通常需要运行实验来收集更多数据,并考虑如何将您的模型整合到您正在开发的整个系统中。说到数据,现在让我们专注于如何为您的项目找到数据。

收集数据

对于许多类型的项目,您可能能够在线找到所需的所有数据。本章中我们将完成的项目是一个“熊探测器”。它将区分三种类型的熊:灰熊、黑熊和泰迪熊。互联网上有许多每种类型熊的图片可供我们使用。我们只需要找到它们并下载它们。

我们提供了一个工具供您使用,这样您就可以跟随本章并为您感兴趣的任何对象创建自己的图像识别应用程序。在 fast.ai 课程中,成千上万的学生在课程论坛上展示了他们的作品,展示了从特立尼达的蜂鸟品种到巴拿马的公交车类型的一切——甚至有一名学生创建了一个应用程序,可以帮助他的未婚妻在圣诞假期期间认出他的 16 个表兄弟!

在撰写本文时,Bing 图像搜索是我们知道的用于查找和下载图像的最佳选择。每月免费提供最多 1,000 次查询,每次查询可下载最多 150 张图片。然而,在我们撰写本书时和您阅读本书时之间可能会出现更好的选择,因此请务必查看本书籍网站以获取我们当前的推荐。

与最新服务保持联系

用于创建数据集的服务时常变化,它们的功能、接口和定价也经常变化。在本节中,我们将展示如何在撰写本书时作为 Azure 认知服务一部分提供的Bing 图像搜索 API

要使用 Bing 图像搜索下载图像,请在 Microsoft 注册一个免费帐户。您将获得一个密钥,您可以将其复制并输入到一个单元格中(用您的密钥替换*XXX*并执行):

key = 'XXX'

或者,如果您在命令行上感到自在,您可以在终端中设置它

export AZURE_SEARCH_KEY=*your_key_here*

然后重新启动 Jupyter 服务器,在一个单元格中键入以下内容,并执行:

key = os.environ['AZURE_SEARCH_KEY']

设置了key之后,您可以使用search_images_bing。这个函数是在线笔记本中包含的小utils类提供的(如果您不确定一个函数是在哪里定义的,您可以在笔记本中输入它来找出,如下所示):

search_images_bing
<function utils.search_images_bing(key, term, min_sz=128)>

让我们尝试一下这个函数:

results = search_images_bing(key, 'grizzly bear')
ims = results.attrgot('content_url')
len(ims)
150

我们已成功下载了 150 只灰熊的 URL(或者至少是 Bing 图像搜索为该搜索词找到的图像)。让我们看一个:

dest = 'images/grizzly.jpg'
download_url(ims[0], dest)
im = Image.open(dest)
im.to_thumb(128,128)

这似乎运行得很好,所以让我们使用 fastai 的download_images来下载每个搜索词的所有 URL。我们将每个放在一个单独的文件夹中:

bear_types = 'grizzly','black','teddy'
path = Path('bears')
if not path.exists():
    path.mkdir()
    for o in bear_types:
        dest = (path/o)
        dest.mkdir(exist_ok=True)
        results = search_images_bing(key, f'{o} bear')
        download_images(dest, urls=results.attrgot('content_url'))

我们的文件夹中有图像文件,正如我们所期望的那样:

fns = get_image_files(path)
fns
(#421) [Path('bears/black/00000095.jpg'),Path('bears/black/00000133.jpg'),Path('
 > bears/black/00000062.jpg'),Path('bears/black/00000023.jpg'),Path('bears/black
 > /00000029.jpg'),Path('bears/black/00000094.jpg'),Path('bears/black/00000124.j
 > pg'),Path('bears/black/00000056.jpeg'),Path('bears/black/00000046.jpg'),Path(
 > 'bears/black/00000045.jpg')...]

Jeremy 说

我就是喜欢在 Jupyter 笔记本中工作的这一点!逐步构建我想要的东西并在每一步检查我的工作是如此容易。我犯了很多错误,所以这对我真的很有帮助。

通常当我们从互联网下载文件时,会有一些文件损坏。让我们检查一下:

failed = verify_images(fns)
failed
(#0) []

要删除所有失败的图像,您可以使用unlink。像大多数返回集合的 fastai 函数一样,verify_images返回一个类型为L的对象,其中包括map方法。这会在集合的每个元素上调用传递的函数:

failed.map(Path.unlink);

在这个过程中要注意的一件事是:正如我们在第一章中讨论的,模型只能反映用于训练它们的数据。而世界充满了有偏见的数据,这最终会反映在,例如,Bing 图像搜索(我们用来创建数据集的)。例如,假设您有兴趣创建一个应用程序,可以帮助用户确定他们是否拥有健康的皮肤,因此您训练了一个模型,该模型基于搜索结果(比如)“健康皮肤”。图 2-3 展示了您将获得的结果类型。

图 2-3. 用于健康皮肤检测器的数据?

使用此作为训练数据,您最终不会得到一个健康皮肤检测器,而是一个年轻白人女性触摸她的脸检测器!一定要仔细考虑您可能在应用程序中实际看到的数据类型,并仔细检查以确保所有这些类型都反映在您模型的源数据中。(感谢 Deb Raji 提出了健康皮肤的例子。请查看她的论文“可操作的审计:调查公开命名商业 AI 产品偏见性能结果的影响”以获取更多有关模型偏见的迷人见解。)

现在我们已经下载了一些数据,我们需要将其组装成适合模型训练的格式。在 fastai 中,这意味着创建一个名为DataLoaders的对象。

从数据到数据加载器

DataLoaders是一个简单的类,只是存储您传递给它的DataLoader对象,并将它们作为trainvalid可用。尽管它是一个简单的类,但在 fastai 中非常重要:它为您的模型提供数据。DataLoaders中的关键功能仅用这四行代码提供(它还有一些其他次要功能我们暂时跳过):

class DataLoaders(GetAttr):
    def __init__(self, *loaders): self.loaders = loaders
    def __getitem__(self, i): return self.loaders[i]
    train,valid = add_props(lambda i,self: self[i])

术语:DataLoaders

一个 fastai 类,存储您传递给它的多个DataLoader对象——通常是一个train和一个valid,尽管可以有任意数量。前两个作为属性提供。

在本书的后面,您还将了解DatasetDatasets类,它们具有相同的关系。要将我们下载的数据转换为DataLoaders对象,我们至少需要告诉 fastai 四件事:

  • 我们正在处理什么类型的数据
  • 如何获取项目列表
  • 如何为这些项目打标签
  • 如何创建验证集

到目前为止,我们已经看到了一些特定组合的工厂方法,当您有一个应用程序和数据结构恰好适合这些预定义方法时,这些方法非常方便。当您不适用时,fastai 有一个名为数据块 API的极其灵活的系统。使用此 API,您可以完全自定义创建DataLoaders的每个阶段。这是我们需要为刚刚下载的数据集创建DataLoaders的步骤:

bears = DataBlock(
    blocks=(ImageBlock, CategoryBlock),
    get_items=get_image_files,
    splitter=RandomSplitter(valid_pct=0.2, seed=42),
    get_y=parent_label,
    item_tfms=Resize(128))

让我们依次查看每个参数。首先,我们提供一个元组,指定我们希望独立变量和因变量的类型:

blocks=(ImageBlock, CategoryBlock)

独立变量是我们用来进行预测的东西,因变量是我们的目标。在这种情况下,我们的独立变量是一组图像,我们的因变量是每个图像的类别(熊的类型)。在本书的其余部分中,我们将看到许多其他类型的块。

对于这个DataLoaders,我们的基础项目将是文件路径。我们必须告诉 fastai 如何获取这些文件的列表。get_image_files函数接受一个路径,并返回该路径中所有图像的列表(默认情况下递归):

get_items=get_image_files

通常,您下载的数据集已经定义了验证集。有时,这是通过将用于训练和验证集的图像放入不同的文件夹中来完成的。有时,这是通过提供一个 CSV 文件,在该文件中,每个文件名都与应该在其中的数据集一起列出。有许多可以完成此操作的方法,fastai 提供了一种通用方法,允许您使用其预定义类之一或编写自己的类。

在这种情况下,我们希望随机拆分我们的训练和验证集。但是,我们希望每次运行此笔记本时都具有相同的训练/验证拆分,因此我们固定随机种子(计算机实际上不知道如何创建随机数,而只是创建看起来随机的数字列表;如果您每次都为该列表提供相同的起始点——称为种子,那么您将每次都获得完全相同的列表)。

splitter=RandomSplitter(valid_pct=0.2, seed=42)

自变量通常被称为x,因变量通常被称为y。在这里,我们告诉 fastai 要调用哪个函数来创建数据集中的标签:

get_y=parent_label

parent_label是 fastai 提供的一个函数,它简单地获取文件所在文件夹的名称。因为我们将每个熊图像放入基于熊类型的文件夹中,这将为我们提供所需的标签。

我们的图像大小各不相同,这对深度学习是一个问题:我们不是一次向模型提供一个图像,而是多个图像(我们称之为mini-batch)。为了将它们分组到一个大数组(通常称为张量)中,以便通过我们的模型,它们都需要是相同的大小。因此,我们需要添加一个转换,将这些图像调整为相同的大小。Item transforms是在每个单独项目上运行的代码片段,无论是图像、类别还是其他。fastai 包含许多预定义的转换;我们在这里使用Resize转换,并指定大小为 128 像素:

item_tfms=Resize(128)

这个命令给了我们一个DataBlock对象。这就像创建DataLoaders模板。我们仍然需要告诉 fastai 我们数据的实际来源——在这种情况下,图像所在的路径:

dls = bears.dataloaders(path)

DataLoaders包括验证和训练DataLoaderDataLoader是一个类,它一次向 GPU 提供几个项目的批次。我们将在下一章中更多地了解这个类。当您循环遍历DataLoader时,fastai 会一次给您 64 个(默认值)项目,全部堆叠到一个单一张量中。我们可以通过在DataLoader上调用show_batch方法来查看其中一些项目:

dls.valid.show_batch(max_n=4, nrows=1)

默认情况下,Resize会将图像裁剪成适合请求大小的正方形形状,使用完整的宽度或高度。这可能会导致丢失一些重要细节。或者,您可以要求 fastai 用零(黑色)填充图像,或者压缩/拉伸它们:

bears = bears.new(item_tfms=Resize(128, ResizeMethod.Squish))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=4, nrows=1)

bears = bears.new(item_tfms=Resize(128, ResizeMethod.Pad, pad_mode='zeros'))
dls = bears.dataloaders(path)
dls.valid.show_batch(max_n=4, nrows=1)

所有这些方法似乎都有些浪费或问题。如果我们压缩或拉伸图像,它们最终会变成不现实的形状,导致模型学习到事物看起来与实际情况不同,这会导致更低的准确性。如果我们裁剪图像,我们会移除一些允许我们进行识别的特征。例如,如果我们试图识别狗或猫的品种,我们可能会裁剪掉区分相似品种所需的身体或面部的关键部分。如果我们填充图像,就会有很多空白空间,这对我们的模型来说只是浪费计算,并导致我们实际使用的图像部分具有较低的有效分辨率。

相反,我们在实践中通常做的是随机选择图像的一部分,然后裁剪到该部分。在每个纪元(即数据集中所有图像的完整遍历),我们随机选择每个图像的不同部分。这意味着我们的模型可以学习关注和识别图像中的不同特征。这也反映了图像在现实世界中的工作方式:同一物体的不同照片可能以略有不同的方式构图。

事实上,一个完全未经训练的神经网络对图像的行为一无所知。它甚至不认识当一个物体旋转一度时,它仍然是同一物体的图片!因此,通过训练神经网络使用物体在略有不同位置并且大小略有不同的图像的示例,有助于它理解物体的基本概念,以及如何在图像中表示它。

这里是另一个示例,我们将Resize替换为RandomResizedCrop,这是提供刚才描述行为的转换。传递的最重要参数是min_scale,它确定每次选择图像的最小部分:

bears = bears.new(item_tfms=RandomResizedCrop(128, min_scale=0.3))
dls = bears.dataloaders(path)
dls.train.show_batch(max_n=4, nrows=1, unique=True)

在这里,我们使用了unique=True,以便将相同图像重复使用不同版本的RandomResizedCrop变换。

RandomResizedCrop是更一般的数据增强技术的一个具体示例。

FastAI 之书(面向程序员的 FastAI)(一)(4)https://developer.aliyun.com/article/1482927

相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
1月前
|
机器学习/深度学习 PyTorch 程序员
FastAI 之书(面向程序员的 FastAI)(二)(4)
FastAI 之书(面向程序员的 FastAI)(二)(4)
41 2
|
1月前
|
机器学习/深度学习 PyTorch 程序员
FastAI 之书(面向程序员的 FastAI)(二)(3)
FastAI 之书(面向程序员的 FastAI)(二)(3)
58 2
|
1月前
|
机器学习/深度学习 算法 程序员
FastAI 之书(面向程序员的 FastAI)(三)(4)
FastAI 之书(面向程序员的 FastAI)(三)(4)
46 2
|
1月前
|
机器学习/深度学习 算法 数据挖掘
FastAI 之书(面向程序员的 FastAI)(四)(4)
FastAI 之书(面向程序员的 FastAI)(四)
62 1
|
1月前
|
机器学习/深度学习 PyTorch 程序员
FastAI 之书(面向程序员的 FastAI)(三)(2)
FastAI 之书(面向程序员的 FastAI)(三)(2)
67 2
|
1月前
|
机器学习/深度学习 自然语言处理 程序员
FastAI 之书(面向程序员的 FastAI)(三)(1)
FastAI 之书(面向程序员的 FastAI)(三)(1)
44 2
|
1月前
|
PyTorch 程序员 API
FastAI 之书(面向程序员的 FastAI)(三)(3)
FastAI 之书(面向程序员的 FastAI)(三)(3)
40 2
|
1月前
|
搜索推荐 PyTorch 程序员
FastAI 之书(面向程序员的 FastAI)(四)(1)
FastAI 之书(面向程序员的 FastAI)(四)
34 0
|
1月前
|
机器学习/深度学习 存储 程序员
FastAI 之书(面向程序员的 FastAI)(一)(4)
FastAI 之书(面向程序员的 FastAI)(一)(4)
37 0
|
1月前
|
机器学习/深度学习 搜索推荐 算法
FastAI 之书(面向程序员的 FastAI)(四)(2)
FastAI 之书(面向程序员的 FastAI)(四)
70 0