Python-数据扩充-全-

Python 数据扩充(全)

原文:annas-archive.org/md5/2766659fe3db9ab25bc76eb90bd568a6

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

通过利用真实世界的数据集,释放数据增强在人工智能和生成性人工智能中的强大功能。使用超过 150 种完全功能的面向对象方法和开源库,提高模型的准确性,扩展图像、文本、音频和表格数据。

本书适合谁阅读

本书面向有兴趣学习人工智能领域的个人,包括数据科学家和学生。虽然不要求具备高级的人工智能或深度学习技能,但需要熟悉 Python 编程和 Jupyter 笔记本。

本书内容

第一章数据增强轻松学,是数据增强的入门篇。读者将了解数据增强的定义、数据类型及其好处。此外,读者将学习如何选择合适的在线 Jupyter Python 笔记本或在本地安装它。最后,第一章将以讨论编码规范、GitHub 访问权限和面向对象类代码基础(名为 Pluto)结束。

第二章数据增强中的偏差,定义了计算偏差、人为偏差和系统性偏差,并通过大量现实世界的例子来说明这些偏差类型之间的区别。读者将有机会通过下载三个现实世界的图像数据集和两个文本数据集(来自 Kaggle 网站)来实践识别数据偏差,从而加强他们的学习。一旦下载完成,读者将学习如何显示图像和文本批次,并讨论数据中可能存在的偏差。

第三章用于分类的图像增强,分为两个部分。首先,读者将学习图像分类增强的概念和技术,接着通过 Python 编程进行实践,并详细解释带有安全图像失真水*的图像增强方法。到本章结束时,读者将学习使用六个实际图像数据集进行分类图像增强的概念和 Python 编程技巧。此外,他们将研究几个用于图像增强的 Python 开源库,并使用所选库编写 Python 包装函数。

第四章用于分割的图像增强,强调了图像分割和图像分类是计算机视觉领域的关键组成部分。图像分割涉及将属于同一物体的图像部分分组,也称为像素级分类。与图像分类不同,后者识别和预测照片的主题或标签,图像分割则确定某个像素是否属于某个对象或标签的列表。分割或分类的图像增强方法是相同的,除了分割额外带有一个掩码或真值图像。第四章旨在为图像分割提供持续的几何和光度变换。

第五章文本增强,探讨了文本增强,这是一种在自然语言处理(NLP)中使用的技术,通过修改或从现有文本数据创建新文本来生成额外的数据。文本增强可以涉及诸如字符交换、噪声注入、同义词替换、单词删除、单词插入和单词交换等技术。图像和文本增强的目标相同。它们都致力于增加训练数据集的大小,并提高 AI 的预测准确性。在第五章中,你将学习文本增强以及如何在 Python Notebooks 中编写这些方法。

第六章基于机器学习的文本增强,讨论了一种旨在提高机器学习模型准确性的先进技术。有趣的是,文本增强使用预训练的机器学习模型来创建额外的训练 NLP 数据,从而形成一个循环过程。尽管机器学习编程超出了本书的范围,但理解使用库与使用机器学习进行文本增强的区别是有益的。第六章将讲解如何通过机器学习进行文本增强。

第七章音频数据增强,解释了类似于图像和文本增强,音频增强的目标是扩展数据集,以便在生成式 AI 系统中获得更高的准确度预测或预报。当获取额外的音频文件昂贵或耗时时,音频增强是一种具有成本效益且可行的选项。编写音频增强方法面临独特的挑战。第一个问题是音频不像图像或文本那样是可视的。如果格式是有声书、网页或移动应用程序,我们播放声音,但载体是纸张。因此,我们将把音频信号转换为可视化表示。第六章将涵盖通过波形变换进行音频增强。你可以在 Python Notebook 上播放音频文件。

第八章使用谱图进行音频数据增强,基于上一章关于音频增强的主题,通过探索除了波形图之外的其他可视化方法来扩展内容。音频谱图是另一种可视化方法,用来查看音频的组成部分。谱图的输入是一个一维的振幅值数组和采样率,它们与波形图的输入相同。音频谱图有时也被称为声谱图、声纹图、声波图或音频指纹。它的典型用途包括音乐、人类语音和声纳。简短的标准定义是频谱图和时间持续度的组合。换句话说,Y 轴表示频率(单位为 Hz 或 kHz),X 轴表示时间持续度(单位为秒或毫秒)。第八章将涵盖音频谱图的标准格式、谱图的变化、梅尔频谱图、色度短时傅里叶变换(STFT)和增强技术。

第九章表格数据增强,涉及从数据库、电子表格或表格格式中提取数据,并将其扩展到 AI 训练周期中。目标是提高预测或预测结果的准确性,这与图像、文本和音频增强的目标相同。表格数据增强是数据科学家相对较新的领域。它与用于报告、总结或预测的分析方法相对立。在分析中,改变或添加数据以扭曲结果,使其符合预先设定的期望结果是不道德的。而在数据增强中,目的是从现有数据集中推导出新的数据。两者的目标看似不一致,但实际上并非如此。我们将在 Python 代码中花更多时间研究真实世界的表格数据集。

为了最大化利用本书内容

我设计这本书的目的是进行动手实践。最有效的方式是阅读一章,运行 Python Notebook 中的代码,重新阅读困扰你的章节内容,然后跳回去修改代码,直到概念或技巧牢牢掌握。

书中涵盖的软件/硬件 操作系统要求
Python Chrome、Edge、Safari 或 FireFox 浏览器,适用于 Windows、macOS 或 Linux。
Jupyter Notebook(Python Notebook)
Python 标准库、Pandas、Matplotlib 和 Numpy
Python 图像、文本、音频和表格数据增强库

默认的在线 Jupyter Notebook 是 Google Colab。你需要一个 Google 账号。对于其他在线 Jupyter Notebook,例如 Kaggle、Microsoft 或其他在线 Jupyter Notebook,你需要注册或拥有他们的账户。

如果你正在使用本书的数字版,我们建议你自己输入代码,或从本书的 GitHub 仓库获取代码(链接将在下一节提供)。这样做可以帮助你避免因复制粘贴代码而产生的潜在错误 代码

从 Kaggle 网站下载实际数据集需要 Kaggle 用户名和密钥。

下载示例代码文件

你可以从 GitHub 下载本书的示例代码文件,网址是 github.com/PacktPublishing/Data-Augmentation-with-Python。如果代码有更新,将会在 GitHub 仓库中更新。

我们还提供了来自我们丰富书籍和视频目录的其他代码包,访问 github.com/PacktPublishing/。快来看看吧!

下载彩色图片

我们还提供了一份 PDF 文件,其中包含本书使用的截图和图表的彩色图片。你可以在此下载: https://packt.link/FhpHV

使用的约定

本书中使用了若干文本约定。

文本中的代码:表示文本中的代码词汇、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名。例如:“使用 fetch_kaggle_comp_data()fetch_df()draw_batch() 包装函数。”

一段代码块设置如下:

pluto.remember_kaggle_access_keys("your_username_here",
  "your_key_here")

当我们希望引起你对某段代码块中特定部分的注意时,相关行或项会以粗体显示:

# Instantiate Pluto
pluto = PackTDataAug("Pluto")

任何命令行输入或输出都如下所示:

!git clone https://github.com/duchaba/Data-Augmentation-with-Python

粗体:表示新术语、重要单词或屏幕上显示的单词。例如,菜单或对话框中的单词显示为粗体。例如:“接下来,转到帐户页面,向下滚动到API部分,点击创建新 API 密钥按钮生成Kaggle 密钥。”

提示或重要说明

这样显示。

联系我们

我们总是欢迎读者的反馈。

一般反馈:如果你对本书的任何部分有疑问,请通过电子邮件联系我们,地址是 customercare@packtpub.com,并在邮件主题中注明书名。

勘误表:尽管我们已尽力确保内容的准确性,但错误仍然会发生。如果你在本书中发现错误,感谢你向我们报告。请访问 www.packtpub.com/support/errata 并填写表格。

copyright@packt.com,并附上该资料的链接。

如果你有兴趣成为作者:如果你在某个领域有专业知识,并且有兴趣撰写或参与编写书籍,请访问 authors.packtpub.com..

分享你的想法

阅读完Python 中的数据增强后,我们非常希望听到你的想法!请点击这里直接进入亚马逊书评页面并分享你的反馈。

你的评价对我们和技术社区都非常重要,能帮助我们确保提供优质的内容。

下载本书的免费 PDF 副本

感谢你购买本书!

你喜欢随时随地阅读,但又无法随身携带纸质书籍吗?

你的电子书购买是否与所选设备不兼容?

不用担心,现在购买每本 Packt 书籍,你都能免费获得该书的无 DRM PDF 版本。

在任何地方、任何设备上阅读。直接从你喜欢的技术书籍中搜索、复制并粘贴代码到你的应用程序中。

福利不仅如此,你还可以独享折扣、新闻简报和每天送到你邮箱的精彩免费内容。

按照以下简单步骤来获得福利:

  1. 扫描二维码或访问以下链接

packt.link/free-ebook/9781803246451

  1. 提交你的购买证明

  2. 就这些!我们会直接将你的免费 PDF 和其他福利发送到你的邮箱。

第一部分:数据增强

本部分包括以下章节:

  • 第一章轻松实现数据增强

  • 第二章数据增强中的偏差

第一章:数据增强简化

数据增强对开发成功的深度学习DL)项目至关重要。然而,数据科学家和开发者往往忽视了这一关键步骤。在一个实际的 DL 项目中,你将花费大部分时间来收集、清理和增强数据集,这一点不是什么秘密。因此,学习如何在不购买新数据的情况下扩展数据集是非常必要的。本书涵盖了扩展图像、文本、音频和表格数据集的标准和高级技术。此外,你还将了解数据偏差,并学习如何在Jupyter Python 笔记本中编写代码。

第一章将介绍各种数据增强概念,设置编码环境,并创建基础类。后续章节将详细解释各种技术,包括 Python 编程。数据增强的有效应用已经被证明是机器学习ML)成功与失败之间的决定性因素。许多现实世界的 ML 项目停留在概念阶段,原因是缺乏足够的数据来训练 ML 模型。数据增强是一种成本效益高的技术,可以增加数据集的大小,降低训练误差率,并生成更准确的预测。

趣味事实

汽车汽油类比对首次学习数据增强和人工智能AI)的学生非常有帮助。你可以将 AI 引擎的“数据”看作是汽油,将数据增强看作是添加剂,比如雪佛龙的 Techron 燃油清洁剂,它能使你的汽车引擎在不增加额外油料的情况下运转得更快、更*稳、行驶得更远。

在本章中,我们将定义数据增强的作用以及在不改变数据完整性的情况下扩展数据的局限性。我们将简要讨论不同类型的输入数据,如图像、文本、音频和表格数据,以及补充数据时面临的挑战。最后,我们将在随附的 Python 笔记本中设置系统要求和编程风格。

我设计这本书是为了让读者进行动手实践。最有效的学习方法是:阅读一章,运行代码,重新阅读让你困惑的部分,再跳回去修改代码,直到你牢固掌握所介绍的概念或技术。

我鼓励你修改或添加新的代码到 Python 笔记本中。这本书的主要目的是互动式学习。所以,如果遇到问题,可以从本书的 GitHub 下载一个新的副本。学习的最佳方式就是犯错并创造新东西。

数据增强是一个迭代过程,没有固定的方案。换句话说,根据数据集的不同,你可以选择增强函数并调整参数。领域专家可能会提供关于多少失真是可以接受的见解。在本章结束时,你将了解数据增强的一般规则、可以增强的输入数据类型、编程风格,以及如何在线或离线设置 Python 笔记本。

本章主要涵盖以下主题:

  • 数据增强的作用

  • 数据输入类型

  • Python 笔记本

  • 编程风格

让我们从数据增强的作用开始。

数据增强的作用

数据在任何 AI 项目中都是至关重要的。这在使用人工神经网络ANN)算法时尤其如此,也被称为深度学习DL)。一个深度学习项目的成败主要取决于输入数据的质量。

数据增强之所以重要,主要原因之一是开发一个用于预测和预报的 AI 相对容易,而这些模型需要强大的数据输入。随着开发、训练和部署深度学习项目的显著进步,例如使用FastAI框架,你可以在几行 Python 代码中创建一个世界级的深度学习模型。因此,扩展数据集是提高深度学习模型准确性、超越竞争对手的有效方式。

传统的获取额外数据的方法困难、昂贵且不切实际。有时,唯一可行的选择就是使用数据增强技术来扩展数据集。

趣闻

数据增强方法可以将数据量增加十倍。例如,获取额外的皮肤癌图像相对困难。因此,使用随机组合的图像变换技术,如垂直翻转、水*翻转、旋转和扭曲,是一种可以扩展皮肤癌照片数据的实用方法。

如果没有数据增强,获取新的皮肤癌照片并进行标注既昂贵又耗时。国际皮肤成像合作组织ISIC)是皮肤病的权威数据来源,由一组皮肤科医生验证和分类这些图片。ISIC 将数据集免费提供给公众下载。如果你无法从 ISIC 找到特定的数据集,找到其他途径将非常困难,因为访问医院或大学实验室获取皮肤病图像涉及法律和后勤障碍。获取照片后,聘请皮肤科医生团队对图像进行分类以纠正疾病会非常昂贵。

另一个例子是,通过增强获得额外图片的不可行性,例如当你从社交媒体或在线搜索引擎下载照片时。社交媒体是图像、文本、音频和视频数据的丰富来源。搜索引擎,如GoogleBing,使得下载额外数据用于项目相对容易,但版权和法律使用问题则是一个泥潭。大多数社交媒体上的图像、文本、音频和视频,如YouTubeFacebookTikTokTwitter,并未明确标注是否具有版权或属于公有领域。

此外,社交媒体推动流行内容,而非不受欢迎或冷门的素材。例如,假设你想为你的鹦鹉分类 AI 系统添加更多的鹦鹉图片。在线搜索会返回大量的蓝黄金刚鹦鹉、红绿金刚鹦鹉或白顶凤头鹦鹉,但不会有那么多的吉拉鹦鹉、凯阿鹦鹉或神话中的挪威蓝鹦鹉——这是一只来自蒙提·派森喜剧小品的假鹦鹉。

AI 训练所需数据不足的问题在文本、音频和表格数据类型中尤为严重。通常,获取额外的文本、音频和表格数据既昂贵又费时。文本数据受到强有力的版权保护。音频文件在网络上较为稀少,而表格数据主要来自私人公司数据库。

接下来的部分将定义四种常用的数据类型。

数据输入类型

四种数据输入类型是不言自明的,但值得明确界定这些数据输入类型及其不包括的内容:

  • 图像定义

  • 文本定义

  • 音频定义

  • 表格数据定义

图 1.1 – 图像、文本、表格和音频增强

图 1.1 – 图像、文本、表格和音频增强

图 1**.1 提供了图像、文本、表格和音频增强的预览。在本书的后续章节中,你将学习如何实现增强方法。

让我们从图像开始吧。

图像定义

图像是一个大类别,因为几乎任何事物都可以通过图像来表示,比如人、风景、动物、植物和我们周围的各种物体。图片还可以表现动作,比如运动、手语、瑜伽姿势等等。图像的一个特别富有创意的用法是通过捕捉计算机鼠标的运动轨迹来预测用户是否为黑客。

增加图片数量的技巧包括水*翻转、垂直翻转、放大、缩小、拉伸、扭曲和光照。人类在处理图像方面是专家。因此,即使图片稍微失真或变暗,你仍然可以辨认出它是同一张图像。然而,对于计算机而言情况并非如此。AI 将彩色图片表示为一个三维数组,包含宽度、高度和 RGB 作为深度。任何图像失真都会导致一个包含不同值的数组。

图形,例如时间序列数据图表和数学方程图,如 3D 拓扑图,不在图像增强的范围内。

有趣的事实

你可以通过创造性地使用数据增强方法来消除深度学习(DL)图像分类训练中的过拟合问题。

文本增强与图像增强有不同的关注点。我们来看看。

文本定义

主要的文本输入数据是英文,但相同的文本增强技术也可以应用于其他西日耳曼语言。Python 课程使用英文作为文本输入数据。

补充文本输入的技术包括回译、简单数据增强和 albumentation。有些方法乍看之下可能违反直觉,例如删除或交换句子中的单词。然而,这是一种可接受的做法,因为在现实生活中,并非每个人都写完美的英语。

例如,美国多厅影院AMC)网站上的电影评论员写的句子通常不完整或语法错误。他们省略动词或使用不合适的词汇。一般来说,你不应期望在许多自然语言处理(NLP)项目中,文本输入数据会是完美的英语。

如果一个 NLP 模型以完美的英语作为文本输入数据进行训练,这可能会导致对典型在线评论员的偏见。换句话说,当部署到实际用户时,NLP 模型可能会预测不准确。例如,在情感分析中,AI 系统将预测一篇电影评论是否为积极或消极情绪。假设你使用完美的英语数据集来训练系统。那么,当人们写下一些带有拼写错误和语法错误的简短评论时,AI 系统可能会预测出假阳性假阴性

语言翻译、表意文字和象形文字不在本书的讨论范围内。现在,让我们来看看音频增强。

音频定义

音频输入数据可以是任何声音波形的记录,如音乐、语音和自然声音。声音波形的属性,如振幅和频率,以图形的形式表示,这些图形在技术上是图像,但你不能对音频输入数据使用任何图像增强方法。

扩展音频输入的技术分为两种类型:波形频谱图。对于原始音频,转换方法包括时间偏移、音高缩放和随机增益,而对于频谱图,功能包括时间遮蔽、时间拉伸、音高缩放等许多其他方法。

使用非英语语言的语音不在本书的讨论范围内。这并不是因为技术上的困难,而是因为本书是用英语写成的。讨论切换到其他语言后的后果会有问题。音频增强很有挑战性,但表格数据的扩展更加困难。

表格数据定义

表格数据是关系数据库、电子表格或文本文件中的信息,格式通常为逗号分隔值CSV)。表格数据增强是 ML 和 DL 领域的一个快速发展方向。表格数据增强技术包括转换、交互、映射和提取。

有趣的挑战

这是一个思维实验。除了图像、文本、音频和表格数据外,你能想到其他数据类型吗?一个提示是 卡萨布兰卡银翼杀手

本章分为两部分。前半部分讨论了各种概念和技巧;接下来的部分是基于 Python Notebook 的实践编码。本书将在所有章节中使用这种“学习-然后编码”的模式。现在是时候动手编写 Python 代码了。

Python Notebook

Jupyter Notebook 是一个开源网页应用程序,是 AI、ML 和数据科学家的事实标准选择。Jupyter Notebook 支持多种编程语言,其中最受欢迎的是 Python。

在本书中,Python Notebook 这个术语将与 Jupyter NotebookJupyterLabGoogle Colab Jupyter Notebook 同义使用。

对于 Python 开发者来说,有很多集成开发环境(IDE)*台可供选择,例如集成开发和学习环境IDLE)、PyCharm、Microsoft Visual Studio、Atom、Sublime 等等。然而,Python Notebook 是 AI、ML 和数据科学家首选的工具。它是一个互动式的 IDE,适合探索、编写和部署 AI 项目。

有趣的事实

最简单的学习方法是阅读本书,运行代码并进行修改。本书无法覆盖所有场景,因此你必须熟悉修改代码,使其适应你的实际数据集。Python Notebook 旨在实现交互性,赋予我们自由去玩、探索并犯错。

Python Notebook 是开发工具的首选,特别是,我们将回顾以下内容:

  • Google Colab

  • Python Notebook 选项

  • 安装 Python Notebook

让我们从 Google Colab 开始。

Google Colab

Google Colab Jupyter Notebook 配合 Python 是开发 AI 和 ML 项目的流行选择。你只需要一个 Gmail 账户。

Colab 可以通过 colab.research.google.com/ 访问。本书中的代码使用免费版本的 Colab 足够了,Pro+ 版本提供更多的 CPU 和 GPU RAM。

登录 Colab 后,你可以从以下 GitHub URL 获取本书的 Python Notebooks:github.com/PacktPublishing/data-augmentation-with-python

你可以通过以下任意一种方式开始使用 Colab:

  • 打开 Python Notebook 的第一种方法是从 GitHub 复制它。从 Colab 中,转到 .ipynb 文件:

图 1.2 – 从 GitHub 加载 Python Notebook

图 1.2 – 从 GitHub 加载 Python Notebook

  • 打开 Python Notebook 的第二种方法是通过 GitHub 自动加载。前往之前提到的 GitHub 链接并点击 Python Notebook (ipynb) 文件。点击蓝色的在 Colab 中打开按钮,如图 1.3所示;它应该出现在 Python Notebook 的第一行。这将启动 Colab 并自动加载 Python Notebook:

图 1.3 – 从 Colab 加载 Python Notebook

图 1.3 – 从 Colab 加载 Python Notebook

  • 确保通过点击文件菜单并选择将副本保存到 Drive选项,将 Python Notebook 保存到本地 Google Drive。之后,关闭原文件并使用副本版本。

  • 打开 Python Notebook 的第三种方法是通过从 GitHub 下载副本。通过点击文件菜单,选择打开 Notebook,然后点击上传选项卡,将 Python Notebook 上传到 Colab,如图 1.4所示:

图 1.4 – 通过上传到 Colab 加载 Python Notebook

图 1.4 – 通过上传到 Colab 加载 Python Notebook

有趣的事实

若要快速了解 Colab 的功能,请访问colab.research.google.com/notebooks/basic_features_overview.ipynb。有关如何使用 Python Notebook 的教程,请访问colab.research.google.com/github/cs231n/cs231n.github.io/blob/master/jupyter-notebook-tutorial.ipynb

选择Colab的理由与选择 IDE 相同:主要基于您的偏好。以下部分描述了额外的 Python Notebook 选项。

其他 Python Notebook 选项

Python Notebooks 提供免费版和付费版,许多在线公司提供,例如 Microsoft、Amazon、Kaggle、Paperspace 等。使用多个供应商是常见的做法,因为 Python Notebook 在不同供应商间表现相同。然而,这就像选择 IDE 一样——一旦选择了一个,通常会继续在同一个环境中工作。

您可以使用以下功能标准来选择一个 Python Notebook:

  • 易于设置。您能在 15 分钟内加载并运行一个 Python Notebook 吗?

  • 一种免费的版本,您可以在此书中运行 Python Notebooks。

  • 免费的 CPU 和 GPU。

  • Python Notebooks 和版本的免费永久存储。

  • 轻松访问 GitHub。

  • 易于上传和下载 Python Notebooks 到本地磁盘驱动器。

  • 升级到付费版以获得更快的处理速度和更多的 CPU 与 GPU 内存。

选择 Python Notebook 的方式取决于您的需求、偏好或熟悉程度。您不必在本书的学习中使用 Google Colab。本书中的 Python Notebooks 可以在以下供应商上运行,但不限于这些:

  • Google Colab

  • Kaggle Notebooks

  • Deepnote

  • Amazon SageMaker Studio Lab

  • Paperspace Gradient

  • DataCrunch

  • Visual Studio Code 中的 Microsoft Notebooks

基于云的选项依赖于始终有快速的互联网连接,因此如果网络连接是一个问题,你可能需要在笔记本电脑/计算机上本地安装 Python Notebook。安装过程非常简单。

安装 Python Notebook

Python Notebook 可以在 Windows、Mac 和 Linux 的本地桌面或笔记本上安装。在线版本的优势如下:

  • 完全可定制

  • 无运行时限制——即在长时间训练过程中,Python Notebook 不会超时

  • 没有规则或随意的限制

缺点是你必须设置并维护环境。例如,你需要做以下操作:

  • 安装 Python 和 Jupyter Notebook

  • 安装并配置 NVIDIA 显卡(对于数据增强可选)

  • 维护和更新几十个依赖的 Python 库

  • 升级硬盘驱动器、CPU 和 GPU 内存

安装 Python Notebook 很简单,只需要一个控制台或终端命令,但首先要检查 Python 版本。在终端或控制台应用中输入以下命令:

>python3 --version

你应该安装 3.7.0 或更高版本。如果你没有 Python 3 或安装的是较旧版本,请从 www.python.org/downloads/ 安装 Python。

使用 pip 安装 JupyterLab,其中包含 Python Notebook。在 Windows、Mac 或 Linux 笔记本上,使用以下命令适用于所有三种操作系统:

>pip install jupyterlab

如果你不喜欢 pip,可以使用 conda

>conda install -c conda-forge jupyterlab

除了 pipconda,你还可以使用 mamba

>mamba install -c conda-forge jupyterlab

使用以下命令启动 JupyterLab 或 Python Notebook:

>jupyter lab

在 Mac 上安装 Python Notebook 的结果如下:

图 1.5 – 本地 MacBook 上的 Jupyter Notebook

图 1.5 – 本地 MacBook 上的 Jupyter Notebook

下一步是从相应的 GitHub 链接克隆本书的 Python Notebook。你可以使用 GitHub 桌面应用程序、终端命令行上的 GitHub 命令,或者使用带有魔法字符感叹号(!)和标准 GitHub 命令的 Python Notebook,具体如下:

url = 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
!git clone {url}

无论你选择基于云的选项(如 Google Colab 或 Kaggle)还是离线工作,Python Notebook 代码都能一样运行。接下来的部分将深入探讨 Python Notebook 编程风格,并介绍 Pluto。

编程风格

编码风格是面向对象编程的标准、经过验证的方法,并且是函数和变量的命名约定。

趣味事实

大多数你在博客和网站上找到的 Python 代码只是代码片段。因此,它们在学习像数据增强这样的基础主题时帮助不大。此外,在 Notebook 上使用 Python 会导致懒惰的编程习惯,因为程序员认为每个 Notebook 的代码单元都是一个与整体分开的片段。实际上,整个 Python Notebook 是一个程序。使用最佳编程实践的主要好处之一是,它能帮助你更容易地学习和记住知识。一种编程风格可能包括许多标准的最佳实践,但它也独具个性。通过这种方式,你可以更快地学习新概念和技巧,比如如何编写数据增强代码。

本节包含了不少主题,特别是我们将覆盖以下几个概念:

  • 源代码管理

  • PackTDataAug

  • 命名规范

  • 扩展基础类

  • 引用库

  • 导出 Python 代码

  • Pluto

让我们从源代码管理开始。

源代码管理

编程的第一条规则是管理源代码版本。这将帮助你回答以下问题:你上周写了什么代码?昨天修复了什么?今天添加了什么新功能?如何与我的团队共享代码?

Git 过程管理一个人或一个团队的源代码。Git 的诸多优点之一是它允许犯错误。换句话说,Git 允许你尝试新的东西或破坏代码,因为你始终可以回滚到先前的版本。

对于源代码管理,GitHub 是一个流行的网站,而 Bitbucket 排名第二。你可以通过命令行终端或 Git 应用程序(如 GitHub Desktop)使用 Git 过程。

Google Colab 内置了 Git 功能。你已经看到将 Python Notebook 加载到 Google Colab 上是多么简单,保存它也同样容易。在 Git 中,你必须进行提交并推送。步骤如下:

  1. Colab 菜单中,点击 文件

  2. 选择 保存副本 到 GitHub

  3. 仓库 字段中输入你的 GitHub URL 并选择代码分支。

  4. 输入提交信息。

  5. 点击 确定

图 1.6 – Google Colab – 保存到 GitHub

图 1.6 – Google Colab – 保存到 GitHub

图 1.6 显示了 Google Colab Python Notebook 和 GitHub 之间的界面。接下来,我们将查看基础类 PacktDataAug

PacktDataAug 类

基础类的代码既不是原创的,也不是本书独有的。它是构建面向对象类的标准 Python 代码。对象的名称在每个项目中都不同。对于本书来说,类的名称是 PacktDataAug

每一章都以这个基础类开始,随着我们学习新概念和数据增强技巧,我们将使用 Python 装饰器向对象添加新方法。

本练习的 Python 代码在 Python Notebooks 和本书的 GitHub 仓库中。因此,我不会在本书中复制或展示完整代码。我会展示相关代码行,解释其意义,并依赖你在 Python Notebooks 中学习整个代码。

基类的定义如下:

# class definition
class PacktDataAug(object):
  def __init__(self,
    name="Pluto",
    is_verbose=True,
    args, **kwargs):

PacktDataAug继承自基础的Object类,定义中有两个可选参数:

  • name参数是一个字符串,它表示你的对象的名称。它没有其他实质性功能,仅用于标记对象。

  • is_verbose是一个布尔值,指示对象在实例化时是否打印对象信息。

下一部分我们将讨论代码命名规范。

命名规范

代码命名规范如下:

  • 函数的名称将以动词开头,如print_fetch_say_

  • 返回布尔值的函数以is_has_开头。

  • 变量名称以名词开头,而不是动词。

  • Python 社区关于是否使用驼峰命名法——例如fetchKaggleData()——还是使用小写字母加下划线——例如fetch_kaggle_data()——展开了激烈的讨论。本书采用小写字母加下划线的命名方式。

  • 以单下划线开头的函数或变量是临时变量或辅助函数——例如_image_auto_id_drop_images()_append_full_path()

  • 变量或函数的缩写很少使用,因为描述性名称更容易理解。此外,Colab 有自动补全功能,因此使用长而描述性的名称可以更容易输入且减少打错字的机会。

实例化基类的代码是标准的 Python 代码。我使用了pluto作为对象名称,但你可以选择任何名称:

# Instantiate Pluto
pluto = PackTDataAug("Pluto")

输出如下:

--------------------------- : ---------------------------
            Hello from class : <class '__main__.PacktDataAug '> Class: PacktDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ---------------------------

基类带有两个简单的辅助方法。它们都用于打印美观的输出——也就是将状态或输出信息整齐地居中打印。

self._ph()方法打印带有等长破折号的头部行,破折号两侧各有一个冒号字符,而self._pp()函数有两个参数,一个用于左侧,另一个用于右侧。

你已经看到过使用is_verbose=True默认参数实例化pluto的结果。作为标准做法,我不会在本书中打印完整代码。我依赖你在 Python Notebook 中查看和运行代码,但在这一章中我会破例,展示is_verbose选项的代码片段。这展示了在 Python Notebook 中阅读 Python 代码是多么容易。代码片段如下:

# code snippet for verbose option
if (is_verbose):
  self._ph()
  self._pp(f"Hello from class {self.__class__} Class: {self.__class__.__name__}")
  self._pp("Code name", self.name)
  self._pp("Author is", self.author)
  self._ph()

趣味小贴士

本书的主要目标是帮助你编写干净且易于理解的代码,而不是编写可能导致混淆的紧凑代码。

另一个强大的编程技巧是使用 Python 装饰器扩展基类。

扩展基类

本书被设计为一个互动式的学习旅程,您将逐步学习和发现新的数据增强概念和技术,从图像、文本和音频数据到表格数据。随着旅程的推进,对象pluto将获得新的方法。因此,拥有一种扩展类并添加新功能的技术至关重要。相比之下,若在本书开始时就提供完全构建好的类,您将无法开始学习之旅。通过探索式学习,您能比通过死记硬背更长时间地保持知识。

@add_method()装饰器函数能够为任何类扩展新功能。

这是扩展基类的一个出色示例。Python 中最常见且令人沮丧的错误根本原因是库版本与类作业或从 Python 社区复制的代码片段不同。Python 数据科学家很少从零开始编写代码,而是大量依赖现有的库。因此,在本地或云服务器上打印 Python 库版本,将节省数小时烦人的调试时间。

为了解决此问题,我们可以扩展PacktDataAug类,或者使用将 Pluto 教会新技能的旅程隐喻。新的方法say_sys_info()将在左侧打印本书预期的系统库版本,在您的本地或远程服务器上打印实际的库版本。扩展 Pluto 类的装饰器定义如下:

# using decorator to add new method
@add_method(PackTDataAug)
def say_sys_info(self):

在运行上述代码单元后,您可以使用以下命令让 Pluto 打印出库版本:

# check Python and libraries version
pluto.say_sys_info()

结果如下:

---------------------------- : ---------------------------
                 System time : 2022/07/23 06:36
                    Platform : linux
     Pluto Version (Chapter) : 1.0
            Python (3.7.10)  : actual: 3.7.12 (default, Apr 24 2022, 17:11:25) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  CPU speed : NOT available
---------------------------- : ---------------------------

如果您的结果包含比本书预期版本更旧的库版本,在学习过程中可能会遇到错误。例如,PillowPIL)库的版本是 7.1.2,低于本书预期的 9.0.0 版本。

为了解决这个问题,请在 Notebook 中运行以下代码行来安装 9.0.0 版本:

# upgrade to Pillow library version 9.0.0
!pip install Pillow==9.0.0

重新运行pluto.say_sys_info()应该会显示PIL版本为 9.0.0。

有趣的挑战

扩展 Pluto 类,新增一个函数来显示系统的 GPU 总 RAM 和可用的空闲 RAM。该函数名可以是fetch_system_gpu_ram()。提示:可以使用torch库以及torch.to cuda.memory_allocated()torch.cuda.memory_reserved()函数。您可以使用这种技巧扩展任何 Python 库类。例如,要向numpy库添加新函数,可以使用@add_method(numpy)装饰器。

还有一些编程风格的话题。接下来,您将学习如何最佳地引用库。

引用库

Python 是一种灵活的语言,支持导入库时使用别名或直接导入。以下是导入相同函数plot()的一些例子:

# display many options to import a function
from matplotlib.pyplot import plot
import matplotlib.pyplot
import matplotlib.pyplot as plt # most popular
# more exotics importing examples
from matplotlib.pyplot import plot as paint
import matplotlib.pyplot as canvas
from matplotlib import pyplot as plotter

关键点是所有这些示例都是有效的,这既好又坏。它提供了灵活性,但同时,当在线分享代码片段或维护代码时,出现问题时会让人感到沮丧,因为 Python 经常在系统无法找到函数时给出难以理解的错误信息。要修复这个问题,你需要知道需要升级哪个库。当许多库使用相同的函数名时,问题变得更加复杂,例如imread()方法,它至少出现在四个库中。

遵循本书的编程风格,当imread()方法失败时,你就知道需要升级或在极少数情况下降级哪个库。代码如下:

# example of use full method name
import matplotlib
matplotlib.pyplot.imread()

matplotlib可能需要升级,或者你可能正在使用错误的imread()方法。它可能来自cv2.imread()

下一个概念是导出。它可能不严格属于编程风格的一部分,但如果你希望重用并为本章的代码添加额外功能,它是必要的。

导出 Python 代码

本书确保每一章都有自己的 Python Notebook。高级的图像、文本和音频章节需要上一章的代码。因此,需要从 Python Notebook 中导出选定的 Python 代码单元。

Python Notebook 既有标记单元也有代码单元,并不是所有的代码单元都需要导出。你只需要导出那些定义新函数的代码单元。对于你希望导出到 Python 文件的代码单元,在代码单元的开头使用 Python Notebook 中的%%writefile file_name.py魔法命令,并使用%%writefile -a file_name.py将额外的代码追加到文件中。file_name是 Python 文件的名称——例如,pluto_chapter_1.py

编程风格中最后也是最重要的部分是将Pluto引入作为你的编程伴侣。

Pluto

Pluto 采用了一种异想天开的教学方式,通过与虚拟数字角色的对话来进行教学。我们可以给 Pluto 分配任务。它的语气友好,有时作者会直接与你对话。它摒弃了直接讲授的方式。有学术论文解释了单口相声式讲授不是学习新概念的最佳方法,例如 Michelene T. H. Chi、Seokmin Kang 和 David L. Yaghmourian 于 2016 年在《学习科学杂志》上发表的文章Why Students Learn More From Dialogue- Than Monologue-Videos: Analyses of Peer Interactions

你很可能是独自阅读本书,而不是与小组一起学习如何编写增强代码。因此,创建一个虚拟伴侣作为实例化对象可能会激发想象力。它让编写和阅读变得更容易——例如,pluto.fetch_kaggle_data()函数一目了然,几乎不需要额外文档。它将 Python 代码简化为一个常见的主题和动词句式。

有趣的挑战

将对象名称从pluto = PackTDataAug("Pluto")更改为hanna = PackTDataAug("Hanna")

友情提醒:不要选择你心爱的猫作为对象名称,因为猫咪不会听从任何命令。想象一下,问你的猫玩接飞盘游戏。

总结

在本章中,你学到了数据增强在深度学习(DL)和生成式 AI 中对于提高预测准确性至关重要。数据增强是一种经济的方式,可以在不需要购买和标注新数据的情况下扩展数据集。

四种输入数据类型分别是图像、文本、音频和表格。每种数据类型面临不同的挑战、技术和局限性。此外,数据集决定了哪些函数和参数是合适的。例如,人脸和航拍照片是图像数据集,但你不能通过垂直翻转人脸图像来扩展数据;然而,你可以垂直翻转航拍照片。

本章的第二部分,你使用了Python 笔记本来加深对这些增强概念的理解。你选择了 Python 笔记本作为默认的 IDE,以便访问基于云的*台,如Google ColabKaggle,或者在你的笔记本电脑上本地安装 Python 笔记本。

编程风格部分为 Python 笔记本的结构奠定了基础。它提到了GitHub作为一种源代码管理形式,使用基类、扩展基类、长函数名、导出到 Python 以及引入 Pluto。

本章以 Pluto 作为主要对象奠定了基础。Pluto 并没有从完整的数据增强功能开始——他从一个最小的结构开始,并随着每一章学习新的数据增强概念和技术,逐步将新方法添加到他的工具库中。

到本书结束时,Pluto 和你将学到关于如何增强图像、文本、音频和表格数据的技术。换句话说,你将学会如何从零开始编写强大的图像、文本、音频和表格增强类,使用真实世界的数据,这些类可以在未来的数据增强项目中复用。

本章中有有趣的事实有趣的挑战。Pluto 希望你能利用提供的内容,拓展你的经验,超越本章的范围。

第二章数据增强中的偏差中,Pluto 和你将探讨数据增强如何增加偏差。将数据偏差作为数据增强的指导原则是一个常被忽视的技巧。

第二章:数据增强中的偏差

随着 人工智能AI)在我们的社会中逐渐深入,它在 AI 系统中的偏差将不利于你的生活质量。这些 AI 系统,特别是在 深度学习DL)和生成式 AI 中,依赖于你用来扩展数据增强的输入数据。

AI 系统在做出决策时高度依赖数据,如果用于训练系统的数据存在偏差,那么 AI 系统将做出不公*的决策。这将导致对个人或群体的不公正对待,并 perpetuate 系统性的不*等。AI 在改变生活的决策中扮演着决定性角色,例如每月的房贷保险费是多少,是否可以获得汽车贷款批准,求职资格,谁能获得政府援助,牛奶的价格,你在社交媒体新闻源上看到的内容,以及你国家的石油进口或出口量,等等。

通过在深入学习数据增强之前了解数据偏差,你将能够帮助开发出有益于社会的道德和公*的 AI 系统。这将帮助你做出关于数据使用的明智决策,防止现有偏差和不*等的延续。此外,理解数据偏差将帮助你做出关于数据收集过程的明智决策,确保数据具有代表性且不带偏见。

数据偏差可能对数据科学家和大学生来说是一个问题,因为它们很少在大学课程中讨论或没有提供。没有现成的公*矩阵可以用于数据增强的编程。也许通过使用最新的生成式 AI,偏差甚至可能来源于计算机系统,而不完全是由人类造成的。

提供受保护和安全的软件产品与服务有许多策略,但 AI 系统需要新的流程和视角。值得信赖和负责任的 AI 是关于公*、道德设计以及最小化偏差。实现值得信赖的 AI 从透明度、数据集、测试、评估、验证和确认TEVV)开始,正如 《人工智能偏差识别与管理标准,国家标准与技术研究所(NIST)》 特别出版物 1270 所定义。

趣闻

2016 年,Twitter 在 1 天内让微软的 AI 聊天机器人 Tay 变得堕落。微软创建 Tay 主要用于在线的休闲和玩乐对话。Tay 被设计为从网络中的未经整理的数据和评论中学习和获取输入。Twitter 社区觉得用厌女症、种族主义和暴力的推文来教 Tay 很有趣。直到今天,Tay 仍然是关于数据偏差输入教训的典型案例。正如一位博主所说:“火焰垃圾堆进,火焰垃圾堆出。”

本章将为你提供一个快速教程,帮助你认识到计算人类系统性偏差的区别。我们将了解偏差的概念,但不会练习如何编程计算偏差。公*性和混淆矩阵用于衡量 AI 预测的真正正例假正例真负例假负例。然而,公*性和混淆矩阵是用于构建 AI 系统的,而不是数据增强。在观察真实世界的文本数据集时,我们将尝试编写 Python 代码来生成包含单词计数和拼写错误的公*性矩阵,但大多数情况下,我们将依赖 Pluto 和你的观察来命名图像和文本数据中的偏差。

本章中的 Python 代码将重点帮助你学习如何从Kaggle网站下载真实世界的数据集。后续章节将重复使用本章中展示的辅助函数和封装函数。

到本章结束时,你将更加深刻地理解*衡数据集。特别是,我们将涵盖以下主题:

  • 计算偏差

  • 人类偏差

  • 系统性偏差

  • Python Notebook

  • 图像偏差

  • 文本偏差

冥王星将从三种偏差中最容易的——计算偏差开始。

计算偏差

在我们开始之前,提前提醒一下,你不会学习如何编写 Python 代码来计算数据集中的计算偏差的数值评分。本章的主要目的是帮助你学习如何从 Kaggle 网站获取真实世界的数据集,并通过观察来发现数据中的偏差。虽然会有一些代码用于计算数据集中的公*性或*衡性,但重点还是在观察。

比如,我们将计算文本数据集中每条记录的单词计数和拼写错误的单词。

你可能认为所有的偏差都是一样的,但将它们分为三类会更有帮助。偏差类别之间的差异在初次阅读数据偏差时可能很微妙。一个帮助区分这些差异的方法是思考你如何去除或减少 AI 预测中的误差。例如,计算偏差可以通过改变数据集来解决,而系统性偏差则可以通过改变 AI 系统的部署和访问策略来解决。

计算偏差源于数据集中针对一般人群的不均衡。换句话说,它偏向或低估了某个群体或数据类别。这些偏见可能是无意的,也可能是根深蒂固的。数据比通常的随机性更为偏斜。因此,算法将面临更高的假正例和假负例预测问题。

数据集表示 (DR) 和 机器学习算法 (MLAs) 是两种计算偏差。DR 更容易理解,并且与数据增强更为密切相关。本节中的许多例子都来自 DR 偏差。MLA 则特定于某个项目,无法广泛推广。

以下是一些计算偏差的例子:

  • 从 1970 年代中期开始的柯达“雪莉卡片”设定了摄影的肤色标准是技术偏见中较为著名的例子之一。雪莉卡片是柯达用来校准图像的工具,如肤色和阴影,目的是在打印人们的照片之前进行调整。它是设置过程的一部分,并且在打印设施中经常使用。雪莉是柯达的一名员工的名字。由于这种无心且非故意的歧视,三十年来,美国打印的照片并未显示出非白人肤色的真实肤色。

  • 谷歌开放 AI DALL-E 2,是 2022 年发布的一个 AI 模型,可以根据文本生成图片。例如,你可以输入一只吃西兰花穿粉色波点泳衣的河马,DALL-E 2 就会生成这张图片。尽管这一技术突破备受推崇,但也存在偏见,正如NBC 科技新闻的杰克·特雷洛(Jake Traylor)在文章《没有快捷解决方案:OpenAI 的 DALL-E 2 如何揭示 AI 偏见的挑战》中所报道的那样。例如,在 DALL-E 中,某个构建者生成的图像只展示了男性,而某个航班乘务员的标题则只生成了女性的图像。DALL-E 2 还继承了其训练数据中的各种偏见,有时其生成的结果会加剧社会刻板印象。

  • 英国信息专员办公室ICO)在 2022 年 7 月披露,AI 自动化的潜在歧视可能会对社会产生严重后果。例如,这可能导致不公*或带有偏见的工作拒绝、银行贷款或大学录取。此外,与 ICO 同时发布的还有卫报的文章《英国数据监管机构调查 AI 系统是否存在种族偏见》,由丹·米尔莫(Dan Milmo)撰写。ICO 的目标是制定一个公*且符合伦理的 AI 系统指南。

有趣的事实

使用生成式 AI 和稳定扩散GitHub上的 Python Notebook,由 Duc Haba 分支,冥王星写道:“一只用水晶球做成的可爱小河马,带有低多边形的眼睛,四周环绕着发光的光晕,细节精致复杂的概念艺术,流行艺术站点 8K,吃西兰花,身穿粉色波点衣服,位于城市中。”经过多次运行并稍微调整措辞后,他最喜欢的生成图像被创作出来。这些是原始图像:

图 2.1 – 生成式 AI,稳定扩散分支

图 2.1 – 生成式 AI,稳定扩散分支

图 2**.1 显示了一只吃西兰花的河马。在这个有趣的插曲后,我们已结束关于计算偏见的这一部分。冥王星是一个数字狗,但它能讲述人类的偏见,接下来它将在下一部分进行讲解。

人类偏见

使用 Python 代码计算人类偏见更为困难。没有 Python 或其他编程语言库可以计算数据集中的人类偏见的数值评分。我们依赖观察来识别这些人类偏见。在推导出可能的人类偏见之前,手动研究特定数据集非常耗时。我们可以辩称,这不是程序员或数据科学家的工作,因为没有可编程的方法可供遵循。

人类偏见反映了人类思维中的系统性错误。换句话说,当你开发一个人工智能系统时,你会受到你所选择的算法和数据的限制。因此,有限结果的预测可能会因为你的选择而产生偏见。这些偏见在个人、群体、机构、企业、教育和政府中隐性存在。

人类偏见种类繁多。认知偏见和感知偏见在各个领域都表现得很明显,并不仅限于人类与人工智能的互动。围绕思维、决策和行为经济学中的偏见与启发式方法,有一个专门的研究领域,如锚定偏见和确认偏见。

作为增强数据的数据科学家,仅仅意识到固有的人类偏见,我们就可以在开发和训练模型之前指出数据中的缺陷。

以下是现实世界中人工智能系统中人类偏见的几个例子:

  • 中华人民共和国PRC)在新疆省实施了面部识别人工智能,用于监控少数民族,如维吾尔族。这是已知的第一个政府专门使用人工智能进行种族画像的例子。该系统存在缺陷,存在歧视,因为它将贫穷和年长的人误判为少数民族的假阳性预测。问题的复杂化在于缅甸购买了中国的系统来打压政治异见者,正如外交关系委员会在其 2022 年发表的《人工智能伦理中国际规范的重要性》一文中所报告的那样。

  • 为了阻止广告商滥用 Facebook 新闻推送算法,Meta 限制了广告定向算法,禁止使用健康、种族、民族、政治立场、宗教和性取向等信息。NPR在文章中报道,Facebook 已经取消了基于政治、种族及其他“敏感”话题的广告定向。此项变化已于 1 月 10 日生效,涵盖 Meta 的所有应用程序,包括 Facebook、Instagram、Messenger 和 Audience Network。据报道,广告商对人群进行了微定向,传递量身定制的信息。换句话说,广告商基于受保护的特征排除了某些人群,并使用反犹太的短语定向广告。

  • 科学美国人》于 2019 年 10 月 4 日发布的文章《在一个主要的医疗风险算法中发现种族偏见》揭示了医疗系统中的许多偏见。黑人患者在干预和急诊就诊时支付更多费用。除了支付更高的费用,黑人患者还会获得较低质量的护理。AI 科学家使用历史数据中的种族和财富信息来训练医疗系统。因此,该系统对少数群体表现出偏见,影响了 2 亿美国人。

趣味挑战

这个挑战是一个思想实验。如果给定充足的预算和时间,你如何建立一个没有偏见的 AI?提示:想想我们曾经拥有过世界和*或没有犯罪的城市的时候。它不可能是一个绝对的答案。它必须是一个接受度的水*。

看清人类偏见与计算偏见之间的区别可能具有挑战性。有些偏见并不是单一的。换句话说,它们不是互相排斥的——你可以在一个 AI 系统中同时存在人类偏见和计算偏见。

人类偏见很难识别,因为它们塑造了我们对世界的感知。然而,系统性偏见在理论上可能更容易解决,但在实践中可能具有挑战性。

系统性偏见

如果我们无法构思出一种方法来计算计算偏见和人类偏见,那么就不可能设计出一个算法来程序化地计算系统性偏见。我们必须依赖人类判断来发现数据集中的系统性偏见。此外,它必须特定于某个特定的数据集,并具有明确的 AI 预测目标。没有通用的规则,也没有公*矩阵可循。

AI 中的系统性偏见是所有 AI 偏见中最臭名昭著的一种。简单来说,系统性歧视指的是当一个企业、机构或政府限制某一群体获得 AI 的利益,同时排除其他弱势群体时的情况。它具有隐蔽性,因为它隐藏在社会现有的规则和规范背后。制度性种族主义和性别歧视是最常见的例子。另一个在日常生活中常见的 AI 可及性问题是限制或排除残疾人士的入场,比如视力和听力受限的人群。

贫困群体和弱势群体在 AI 系统开发过程中没有代表权,但他们却被迫接受 AI 的预测或预测结果。这些 AI 会做出重大生活决策,包括针对贫困和弱势群体的决策,比如汽车或健康保险的费用、住房或商业银行贷款的选择,或者是否有资格接受医疗治疗。

以下是一些 AI 系统性偏见的现实例子:

  • 2022 年 7 月 4 日,《洛杉矶时报》发布的文章研究人员利用人工智能预测犯罪,揭示洛杉矶等美国大城市的偏见性执法发现了执法中的人工智能偏见。芝加哥大学的 AI 犯罪预测系统没有解决执法中的系统性偏见。对潜在犯罪地点或热点的预测基于有缺陷的输入和与贫困社区相关的环境因素,而不是犯罪发生的实际地点。人工智能反映了执法实践和程序中的系统性偏见。因此,它预测贫困社区的犯罪率较高,因为警察在过去的系统性偏见。

  • 美国司法部审查了囚犯评估工具:估算风险和需求PATTERN),并发现谁能使用 PATTERN 存在系统性偏见。此问题在 2020 年 5 月 10 日由《监管审查》发布的解决算法性 PATTERN 偏见一文中进行了讨论。报告强化了司法部对低风险罪犯应为唯一符合提前释放条件的偏见观点。PATTERN 将囚犯分为低、中、高风险,预测这些人是否会在释放后再次犯罪。由于 PATTERN 仅限于特定群体,它排除了其他囚犯的提前释放机会。

  • 文章机器学习中的偏见潜力及健康保险公司应对的机会报告了关于机器学习如何反映并延续过去和现在的系统性不公正与偏见的日益关注。该文于 2022 年 2 月由《健康事务》杂志发布。对住院可能性、药房入驻情况以及缺失或不完整数据的有限访问是种族主义和代表性不足群体的几种系统性偏见。因此,人工智能的预测可能会反映这些系统性偏见,而基于这些预测风险做出的政策决策可能会加剧现有的不*等。

趣味挑战

这个挑战是一个思想实验。哪个类别的偏见更容易发现?提示:考虑公司利润。

计算偏见、人为偏见和系统性偏见有相似之处,并且它们不是相互排斥的。没有算法或库来指导你的编码工作,它依赖于你通过学习数据集所做的观察。此时,Pluto 已经准备好学习如何从Kaggle网站获取真实世界的数据集。作为选择性任务,他将要求你在数据集中发现偏见。

Python 笔记本

本章的编码课程主要集中在从Kaggle网站下载真实世界的数据集。后续章节将依赖或重用这些数据获取功能。

在上一章中,你学习了本书关于在 Python Notebook 上进行开发的一般规则。名为 Pluto 的面向对象类包含方法和属性,你在学习新概念和技术时将向 Pluto 添加新的方法。如果你不确定开发理念,可以回顾 第一章

在本书中,Python Notebook 一词与 Jupyter NotebookJupyterLabGoogle Colab Notebook 同义使用。

有趣的挑战

Pluto 挑战你将对象的名称从 pluto.draw_batch_image() 改为 sandy.draw_batch_image()

从本章开始,使用 Python Notebook 的设置过程将在每一章中保持一致。本章的目标是帮助你更深入地理解数据集,而不是编写用于计算每个数据集偏差值的 Python 代码。设置步骤如下:

  1. 加载 Python Notebook。

  2. 克隆 GitHub。

  3. 实例化 Pluto。

  4. 验证 Pluto。

  5. 创建 Kaggle ID。

  6. 下载真实世界的数据集。

让我们从加载 Python Notebook 开始。

Python Notebook

第一步是定位 data_augmentation_with_python_chapter_2.ipynb 文件。该文件位于本书的 GitHub 仓库中,链接为 github.com/PacktPublishing/Data-Augmentation-with-Python。如果你忘记了如何加载 Python Notebook,请参考 第一章

下一步是克隆 GitHub 仓库。

GitHub

第二步是定位 ~/Data-Augmentation-with-Python/pluto/pluto_chapter_1.py 文件。该文件位于本书的主要 GitHub 仓库中的 pluto 文件夹下。

Pluto 在 Google Colab 上使用 Python Notebook。每次都会启动一个新的会话——也就是说,不会保存上次会话的永久存储。因此,加载所有所需文件的更快、更简单的方法是克隆 GitHub 仓库。它可以是本书的 GitHub 仓库,或者是你自己 Fork 的 GitHub 仓库。

从这一点开始,所有命令、代码和引用都来自 data_augmentation_with_python_chapter_2.ipynb Python Notebook。

Pluto 使用 !git clone {url} 命令来克隆一个 GitHub 仓库,其中 {url} 是 GitHub 仓库的链接。代码片段如下:

# load from official GitHub repo.
!git clone https://github.com/PacktPublishing/Data-Augmentation-with-Python
# optional step, sustitute duchaba with your GitHub space
!git clone https://github.com/duchaba/Data-Augmentation-with-Python

在 Python Notebook 中,任何以感叹号(!)开头的代码单元将告诉系统将其作为系统 shell 命令行运行。对于 Google Colab,它是 %)这样的特殊命令,它们被称为 魔法关键词魔法命令

有趣的事实

Jupyter Notebook 的内置魔法命令为底层 % 提供了便捷的功能。例如,%ldir 用于列出当前目录文件,%cp 用于复制本地目录中的文件,%debug 用于调试,等等。一个有用的 %lsmagic 命令用于列出当前 Python Notebook 环境支持的所有可用魔法命令。感叹号字符 (!) 用于运行底层操作系统命令行功能。例如,在 Linux 系统中,!ls -la 用于列出当前目录中的文件,而 !pip 用于安装 Python 库。

现在你已经下载了 Pluto 的 Python 代码,下一步是实例化 Pluto。

Pluto

实例化 Pluto 的 Python Notebook 魔法命令如下:

# instantiate pluto
pluto_file='Data-Augmentation-with-Python/pluto/pluto_chapter_1.py'
%run {pluto_file}

输出如下:

---------------------------- : ---------------------------
            Hello from class : <class '__main__.PackTDataAug'> Class: PackTDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ---------------------------

设置过程中的倒数第二步是验证 Pluto 是否正在运行正确版本。

验证 Pluto

为了进行双重检查,Pluto 运行以下函数:

# Are you ready to play?
pluto.say_sys_info()

结果应与以下输出类似:

---------------------------- : ----------------------------
                 System time : 2022/08/16 06:26
                    Platform : linux
       Python version (3.7+) : 3.7.13 (default, Apr 24 2022, 01:04:09) [GCC 7.5.0]
     Pluto Version (Chapter) : 1.0
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  CPU speed : NOT available
---------------------------- : ----------------------------

由于这段代码来自于第一章,Pluto 的版本是1.0。在 Pluto 从 Kaggle 网站下载数据集之前,他需要 Kaggle 的 密钥访问令牌

Kaggle ID

Pluto 使用 Kaggle 数据集,因为他想学习如何获取用于数据增强的真实世界数据。这比使用一小套虚拟数据更有影响力。因此,前两步是安装库以帮助下载 Kaggle 数据并在Kaggle.com上注册。

安装和导入的代码可以在开源 opendatasets 库中找到,该库由 Jovian 提供。功能代码位于 Python Notebook 中;以下是其中的一个代码片段:

# install opendatasets library
!pip install opendatasets --upgrade
import opendatasets

在你在Kaggle.com上创建账户后,你将拥有一个 Kaggle 用户名 并收到一个 Kaggle 密钥。接下来,进入 账户 页面,向下滚动到 API 部分,点击 创建新 API 令牌 按钮以生成 Kaggle 密钥

图 2.2 – Kaggle 账户页面 – 新的令牌

图 2.2 – Kaggle 账户页面 – 新的令牌

一旦你有了 remember_kaggle_access_key() 包装方法来存储对象中的属性。代码使用 Python 的 self 关键字来存储这些信息 – 例如,self.kaggle_username。该方法的定义如下:

# method definition
def remember_kaggle_access_keys(self,username,key):

其他方法将自动使用这些属性。Pluto 运行以下方法来记住你的 Kaggle 用户名和密钥:

# save Kaggle username and key
pluto.remember_kaggle_access_keys("your_username_here",
  "your_key_here")

_write_kaggle_credit() 方法将你的 Kaggle 用户名和密钥写入两个位置 – ~/.kaggle/kaggle.json./kaggle.json。它还会将文件属性更改为 0o600。这个函数以一个下划线开头;因此,它是一个主要供其他方法使用的辅助函数。

Pluto 从 Kaggle 抓取数据有两种方法:fetch_kaggle_comp_data(competition_name),其中competition_name是比赛的名称,和fetch_kaggle_dataset(url),其中url是数据集的链接。

fetch_kaggle_comp_data()包装方法中,完成大部分工作的主要代码行如下:

# code snippet for fetcing competition data
kaggle.api.competition_download_cli(str(path))

fetch_kaggle_dataset()方法中,完成大部分工作的主要代码行如下:

# fetching real-world dataset for the Kaggle website
opendatasets.download(url,data_dir=dest)

有趣的事实

截至 2022 年,Kaggle 网站上有超过 2500 个历史和当前的比赛,超过 150,000 个数据集。这些数据集涵盖了从医学、金融到其他行业的各种领域。

图像偏差

Pluto 可以访问成千上万的数据集,下载这些数据集就像替换URL一样简单。特别是,他将下载以下数据集:

  • State Farm distracted drivers detection(SFDDD 数据集

  • Nike shoes 数据集

  • Grapevine leaves 数据集

让我们从 SFDDD 数据集开始。

State Farm distracted drivers detection

开始时,Pluto 会慢下来并解释下载真实世界数据集的每一个步骤,尽管他将使用一个包装函数,看起来非常简单。Pluto 不会写任何用于程序化计算偏差公正矩阵值的 Python 代码。他依赖于你的观察力来发现数据集中的偏差。

给 Pluto 一个命令让他去抓取数据,他会将数据下载并解压解 tar到你的本地磁盘。例如,在从比赛中获取数据时,要求 Pluto 通过以下命令去抓取:

# fetch real-world data
pluto.fetch_kaggle_comp_data(
  "state-farm-distracted-driver-detection")

由于此数据来自比赛,必须加入 State Farm 比赛才能下载数据集。你应该前往State Farm Distracted Driver Detection比赛并点击Join按钮。比赛的描述来自Kaggle网站,如下所示:

“State Farm 希望通过测试仪表盘摄像头是否能自动检测驾驶员的分心行为来改善这些令人担忧的统计数据,并更好地为客户提供保险。给定一个 2D 仪表盘摄像头图像数据集,State Farm 正在挑战 Kaggler 们对每个驾驶员的行为进行分类。”

State Farm提供了该数据集,并于 2016 年发布。规则和使用许可可以在www.kaggle.com/competitions/state-farm-distracted-driver-detection/rules找到。

有趣的事实

你必须加入 Kaggle 比赛才能下载比赛数据,但下载 Kaggle 数据集时无需参加比赛。

不是所有方法都在 Python 笔记本的pluto中。例如,你不能这样做:

# 错误语法示例

fetch_kaggle_dataset(url)

然而,使用pluto前缀是正确的,如下所示:

# example of correct syntax
pluto.fetch_kaggle_dataset(url)

在 Pluto 批量显示图像之前,他必须写几行简单的代码来检查下载是否正确:

# read the image file
f = 'state-farm-distracted-driver-detection/imgs/train/c0/img_100026.jpg'
img = PIL.Image.open(f)
# display image using Python Notebook build-in command
display(img)

输出如下:

图 2.3 – State Farm 分心驾驶员

图 2.3 – State Farm 分心驾驶员

SFDDD 数据集包含 22,423 张图像,每次查看一张照片,如图 2.3所示,并不能帮助 Pluto 看到偏差。Pluto 喜欢将列表和表格数据放入 Python pandas 库中。幸运的是,State Farm 比赛自带 fetch_df(self, csv) 方法,使这一过程更简单。相关的代码行如下:

# code snippet to import into Pandas
df = pandas.read_csv(csv)

Pluto 使用 fetch_df(self, csv) 封装函数来下载数据,并使用 Pandas 显示最后三行。代码如下:

# fetch data
pluto.df_sf_data = pluto.fetch_df('state-farm-distracted-driver-detection/driver_imgs_list.csv')
# display last three records
pluto.df_sf_data.tail(3)

结果如下:

图 2.4 – State Farm 数据 – 最后三行

图 2.4 – State Farm 数据 – 最后三行

Pluto 喜欢原始 CSV 文件中的数据,如图 2.4所示,但它没有包含图像文件完整路径的列。Pandas 使得创建包含完整图像路径的新列变得非常容易。没有复杂的build_sf_fname(self, df),其中 df 是原始 DataFrame。代码片段如下:

# code snippet to create full image path
root = 'state-farm-distracted-driver-detection/imgs/train/'
df["fname"] = f'{root}/{df.classname}/{df.img}

完整的功能代码可以在 Python Notebook 中找到。Pluto 添加了完整路径列,并使用以下代码显示前 3 行:

#create new fname column
pluto.build_sf_fname(pluto.df_sf_data)
pluto.df_sf_data.head(3)

结果如下:

图 2.5 – State Farm 数据 – 完整路径图像名称

图 2.5 – State Farm 数据 – 完整路径图像名称

为了双重检查,Pluto 写了几行简单的代码来显示来自 pandas fname 列的图像,如图 2.5所示,使用 PIL 库。代码如下:

# display the image
img = PIL.Image.open(pluto.df_sf_data.fname[0])
display(img)

结果图像如下:

图 2.6 – State Farm 数据 – fname 列

图 2.6 – State Farm 数据 – fname 列

图 2.6 显示了一个驾驶员。使用 fname 列,绘制一个批次或图像集合相对容易。draw_batch() 封装函数的定义如下:

# function definition
def draw_batch(self, df_filenames,
  disp_max=10,
  is_shuffle=False,
  figsize=(16,8)):

= df_filenames 是文件名列表,存储在 pandas DataFrame 中。disp_max 默认值为 10,这是一个增量为 5 的值,例如每行 5 张照片。is_shuffle 默认为 False。如果设置为 True,每个批次将是随机选择的。最后,figsize 是输出图像的大小,默认为 (16,8)

使用 draw_batch() 封装方法,Pluto 可以绘制任何照片集合。例如,Pluto 可以使用以下代码从 SFDDD 比赛中绘制 10 张随机图像:

# display image batch
x = pluto.draw_batch(pluto.df_sf_data["fname"],
  is_shuffle=True)

结果如下:

图 2.7 – State Farm 数据 – draw_patch()

图 2.7 – State Farm 数据 – draw_patch()

Pluto 重复运行代码来查看数据集中的不同图像,如图 2.7所示。例如,他可以一次性使用以下代码随机绘制 20 张图片:

# display image batch
x = pluto.draw_batch(pluto.df_sf_data["fname"],
  is_shuffle=True,
  disp_max=20,
  figsize=(18,14))

输出结果如下:

图 2.8 – State Farm 数据 – 随机选择的 20 张图片

图 2.8 – State Farm 数据 – 随机选择的 20 张图片

图 2**.8显示了 20 张司机的照片。通过使用fetch_kaggle_comp_data()fetch_df()draw_batch()包装函数,Pluto 可以从 Kaggle 获取任何千余个真实世界的数据集。

有趣的挑战

这个挑战是一个思维实验。在阅读 Pluto 的答案之前,你在图像中看到了哪些偏见?这是可选的,没有算法或库可以用来计算偏见公*性值。这依赖于你的观察。

Pluto 阅读了 SFDDD 的目标,并考虑了计算偏见、人为偏见和系统偏见。以下要点不是需要修复的错误,但它们可能是偏见。这些偏见来自图 2**.7,关于代表性不足群体的观察。Pluto 假设 SFDDD 的长期目标是将其部署到美国:

  • Pluto 在数据集中没有看到任何年长的成年人作为司机。

  • 司机的人口统计分布是有限的。数据集中约有十几位司机,长期目标是将该 AI 系统部署到美国。因此,AI 系统将基于有限数量的司机进行训练。

  • 数据集中表示的车辆类型较少,主要是轿车、紧凑型车或 SUV。跑车或卡车的内部结构不同,可能会影响假阳性或假阴性的预测。

  • 驾驶时有其他干扰活动没有在数据集中表示出来,比如吃冰淇淋、观看车外发生的事件、梳理头发或整理发型等。

  • 数据集中的所有司机都穿着城市风格的衣服。更精致或以民族为中心的衣服风格可能会导致 AI 预测出假阳性或假阴性。

  • 目标是拯救生命。因此,系统性偏见可能是让每个人都能负担得起,而不仅仅是技术精通的城市精英。

有趣的挑战

这个挑战是一个思维实验。你能找到其他的偏见吗?没有绝对正确或错误的答案。这里列出的偏见无法通过编程方式发现。

这是一段关于 SFDDD 数据集的详细讨论。Pluto 将从Kaggle网站获取另一个数据集——Nike 鞋子数据集。

Nike 鞋子

选择 Nike 鞋子数据集是因为它将展示不同的偏见。像 State Farm 的照片一样,没有算法或库来计算公*性矩阵。我们依赖于 Pluto 和你的观察。

Nike,Adidas 和 Converse 鞋子图片(Nike)数据集包含按文件夹组织的图像,没有CSV文件。Nike 数据集在 Kaggle 网站上的描述如下:

这个数据集非常适合使用深度神经网络(如 CNNs)或更简单的机器学习分类模型进行多分类。你可以使用 TensorFlow 及其高级 API Keras,sklearn,PyTorch 或其他深度/机器学习库。

作者是 Iron486,许可协议为 CC0: 公共领域creativecommons.org/publicdomain/zero/1.0/

由于 Pluto 没有 CSV 文件可以导入到 pandas 中,Pluto 编写了 build_df_fname(self, start_path) 方法,其中 start_path 是数据存储的目录。

关键代码行是 os.walk() 函数:

# code snippet for generating meta data
for root, dirs, files in os.walk(start_path, topdown=False):
   for name in files:

Pluto 将执行查看 Nike 数据集的三步熟悉操作,具体如下:

# 1\. fetch data
fname='https://www.kaggle.com/datasets/die9origephit/nike-adidas-and-converse-imaged'
pluto.fetch_kaggle_dataset(fname)
# 2\. import meta data to Pandas
pluto.df_shoe_data = pluto.build_shoe_fname(
  'kaggle/nike-adidas-and-converse-imaged/train')
# 3\. display image batch
x = pluto.draw_batch(pluto.df_shoe_data["fname"],
  is_shuffle=True,
  disp_max=20,
  figsize=(18,14))

输出结果如下:

图 2.9 – Nike 数据 – 随机选择的 20 张图片

图 2.9 – Nike 数据 – 随机选择的 20 张图片

以下是 Pluto 从 图 2.9 提取的数据偏见观察列表:

  • 鞋子太干净了。哪里有泥泞或脏的鞋子?

  • 照片拍摄得非常专业。因此,当 AI 驱动的应用程序部署时,人们可能会发现他们的应用程序做出错误预测,因为他们的照片拍摄得很随意。

  • 在城市、农业或远足环境中缺少鞋子的图片。

让我们让 Pluto 再抓取一个图像数据集,然后再切换到文本数据集的分析。

葡萄藤叶

葡萄藤叶数据集是 Pluto 从 Kaggle 网站抓取的第三个也是最后一个真实世界图像数据集。主要目的是让你练习下载数据集并将元数据导入 pandas。顺便说一下,Pluto 将使用葡萄藤叶数据集通过观察命名其他类型的数据偏见。他不依赖于通过编码定义公*性矩阵,因为这尚不可行。也许下一代生成性 AI 将能够处理数据集中的所有照片,并推断出偏见。

这是来自葡萄藤叶数据集的摘录:

“葡萄藤的主要产品是鲜食或加工的葡萄。此外,葡萄藤叶作为副产品每年采摘一次。葡萄藤叶的品种在价格和口感上非常重要。”

作者是 Koklu M.、Unlersen M. F.、Ozkan I. A.、Aslan M. F. 和 Sabanci K.,许可协议为 CC0: 公共领域creativecommons.org/publicdomain/zero/1.0/

葡萄藤数据集中的文件名包含空格字符,这可能会使许多 Python 库混淆。因此,Pluto 运行了几个简单的 Linux 脚本,将空格转换为下划线。代码片段如下:

# remove white space from file and directory name
f2 = 'kaggle/grapevine-leaves-image-dataset/Grapevine_Leaves_Image_Dataset'
!find {f2} -name "* *" -type f | rename 's/ /_/g'

清理完文件名后,Pluto 将执行三步熟悉的操作:获取、导入和显示葡萄藤数据集。图片与 Nike 照片位于相同的文件夹结构中。因此,Pluto 重用了相同的 pluto.fetch_df() 方法:

# fetch data
fname=' https://www.kaggle.com/datasets/muratkokludataset/grapevine-leaves-image-dataset'
pluto.fetch_kaggle_dataset(fname)
# import to Pandas
pluto.df_grapevine_data=pluto.fetch_df("kaggle/grapevine-leaves-image-dataset/Grapevine_Leaves_Image_Dataset")
# display image batch
x = pluto.draw_batch(pluto.df_grapevine_data["fname"],
  is_shuffle=True,
  disp_max=20,
  figsize=(18,14))

输出结果如下:

图 2.10 – 葡萄藤数据 – 随机选择的 20 张图片

图 2.10 – 葡萄藤数据 – 随机选择的 20 张图片

以下是 Pluto 从 图 2.10 提取的数据偏见列表:

  • 这些照片太完美了,无疑它们非常容易增强和训练,但普通用户是如何使用 AI 系统的呢?如果酿酒师通过 iPhone 访问 AI 系统,他们拍摄的葡萄藤叶照片与数据集中的完美照片完全不同。结果可能会产生假阳性。

  • 类似于完美照片偏差,叶子是*的,背景是白色的,这在现实世界的使用中并不常见。训练周期能够达到高准确度,但这对于实际使用来说并不适用。

  • 如果模型按原样训练并部署,那么生成的 AI 将具有系统性偏差,仅适用于实验室技术人员,而不适用于农民。

趣味挑战

Kaggle 网站上有成千上万的图像数据集。Pluto 挑战你选择、下载、展示并列出三个不同图像数据集的偏差。

除了分心的司机、耐克鞋和葡萄藤叶外,Python 笔记本中还有更多的例子。不过接下来,Pluto 会从偏差转到文本增强。

文本偏差

到目前为止,你应该已经能识别出获取真实世界图像数据集和导入元数据到 pandas 的模式。文本数据集也是相同的模式。Pluto 会通过两节课程带领你,利用他的观察力来命名偏差。他可能会使用最新的生成 AI,如 OpenAI GPT3 或 GPT4,列出文本中的偏差。也许他以后会这么做,但现在,他会用自己的大脑来处理。不过,Pluto 会尝试编写 Python 代码,洞察文本的结构,如单词计数和拼写错误。这里并不是公*性矩阵,而是朝着正确方向迈出的第一步。

Pluto 在 Kaggle 网站上搜索 自然语言处理 (NLP) 数据集,结果显示超过 2,000 个数据集。他选择了 Netflix ShowsAmazon Reviews 数据集。获取和查看 NLP 数据集的步骤与图像数据集的获取、导入和打印步骤相同。

让我们从 Netflix 数据开始。

Netflix

Pluto 重用包装函数来下载数据。命令如下:

# fectch real-world dataset
fname='https://www.kaggle.com/datasets/infamouscoder/dataset-Netflix-shows'
pluto.fetch_kaggle_dataset(fname)

Netflix 数据集的描述来自 Kaggle 网站,如下所示:

“原始数据是通过 Selenium 网络爬虫抓取的。它包含了大约 9,000 部 Netflix 电视剧和电影的未标注文本数据,以及完整的详细信息,如演员表、发行年份、评分、描述等。”

作者是 InFamousCoder,许可协议为 CC0: 公共领域creativecommons.org/publicdomain/zero/1.0/.

第二步是将数据导入到 pandas DataFrame 中。Netflix 数据自带一个 fetch_df() 方法,可以将 Netflix 评论导入到 DataFrame,并显示前三行,如下所示:

# import metadata into Pandas
pluto.df_netflix_data = pluto.fetch_df(
  'kaggle/dataset-Netflix-shows/Netflix_titles.csv')
pluto.df_netflix_data[['show_id',
  'type', 'title', 'director', 'cast']].head(3)

结果如下:

图 2.11 – Netflix 数据,左侧列

图 2.11 – Netflix 数据,左侧列

图 2**.11 显示了 Netflix 元数据。前两步不需要 Pluto 编写新代码,但 Pluto 需要为第三步编写代码,即显示电影的标题和描述。目标是让 Pluto 查找电影描述中的任何偏见。

Pandas 使得编写 display_batch_text() 包装方法变得轻松。这段方法没有循环索引计数器洗牌算法if-else 语句。它只有三行代码,因此 Pluto 在这里展示了完整的代码:

# define wrapper function
def print_batch_text(self, df_orig,
  disp_max=10,
  cols= ["title", "description"]):
  df = df_orig[cols]
  with pandas.option_context("display.max_colwidth", None):
    display(df.sample(disp_max))
  return

Pluto 使用以下代码批量显示 Netflix 电影的标题和描述:

# print text batch
pluto.print_batch_text(pluto.df_netflix_data)

结果如下:

图 2.12 – Netflix 电影标题和描述

图 2.12 – Netflix 电影标题和描述

有趣的事实

每次 Pluto 运行 print_batch_text() 包装函数时,都会显示电影标题和描述。最好多次运行该包装函数,以便更深入地了解数据。

图 2**.12 显示了一个文本批次。Pluto 已经阅读了数百个电影描述,未发现明显的偏见。这是语言学家的工作。一般来说,英语语言可能存在以下偏见:

  • 宗教偏见

  • 性别偏见

  • 民族偏见

  • 种族偏见

  • 年龄偏见

  • 精神健康偏见

  • 前科偏见

  • 精英主义偏见

  • LGBTQ 偏见

  • 残障偏见

Pluto 不是语言学家,但其他数据属性可能会影响语言偏见,如单词数和拼写错误的单词。换句话说,Netflix 的电影描述是否大体相同长度?并且是否有很多拼写错误的单词?

这是尝试编码公*矩阵的一小部分。当使用 pandas DataFrame 时,count_words() 方法只有一行代码。其内容如下:

# attempt at fairness matrix, count words
def count_word(self, df, col_dest="description"):
  df['wordc'] = df[col_dest].apply(lambda x: len(x.split()))
  return

Pluto 计算了 Netflix 电影的单词数,并通过以下代码重新检查了结果:

# count words and dislay result
pluto.count_word(pluto.df_netflix_data)
pluto.print_batch_text(pluto.df_netflix_data,
  cols=['description','wordc'])

结果如下:

图 2.13 – 电影描述字数

图 2.13 – 电影描述字数

图 2**.13 显示了每个记录的字数。下一步是使用 draw_word_count() 函数绘制字数分布,结果如下:

# code snippet for draw word count
df.boxplot(ax=pic[0],
  column=[wc],
  vert=False,
  color="black")
df[wc].hist(ax=pic[1],
  color="cornflowerblue",
  alpha=0.9)

完整的函数代码可以在 Python Notebook 中找到。Pluto 使用以下代码绘制 BoxPlot 和直方图:

# draw word count
pluto.draw_word_count(pluto.df_netflix_data)

结果如下:

图 2.14 – Netflix 电影描述字数

图 2.14 – Netflix 电影描述字数

图 2**.14 所示,BoxPlot 和直方图显示分布均匀。有少数异常值,均值为 23.88,Netflix 电影描述的大部分字数在 22 到 25 字之间。因此,这里没有偏见。接下来 Pluto 将检查拼写错误的单词。

Pluto 使用 pip 命令安装 spellchecker 类。check_spelling() 方法将 pandas DataFrame 和指定的列作为参数。函数的关键代码行如下:

# code snippet for check spelling
df["misspelled"] = df[col_dest].apply(
  lambda x: spell.unknown(self._strip_punc(x).split()))
df["misspelled_count"] = df["misspelled"].apply(
  lambda x: len(x))

Pluto 检查了 Netflix 电影描述的拼写,并使用 print_batch_text() 函数显示结果。代码如下:

# check spelling
pluto.check_spelling(pluto.df_netflix_data)
# print batch text withh correct spelling
pluto.print_batch_text(pluto.df_netflix_data,
  cols=['description', 'misspelled'])

结果如下:

图 2.15 – Netflix 错别字

图 2.15 – Netflix 错别字

图 2**.15 显示了错别字。Pluto 通过重用相同的 draw_word_count() 函数,在图表中展示这些数据,如下所示:

# draw word count
pluto.draw_word_count(pluto.df_netflix_data,
  wc='misspelled_count')

结果如下:

图 2.16 – Netflix 错别字图

图 2.16 – Netflix 错别字图

错别字大多数是人名或产品名,如 图 2**.16 所示。Netflix 的电影描述*均每个有 0.92 个错别字,且只有少数几个异常值。没有语言学家的帮助,Pluto 无法在 Netflix 电影描述中发现任何偏差。接下来我们来看一下亚马逊评论,看看是否能找到任何偏差。

亚马逊评论

亚马逊评论数据集是本章下载的最后一个真实世界文本数据集。Pluto 按照相同的模式进行处理,你现在应该已经熟悉这些代码,并准备好从 Kaggle 网站下载任何真实世界的数据集。此外,像处理 Netflix 数据一样,Pluto 将利用他作为数字狗的强大洞察力,找出文本中的偏差。他将使用相同的技术和库,程序化地找到单词计数和错别字。

Pluto 不会解释如何为亚马逊评论编写代码,因为他在 Netflix 数据中重用了相同的函数。完整的代码可以在 Python Notebook 中找到。以下是代码片段:

# fetch data
pluto.fetch_kaggle_dataset(
  'https://www.kaggle.com/datasets/tarkkaanko/amazon')
# import to Pandas
pluto.df_amazon_data = pluto.fetch_df(
  'kaggle/amazon/amazon_reviews.csv')
# count words and misspell
pluto.count_word(pluto.df_amazon_data,
  col_dest='reviewText')
pluto.check_spelling(pluto.df_amazon_data,
  col_dest='reviewText')

亚马逊评论数据集在 Kaggle 上的数据描述如下:

“电子商务中最重要的问题之一是正确计算售后产品的积分。解决这个问题的方法是为电子商务网站提供更高的客户满意度,为卖家提供产品的突出展示,并为买家提供无缝的购物体验。另一个问题是正确排序产品的评论。误导性评论的突出展示将导致财务损失和客户流失。”

作者是 Tarık kaan Koç,并且许可证是 CC BY-NC-SA 4.0creativecommons.org/licenses/by-nc-sa/4.0/

Pluto 使用以下代码打印批次:

# display misspelled words
pluto.print_batch_text(pluto.df_amazon_data,
  cols=['reviewText','misspelled'])

结果如下:

图 2.17 – 亚马逊评论错别字

图 2.17 – 亚马逊评论错别字

Pluto 选择在 print_batch 函数中显示两列数据,如 图 2**.17 所示,但数据集中有 12 列数据。它们如下:

  • reviewerName

  • overall

  • reviewText

  • reviewTime

  • day_diff

  • helpful_yes

  • helpful_no

  • total_vote

  • score_pos_neg_diff

  • score_average_rating

  • wilson_lower_bound

Pluto 使用以下代码绘制单词计数和错别字:

# display word count
pluto.draw_word_count(pluto.df_amazon_data)
# draw misspelled words
pluto.draw_word_count(pluto.df_amazon_data,
  wc='misspelled_count')

单词计数的结果如下:

图 2.18 – 亚马逊评论字数

图 2.18 – 亚马逊评论字数

这是拼写错误单词的图表:

图 2.19 – 亚马逊评论拼写错误单词图表

图 2.19 – 亚马逊评论拼写错误单词图表

普鲁托(Pluto)注意到,亚马逊评论中的偏见,如图 2.172.182.19所示,具体如下:

  • 亚马逊评论中的语法错误比 Netflix 电影描述中的更多。因此,可能会对写得好的评论产生偏见。

  • 评论中有更多的技术产品名称和术语。因此,可能会对非技术性评论者产生偏见。

  • 评论中有很多大纲。*均每条评论有 50.46 个单词,反馈大多集中在 20 到 180 个单词之间。通过其他列(如 helpful_yestotal_votescore_pos_neg_diff)进行更深入的挖掘,看看每个类别的评论长度是否存在偏见,是很有意义的。

  • 亚马逊评论中的拼写错误单词比 Netflix 电影描述中的更多,这强化了对写得好的评论者的偏见。

在进入总结之前,有一个有趣的事实。

有趣的事实

凯西·奥尼尔(Cathy O’Neil)在 2016 年出版的书籍《数学毁灭武器:大数据如何增加不*等并威胁民主》描述了算法和人工智能中的许多偏见,这本书是数据科学家和大学生的必读书。书中有两个突出示例:一位经验丰富的教师被计算机算法解雇,一位合格的大学生被候选人筛选软件拒绝。

总结

本章不同于本书的其他章节,因为我们讨论了更多的理论内容,而非实际的数据增强技术。起初,数据偏见和数据增强之间的联系似乎微弱。然而,随着你开始了解计算偏见、人为偏见和系统性偏见,你会看到它们之间有着强烈的联系,因为它们都有确保成功的伦理 AI 系统使用和接受的共同目标。

换句话说,数据增强提高了 AI 的预测准确性,同时减少了数据增强中的偏见,确保了 AI 预测的假阴性和真阴性结果更少。

计算偏见、人为偏见和系统性偏见虽然相似,但并不互相排斥。然而,通过提供大量现实世界中的偏见示例,并观察三个现实世界的图像数据集和两个现实世界的文本数据集,这些偏见变得更加容易理解。

数据增强中的偏见性质使得编程计算偏见变得具有挑战性。然而,你已经学会了如何使用单词计数和拼写错误单词技术为文本数据集编写 Python 代码来生成公*性矩阵。你还可以使用生成型 AI,如 Stable Diffusion 或 DALL-E,自动识别照片中的偏见,并使用 OpenAI GPT3、GPT4 或 Google Bard 来计算文本数据中的偏见。不幸的是,生成型 AI 超出了本书的讨论范围。

最初,Pluto 倾向于通过一步一步的解释来讲解,但随着学习的深入,他简化了论证过程,只展示了最基础的代码。完整的代码可以在 Python Notebook 中找到。

大部分 Python 代码都用于教你如何从 Kaggle 网站下载真实世界的数据集,并将元数据导入 pandas。后续章节将复用这些助手和包装函数。

在本章中,有许多有趣的事实有趣的挑战。Pluto 希望你能充分利用这些,并将你的经验扩展到本章之外。

Pluto 期待着第三章,他将在那里展示如何在 Python 中进行图像增强。

第二部分:图像增强

本部分包括以下章节:

  • 第三章用于分类的图像增强

  • 第四章用于分割的图像增强

第三章:图像增强用于分类

机器学习ML)中的图像增强是一种提高预测准确性的稳定方法,尤其是在图像分类领域。因果逻辑是线性的,这意味着数据输入越强大,预测准确度越高。

深度学习DL)是机器学习的一个子集,使用人工神经网络来学习模式并根据输入数据进行预测。与依赖程序员编码和规则来分析数据的传统机器学习算法不同,深度学习算法能够自动学习、解决问题并分类数据与标签之间的关系。因此,扩展数据集直接影响深度学习模型对新见解的预测,这些见解在训练数据中尚未出现。

深度学习算法旨在模仿人类大脑,具有多层神经元来处理信息并将其传递到下一层。每一层神经元都会学习从输入数据中提取越来越复杂的特征,从而使网络能够识别模式并随着准确度的提高做出预测。

深度学习(DL)在图像分类领域已被证明在多个行业中都非常有效,从医疗、金融、交通、消费品到社交媒体。举些例子,如识别 120 种狗狗品种检测颈椎骨折编目地标分类耐克鞋识别名人面孔以及分离纸张和塑料 用于回收

没有标准公式来估计需要多少图像才能达到图像分类所需的预测准确度。由于成本和时间的限制,获取更多图像可能不是一个可行的选择。另一方面,图像数据增强是一种经济有效的技术,它能够增加用于图像分类训练的图像数量。

本章由两部分组成。首先,你将学习图像分类增强的概念和技术,随后进行动手的 Python 编程,并详细解释图像增强技术。

有趣的事实

在图像分类模型中,图像数据集通常被划分为 75%的训练集、20%的验证集和 5%的测试集。通常,分配给训练集的图像会进行增强,但验证集和测试集之外的图像不会进行增强。

图像增强的两种主要方法是预处理和动态方法。它们使用相同的技术,但在增强的时间点上有所不同。预处理方法在训练之前创建并保存增强后的图像,而动态方法则在训练周期中扩展输入图像。

第二章中,你学习了数据偏差,值得记住的是,图像增强虽然能提高深度学习模型的准确性,但也可能增加偏差。

除了偏差,另一个值得注意的概念是 安全性。它指的是在变换后不会改变原始图像标签的失真幅度。不同的照片领域具有不同的 安全性 水*。例如,水*翻转一个人的肖像照片是一个可接受的增强技术,但翻转手势图像在手语中则是不安全的。

到本章结束时,你将掌握分类图像增强的概念和 Python 编程的实践技巧,使用真实世界的数据集。此外,你还将了解几种用于图像增强的 Python 开源库。本章特别涵盖以下主题:

  • 几何变换

  • 光度变换

  • 随机擦除

  • 组合

  • 通过 Python 代码加强学习

几何变换是常用的主要图像增强技术,广泛应用于多个图像数据集中。因此,这是讨论图像增强的一个好起点。

几何变换

几何变换会改变照片的几何形状,这可以通过沿 X 轴或 Y 轴翻转、裁剪、填充、旋转、扭曲和位移来实现。复杂的增强技术使用这些基本的照片变换方法。在进行几何变换时,必须根据图像主题保持失真幅度在安全范围内。因此,并没有一个适用于所有照片的通用几何变换公式。在本章后半部分的 Python 编程部分,你和 Pluto 将下载真实世界的图像数据集,以定义每个图像集的安全水*。

以下技术并非互相排斥。你可以将水*翻转与裁剪、调整大小、填充、旋转或任何组合技术结合使用。唯一的限制是失真的安全级别。

特别是,你将学习以下技术:

  • 翻转

  • 裁剪

  • 调整大小

  • 填充

  • 旋转

  • 位移

  • 噪声注入

我们从翻转开始。

翻转

翻转的两种类型是水* Y 轴翻转和垂直 X 轴翻转。沿 Y 轴翻转照片就像看镜子一样。因此,除了方向性图像(如路标)外,这种翻转适用于大多数类型的照片。有很多情况下,沿 X 轴旋转是不安全的,例如风景或城市景观图像,其中天空应位于照片的顶部。

这不是非此即彼的选择,图像可以同时使用水*和垂直翻转,例如来自飞机的航拍照片。因此,翻转通常是安全的。然而,有些照片对于任何变换都不安全,比如路标,任何旋转都会改变原始标签的完整性。

本章后面,你将学习如何使用 Python 代码和图像增强库翻转图像,但现在,这里有一个预告演示。函数名称是 pluto.draw_image_teaser_flip();解释将稍后进行。

图像输出如下:

图 3.1 – 图像垂直翻转

图 3.1 – 图像垂直翻转

翻转保持所有图像内容不变。然而,下面的技术称为裁剪,会丢失信息。

裁剪

裁剪图像涉及删除图片的边缘。大多数卷积神经网络(CNNs)使用正方形图像作为输入。因此,纵向或横向模式的照片通常被裁剪为正方形图像。在大多数情况下,裁剪边缘基于图片的中心,但没有规则表明它必须是图片的中心。

照片的中心点是宽度的 50%和高度的 50%。然而,在图像增强中,你可以选择将裁剪中心移动到宽度的 45%和高度的 60%。裁剪中心可以根据照片的主题而变化。一旦确定了移动裁剪中心的安全范围,你可以尝试在每个训练周期动态裁剪图像。因此,每个训练周期都有一组不同的照片。这样做的效果是,机器学习模型不太可能过拟合,并且由于拥有更多的图像,准确率更高。

pluto.draw_image_teaser_crop() 函数是另一个预告演示。在接下来的章节中,我将只展示一些增强方法的预览图像,因为你稍后会通过 Python 代码更深入地了解它们。

中心裁剪 的输出图像如下:

图 3.2 – 图像中心裁剪

图 3.2 – 图像中心裁剪

裁剪不同于调整图像大小,我们将在下面讨论。

调整大小

可以通过保持或不保持相同的纵横比来调整大小:

  • 缩放(Zooming) 相当于放大、裁剪并保持相同的纵横比。

  • 压缩(Squishing) 相当于放大或缩小并改变原始纵横比。对于缩放、压缩或其他调整技术的安全级别取决于图像类别。

pluto.draw_image_teaser_resize() 函数是使用 压缩 模式调整图像大小的有趣演示。输出如下:

图 3.3 – 使用压缩模式调整图像大小

图 3.3 – 使用压缩模式调整图像大小

当调整照片大小而不保持原始纵横比时,需要对新图像进行填充。有不同的填充方法。

填充

填充涉及填充不是图像的画布外边缘。填充有三种常用方法:

  • 零填充(Zero padding) 指的是使用黑色、白色、灰色或高斯噪声填充图像。

  • 反射填充(Reflection padding) 会镜像填充区域与原始图像

  • 边框填充涉及在填充区域中重复边界线

填充与裁剪、调整大小、*移和旋转相结合使用。因此,安全比例取决于裁剪、调整大小和旋转。

旋转

旋转图像涉及顺时针或逆时针旋转图片。旋转的度量单位是度数,并且旋转方向为顺时针。因此,旋转 180 度相当于垂直翻转,而旋转 360 度则将照片恢复到原始位置。

一般的旋转操作是在 X-Y *面上进行的,而在 Z *面上的旋转被称为倾斜倾斜剪切涉及在三个*面(即 X、Y 和 Z *面)上旋转。与大多数几何变换一样,旋转是一种安全操作,对某些图像数据集有固定的限制,而对其他数据集则没有。

pluto.draw_image_teaser_rotate()函数是一个有趣的示范,展示了如何使用反射填充模式旋转图像。输出如下:

图 3.4 – 图像旋转与反射填充模式

图 3.4 – 图像旋转与反射填充模式

类似于旋转的是图像*移,这导致了下一种技术,称为*移。

*移

翻译方法通过沿 X 轴向左或向右移动图像,或沿 Y 轴向上或向下移动图像。它使用填充来填补因移动照片而留下的负空间。*移有助于减少图像中心偏差,例如当人的肖像被居中时。照片的主体将决定*移图像的安全参数。

下一个几何变换与我们到目前为止讨论的有所不同,因为噪声注入会降低照片的清晰度。

噪声注入

噪声注入会向图片中添加随机的黑色、白色或彩色像素,从而在原始图像上创建颗粒感效果。高斯噪声是生成自然噪声的事实标准,基于数学家卡尔·弗里德里希·高斯在 1830 年代提出的高斯分布算法。

pluto.draw_image_teaser_noise()函数是一个有趣的示范,展示了使用高斯模式进行的噪声注入。输出如下:

图 3.5 – 使用高斯模式的图像噪声注入

图 3.5 – 使用高斯模式的图像噪声注入

有趣的挑战

这是一个思维实验:你能想到其他几何图像变换吗?提示:使用 Z 轴,而不仅仅是 X 轴和 Y 轴。

本章的第二部分,Pluto 和你将一起发现如何编写几何变换的代码,如翻转、裁剪、调整大小、填充、旋转和噪声注入,但首先有一些其他图像增强技术需要学习。下一个类别是光度变换。

光度变换

光度变换也称为光照变换。

图像表示为一个三维数组或一个三阶张量,前两个维度是图像的宽度和高度坐标,对应每个像素的位置。第三个维度是红色、蓝色和绿色RGB)值,范围从零到 255,或在十六进制表示中为 #0 到 #FF。打印中 RGB 的等价物是青色、品红色、黄色和黑色CMYK)。另一个流行的格式是色相、饱和度和数值HSV)。重点是,图像在归一化时是一个整数或浮点矩阵。

将图像可视化为一个数字矩阵,可以方便地对其进行转换。例如,在 HSV 格式中,将矩阵中的饱和度值调整为零,会将图像从彩色转换为灰度图像。

数十种滤镜改变色彩空间的特性,从基础到独特的都有。基础方法包括变暗变亮锐化模糊对比度色调偏移。除了基础方法,还有许多滤镜类别无法在此一一列举,比如复古动感蒸汽朋克等。此外,像 Adobe Photoshop 这样的照片软件,以及在线图像编辑器,常常会创造出新的图像滤镜。

特别地,本节将涵盖以下主题:

  • 基本和经典

  • 高级与独特

让我们从基础和经典开始。

基本和经典

在图像增强中的光度变换是一种提高 AI 模型准确性的有效技术。大多数学术论文,如 Nour Eldeen Khalifa、Mohamed Loey 和 Seyedali Mirjalili 发表的《深度学习在数字图像增强中的最新趋势综述》(A comprehensive survey of recent trends in deep learning for digital images augmentation),由Artificial Intelligence Review于 2021 年 9 月 4 日发表,专门使用经典滤镜,因为代码执行速度快。经典滤镜有许多开源 Python 库,Pluto 和你将在本章后续内容中进一步探索。

特别地,你将学习以下经典技术:

  • 变暗与变亮

  • 色彩饱和度

  • 色调偏移

  • 色调偏移

  • 对比度

让我们从最常见的技术开始:变暗和变亮滤镜。

变暗与变亮

亮化图像意味着增加亮度值,而降低亮度值则意味着变暗图像。在 Python 代码中,照片是一个整数或浮点值的矩阵,一旦转换为 HSV 格式,增加或降低 HSV 矩阵中的数值V)就可以增加或减少图像的亮度。

当你需要为 Pluto 对象编写图像变亮或变暗的函数时,你将使用 Python 图像库来完成繁重的工作,但从头编写代码并不困难。亮度值的安全范围取决于图像的主题和标签目标。

pluto.draw_image_teaser_brightness() 函数是一个有趣的变暗图像演示。输出结果如下:

图 3.6 – 图像亮度,变暗模式

图 3.6 – 图像亮度,变暗模式

类似地,色彩饱和度在 Python 中也很容易编码。

色彩饱和度

色彩饱和度涉及增加或减少照片中颜色的强度。通过将饱和度值降低到接*零,图像将变成灰度图像。相反,抬高饱和度值,图像会显示出更加浓烈或鲜艳的颜色。

类似于亮度水*编码,在 HSV 矩阵中操作图像的饱和度S)值可以产生期望的效果。色彩饱和度的安全范围取决于图像的主题和标签目标。

到目前为止,我们已经看过了SVHSV中的作用,那么H值是做什么的呢?它是用来做色调偏移的。

色调偏移

在 HSV 格式的 Python 图像矩阵中,移动色调H)值会改变照片的颜色。通常,色调值用一个圆圈表示。因此,色调值从零开始,到 360 度结束。红色位于旋转的顶部,起始值为零,接着是黄色、绿色、青色、蓝色和洋红色。每种颜色之间相隔 60 度。因此,最后一种颜色——洋红色,从 310 度开始,到 360 度结束。

色调偏移是一个很好的图像编辑滤镜,但对于 AI 图像增强,它并没有太大帮助,因为它会使图像超出预期的标签。例如,假设你正在开发一个 AI 模型来分类不同物种的变色龙。在这种情况下,色调切换技术足以进行图像增强。但如果你的项目是区分猫和毛茸茸的玩具球,它可能会导致误报,因为你可能得到荧光粉色的猫。

pluto.draw_image_teaser_hue()函数是一个有趣的色调偏移演示。输出结果如下:

图 3.7 – 图像色调偏移

图 3.7 – 图像色调偏移

与色调偏移类似的是色彩投射。

色彩投射

色彩投射也称为色彩调 tinting。当白色不*衡或不准确时,就会发生色彩投射。常见的调色为红色、绿色或蓝色RGB)。在 Python 中,给照片加上色调就像改变图像矩阵中的 RGB 值一样简单。与色调偏移滤镜一样,色彩投射的安全范围也要考虑到相同的因素。换句话说,色彩投射在 AI 图像增强中使用有限。

没有正式的定义来区分哪些滤镜是基础的或经典的,哪些是高级的或异国情调的。因此,我们选择查看对比度滤镜作为经典光度变换的最终示例。

对比度

对比度是区分图像中物体的亮度或颜色差异。例如,大多数摄影师希望前景中的人物与背景之间有很高的对比度。通常,前景物体比背景更明亮,焦点更清晰。对比度值的安全范围取决于图像的主题和标签目标。

Pluto 和你将在本章后半部分通过 Python 代码探索对比滤镜和所有其他经典光度变换。接下来的部分将涉及高级和异域滤镜。

高级与异域

高级或异域技术没有用于在数据增强中实现这些滤镜的 Python 库。在线照片编辑网站和桌面软件经常每月创建新的异域滤镜。

如果你查看Adobe Photoshop的滤镜部分,或许还能在许多在线照片编辑网站上找到如www.fotor.com这样的服务,你会发现数十种或数百种滤镜选项。专门针对图像主题的滤镜包括人物肖像、风景、城市景观、静物等。滤镜也按风格分类,如复古、老式、蒸汽朋克、时尚、温和、动感等。

异域滤镜在学术论文中并不常见,部分原因是缺乏可用的 Python 库,并且在训练周期中执行这些操作需要大量的 CPU 或 GPU 资源。然而,理论上,异域滤镜是图像增强的优秀技术。

有趣的挑战

让我们进行一个思维实验。像稳定扩散(stable diffusion)或 DALL-E 这样的生成性 AI 能否为数据增强创造新图像?生成性 AI 可以根据输入文本生成数百或数千张图像。例如,假设你的任务是开发一个 AI 来识别独角兽、飞马或弥诺陶洛斯,这些神话生物的图像是更容易在印刷品中找到还是在现实生活中找到?生成性 AI 可以做到这一点,但这是一种实用的技术吗?提示:思考静态与动态数据增强所需的磁盘空间和时间。

光度和几何变换可以操作照片,而随机擦除则为图像添加了新元素。

随机擦除

随机擦除选择图像中的一个矩形区域,并用灰色、黑色、白色或高斯噪声像素矩形替换或覆盖它。这种技术为何能提高 AI 模型的预测准确性,直觉上是难以理解的。

任何机器学习模型的强大之处,尤其是卷积神经网络(CNN),在于预测或预见训练或验证阶段未曾见过的数据。因此,随机丢弃(dropout)是一种经过验证的有效方法,可以减少过拟合并提高准确性,这意味着随机擦除具有与增加丢弃率相同的效果。

一篇名为《随机擦除数据增强》的论文于 2017 年 11 月 16 日通过 arXiv 发布,展示了随机擦除如何在基于 CNN 的模型中提高准确性并减少过拟合。该论文的作者为来自厦门大学和澳大利亚悉尼科技大学认知科学系的 Zhun Zhong、Liang Zheng、Guoliang Kang、Shaozi Li 和 Yi Yang。

通常,随机擦除矩形区域,也称为切割区域,会使用高斯随机化填充随机像素。随机擦除的安全范围取决于图像主题和标签目标。

有趣的事实

有一个创造性的例子,使用随机擦除进行图像增强,以减少偏差。在自动驾驶汽车系统中,一个图像分类模型是识别和分类路标。该 AI 模型使用清晰、完整的路标照片进行训练,因此它对美国贫困社区中那些被涂鸦和破坏的路标照片有偏见。通过随机添加涂鸦、油漆、污垢和弹孔的切割区域,提高了模型的准确性,减少了过拟合,并且减少了对贫困社区路标的偏见。

根据图像数据集的主题,可以混合和匹配随机擦除、光度和几何变换。我们来详细讨论一下。

结合

几何变换中的技术或滤镜可以轻松与大多数图像主题结合。例如,你可以将水*翻转、裁剪、调整大小、填充、旋转、*移和噪声注入等技术混合应用于多个领域,如人物、风景、城市景观等。

此外,以风景为主题,你可以将多种滤镜结合在光度变换中,例如暗化、亮化、色彩饱和度和对比度。色调偏移和色彩偏差可能不适用于风景照片。然而,先进的摄影变换滤镜,例如向风景图像中添加雨雪效果,是可以接受的。

还有更多:你可以将随机擦除应用于风景图像。因此,1,000 张风景图像可能会增加到 200,000 张用于训练的照片。这就是图像增强的力量。

有趣的挑战

这是一个思维实验:你应该增强整个图像数据集,还是只增强其中的一部分?

数据增强可以为训练生成数十万张新图像,减少过拟合问题,从而提高 AI 预测的准确性。但是,如果你还增强了验证和测试数据集呢?提示:考虑一下真实世界的应用、深度学习的泛化能力,以及假阴性和假阳性。

到目前为止,我们已经讨论了各种图像增强滤镜和技术。下一步是你和 Pluto 编写 Python 代码,以加深你对这些概念的理解。

通过 Python 代码强化你的学习

我们将采用与第二章相同的方法。首先,在 Google Colab 或你选择的 Jupyter Notebook 或 JupyterLab 环境中加载 data_augmentation_with_python_chapter_3.ipynb 文件。从此时起,代码片段将来自 Python Notebook,其中包含所有函数。

本章的编码学习主题如下:

  • Pluto 和 Python Notebook

  • 真实世界的图像数据集

  • 图像增强库

  • 几何变换

  • 光度变换

  • 随机擦除

  • 合并

下一步是下载、设置并验证 Pluto 和 Python Notebook 是否正常工作。

Pluto 和 Python Notebook

在加载 Pluto 之前,需要通过克隆本书的 %run 魔法命令来获取 Pluto,我们可以调用它。如果你对 Pluto 进行了改进或修改,加载那个文件。如果这些步骤不熟悉,请查看 第二章

有趣的事实

编码的启动过程对于每一章都是相同的。Pluto 只显示本书中的必要代码片段,剩下的完整代码需要你在 Python Notebook 中查看。

使用以下代码克隆 Python Notebook 并调用 Pluto:

# clone the book repo.
f = 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
!git clone {f}
# invoke Pluto
%run 'Data-Augmentation-with-Python/pluto/pluto_chapter_2.py'

输出将类似于以下内容:

---------------------------- : ---------------------------
            Hello from class : <class '__main__.PacktDataAug'> Class: PacktDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ---------------------------

通过在 Python Notebook 中运行以下代码来仔细检查 Pluto 是否正确加载:

# display system and libraries version
pluto.say_sys_info()

输出将如下所示,具体内容根据你的系统可能有所不同:

---------------------------- : ---------------------------
                 System time : 2022/09/18 06:07
                    Platform : linux
     Pluto Version (Chapter) : 2.0
       Python version (3.7+) : 3.7.13 (default, Apr 24 2022, 01:04:09) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  CPU speed : NOT available
---------------------------- : ---------------------------

Pluto 已验证 Python Notebook 正常工作,接下来的步骤是从 Kaggle 网站下载真实世界图像数据集。

真实世界图像数据集

第二章 中,Pluto 学会了如何从 Kaggle 网站下载成千上万的真实世界数据集。在本章中,他选择了六个图像数据集来展示不同的图像增强技术。当然,你也可以通过将新的 URL 传递给 Python Notebook 中的代码来替换或添加新的 Kaggle 图像数据集。

有趣的挑战

从 Kaggle 网站下载另外两个真实世界数据集。Pluto 喜欢玩接飞盘,所以它取回新的数据集不成问题。提示:访问 www.kaggle.com/datasets 并搜索 图像分类。下载更多的真实世界数据将进一步加深你对图像增强概念的理解。

Pluto 选择了六个图像数据集,基于每个主题对增强技术的挑战。换句话说,一个概念可能适用于某个主题,但对另一个主题则不适用。具体来说,六个图像数据集如下:

  • Covid-19 图像数据集

  • 印度人

  • 可食用和有毒的真菌

  • 海洋动物

  • 越南食物

  • 商场人群

有趣的事实

Kaggle 网站下载这六个真实世界数据集的代码看起来有些重复。设计如此简单,因为 Pluto 花了很多心思创建了可重用的方法,在 第二章中,你可以查看完整的代码。他希望这个过程尽可能简单,这样你就能轻松地从 Kaggle 网站下载任何真实世界数据集。

让我们从 Covid-19 数据开始。

Covid-19 图像数据集

医疗是人工智能图像预测模型的热门类别。因此,Pluto 选择了 Covid-19 图像数据集。他获取了图片,并使用 第二章 中展示的方法创建了所需的 pandas DataFrame。注意,完整代码在 Python Notebook 中。

以下命令用于获取并加载数据到 pandas:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/pranavraikokte/covid19-image-dataset')
# import to Pandas data frame
f = 'kaggle/covid19-image-dataset/Covid19-dataset/train'
pluto.df_covid19 = pluto.make_dir_dataframe(f)

pandas DataFrame 的前三条记录如下:

图 3.8 – pandas DataFrame 的前三行

图 3.8 – pandas DataFrame 的前三行

Kaggle 网站上,数据的背景如下:

帮助像我这样的深度学习和人工智能爱好者通过仅使用胸部 X 光片贡献改善 Covid-19 检测的工作。数据集包含约 137 张经过清理的 Covid-19 图像和 317 张包含病毒性肺炎和正常胸部 X 光片的图像,已经结构化为测试集和训练集目录。

该引用来自 蒙特利尔大学,列出的合作者是 Pranav Raikote(所有者),许可证:CC BY-SA 4.0choosealicense.com/licenses/cc-by-sa-4.0

现在,Pluto 已经下载了 Covid-19 数据,他将开始处理 People 数据集。

印度人民

图像预测或分类中的第二个典型类别是人物。Pluto 选择了 印度人民 数据集。以下是 Python Notebook 中的一段代码,它获取并加载数据到 pandas:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/sinhayush29/indian-people')
# import to Pandas DataFrame
f = 'kaggle/indian-people/Indian_Train_Set'
pluto.df_people = pluto.make_dir_dataframe(f)

Kaggle 网站上,数据集没有描述。没有解释或目标的情况并不少见,人们会被要求对其进行补充。列出的合作者是 Ayush Sinha(所有者),许可证:无,公开可见

人物数据的典型用途是识别或分类年龄、性别、种族、情感倾向、面部识别等。

有趣的事实

有一些有争议的图像分类人工智能系统,例如预测人们是否是罪犯、预测对社会的价值、识别性取向以及选择移民或公民。然而,其他创造性的用途包括识别潜在的新“鲸鱼”——来自某赌场的超级高消费客户,通过在大厅安装摄像头并将数据输入人工智能系统。

现在,让我们看看真菌数据。

可食用和有毒的真菌

图像分类中第三个最常用的主题是安全性,比如分心的驾驶员、有毒的蛇或癌症肿瘤。Pluto 在 Kaggle 网站上找到了真实世界的 可食用和有毒的真菌 数据集。以下是 Python Notebook 中的一段代码,它获取并加载数据到 pandas:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/marcosvolpato/edible-and-poisonous-fungi')
# import into Pandas data frame
f = 'kaggle/edible-and-poisonous-fungi'
pluto.df_fungi = pluto.make_dir_dataframe(f)

Kaggle 网站上,描述如下:

我们创建这个数据集是作为我们学校研究项目的一部分。由于我们在开始时没有找到类似的东西,我们决定在这里发布它,以便未来关于蘑菇和人工智能的研究能够受益于它。

列出的合作者是Marcos Volpato(所有者),许可证:开放数据公约开放数据库许可证(****ODbL)opendatacommons.org/licenses/odbl/1-0/

现在,我们来看看海洋动物数据。

海洋动物

第四个主题是自然。Pluto 选择了海洋动物图像数据集。以下命令将数据抓取并加载到 pandas 中:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/vencerlanz09/sea-animals-image-dataste')
# import to Pandas data frame
f = 'kaggle/sea-animals-image-dataste'
pluto.df_sea_animal = pluto.make_dir_dataframe(f)

Kaggle 网站对此数据集的描述如下:

大多数生命形式的进化始于水生环境。海洋提供了世界 90% 的生活空间(按体积计算)。鱼类是唯一生活在水中的脊椎动物,它们是已知的第一批脊椎动物。这些鱼类中的一些转变为两栖动物,它们在白天的部分时间里生活在陆地和水域中。

列出的合作者是Vince Vence(所有者),许可证:其他——教育用途和商业使用免费(****FFCU)www.flickr.com/people/free_for_commercial_use/

接下来,我们将查看食品数据。

越南食品

第五个广泛应用于图像分类的主题是食品。Pluto 找到了30VNFoods – 越南食品图像识别数据集。以下命令将数据抓取并加载到 pandas 中:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/quandang/vietnamese-foods')
# import to Pandas DataFrame
f = 'kaggle/vietnamese-foods/Images/Train'
pluto.df_food = pluto.make_dir_dataframe(f)

Kaggle 网站的描述如下:

本文介绍了一个包含 25,136 张关于 30 种受欢迎越南食品的图像的大型数据集。多种机器学习和深度学习图像分类技术已经应用于测试此数据集,结果被比较并报告。

列出的合作者是Quan Dang(所有者),Anh Nguyen Duc Duy(编辑),Hoang-Nhan Nguyen(查看者),Phuoc Pham Phu(查看者),Tri Nguyen(查看者),许可证:CC BY-SA 4.0choosealicense.com/licenses/cc-by-sa-4.0

现在,我们来看看购物中心人群数据。

购物中心人群

Pluto 选择了第六个也是最后一个数据集,用于创意的 AI 图像分类——购物中心 - 人群估算数据集。以下 Python Notebook 代码片段将数据抓取并加载到 pandas 中:

# fetch image data
pluto.fetch_kaggle_dataset('https://www.kaggle.com/datasets/ferasoughali/mall-crowd-estimation')
# import to Pandas DataFrame
f = 'kaggle/mall-crowd-estimation/mall_dataset/frames'
pluto.df_crowd = pluto.make_dir_dataframe(f)

Kaggle 网站的描述如下:

“购物中心数据集是从一个公开可访问的网络摄像头收集的,用于人群计数和画像研究。”

列出的合作者是Feras(所有者),许可证:无,公开可见

有趣的挑战

重构提供的代码并编写一个函数来下载所有六个数据集。提示:将六个Kaggle数据集的 URL 放入一个数组中。Pluto 不编写超大方法,因为他专注于让增强技术更易于理解,而不是编写可能使意义模糊的紧凑代码。

下载完所有六个数据集后,Pluto 必须绘制图像批次。

绘制图像批次

让我们看看这六个数据集中的图片。Pluto 将从 pandas DataFrame 中提取样本,并使用在第二章中定义的draw_batch()函数。

以下是两张 Covid-19 图片、两个人物图片、两张真菌图片、两张海洋动物图片、一张食物图片和一张商场人群图片的输出:

图 3.9 – 六个图像数据集

图 3.9 – 六个图像数据集

Pluto 已经下载了大量真实世界的图片,接下来的步骤是选择一个图像增强库。

图像增强库

有许多开源的 Python 图像增强和处理库。大多数库提供几何和光度变换的滤镜。此外,少数库针对特定的图像主题提供了专门的功能。

Pluto 只会介绍其中的一部分库。最流行的库有 Albumentations、Fast.ai、Pillow (PIL)、OpenCV、scikit-learn、Mahotas 和 pgmagick:

  • Albumentations 是一个快速且高度可定制的 Python 图像增强库。它已经成为与计算机视觉和深度学习相关研究领域的事实标准。Albumentations 高效地实现了超过 70 种图像变换操作,并且在性能上进行了优化。Albumentations 的显著优势在于它与许多深度学习框架的广泛集成。该库于 2019 年推出,可以在 GitHub 上找到:github.com/albumentations-team/albumentations

  • Fast.ai 是一个顶级的深度学习和人工智能库与框架。它由 Jeremy Howard 和 Rachel Thomas 于 2016 年创立,旨在使深度学习更加普及。Fast.ai 提供了广泛的内建功能用于图像增强。此外,它的图像增强操作使用 GPU,因此可以在训练周期中进行动态图像增强。换句话说,由于 GPU 的加持,它是市场上性能最强的图像增强库。可以在 GitHub 上找到它:github.com/fastai

  • PillowPython Imaging Library (PIL) 库的现代友好分支。PIL 是一个流行的开源图像处理与增强库,最早发布于 1995 年。许多开源的 Python 图像处理、显示和增强库都基于 PIL 构建。可以在 GitHub 上找到它:github.com/python-pillow/Pillow

  • AugLy 是 Meta(Facebook)推出的一个开源 Python 数据增强项目。该库提供了超过 100 种音频、视频、图像和文本数据增强方法。可以在 GitHub 上找到它:github.com/facebookresearch/AugLy

  • OpenCV是英特尔于 2000 年开发的开源库。机器学习主要在计算机视觉任务中使用 OpenCV,例如物体分类和检测、人脸识别以及图像分割。此外,OpenCV 还包含了机器学习的基本方法。可以在 GitHub 上找到:github.com/opencv/opencv

  • scikit-learn是 2009 年早期发布的开源图像增强库之一。部分 scikit-learn 是用 Cython 编写的,Cython 是一种 Python 的超集编程语言。其主要优点之一是高性能速度,使用 NumPy 数组作为图像的结构。可以在 GitHub 上找到:github.com/scikit-image/scikit-image

  • Mahotas是一个专注于生物图像信息学的图像处理与增强库。Mahotas 使用 NumPy 数组,并且是用 C++编写的,提供 Python 接口。它于 2016 年发布。可以在 GitHub 上找到:github.com/luispedro/mahotas

  • pgmagick:pgmagick 是 Python 的 GraphicsMagick 绑定库。GraphicsMagick 最著名的是支持大尺寸图像,达到吉像素级别。它最初源自于 2002 年的 ImageMagick。可以在 GitHub 上找到:github.com/hhatto/pgmagick

没有哪个库比另一个更好,你可以在项目中使用多个库。然而,Pluto 建议选择两三个库,并在它们上面精通,甚至成为专家。

Pluto 将隐藏库或多个库,并创建一个包装函数,例如draw_image_flip(),该函数使用其他库来执行转换。编写包装函数的另一个原因是切换库并尽量减少代码更改。Pluto 在本章中选择了AlbumentationsFast.aiPIL库作为幕后引擎。

你有两种选择:每批次动态地创建图像增强,或静态创建。当采用静态方法时,也称为预处理,你需要在本地或云驱动器中创建并保存增强后的图像。

在本章中,Pluto 选择动态增强图像,因为根据滤镜的组合,你可以生成超过一百万张合格的变化图像。这两种方法的唯一区别是,预处理方法将增强后的图像保存到本地或云驱动器,而动态方法则不保存。

有趣的挑战

这里有一个思维实验:你应该选择一个拥有更多增强方法的增强库,还是选择一个支持 GPU 的库?提示:考虑你的项目目标以及其磁盘和时间资源。

让我们开始为几何变换滤镜编写代码。

几何变换滤镜

Pluto 可以编写许多几何变换滤镜的 Python 代码,他将选择两个或三个图像数据集来说明每个概念。此外,通过使用多个图像主题,他可以发现安全级别。安全级别的范围是主观的,您可能需要咨询领域专家,以了解照片应扭曲到什么程度。在方便的情况下,Pluto 会使用不同的库编写相同的方法。

让我们开始翻转图像吧。

翻转

Pluto 将从最简单的滤镜开始:水*翻转。它会镜像图像,换句话说,它沿 Y 轴翻转照片。包装函数被称为draw_image_flip()。所有的图像增强方法都以draw_image_为前缀,这样方便 Pluto 记住它们。此外,他可以使用 Python Notebook 的自动完成输入功能。通过输入pluto.draw_im,将弹出一个包含所有滤镜函数的菜单。

draw_image_flip_pil()函数中,使用 PIL 库时,相关代码行如下:

# use PIL to flip horizontal
mirror_img = PIL.ImageOps.mirror(img)

因此,Pluto 从人物数据集中选择一张图像,并使用以下代码进行翻转:

# Select an image from Pandas and show the original and flip
pluto.draw_image_flip_pil(pluto.df_people.fname[100])

结果如下,原始图像位于顶部,翻转后的图像位于底部:

图 3.10 – 使用 PIL 库进行水*翻转

图 3.10 – 使用 PIL 库进行水*翻转

与一次查看一张图片不同,一次查看整个数据集的一个批次更有利。这是因为一个滤镜可能适用于一张图像,或者安全范围对于某一张图像可接受,但对于同一数据集中的另一张图像则不可接受。Fast.ai库有一个数据批处理类,支持许多机器学习功能,包括接受转换方法并显示一组随机图片,这也叫做显示一个批次。

Pluto 将编写两个新方法:_make_data_loader(),这是一个辅助函数,用于创建draw_image_flip()函数,该函数对水*翻转进行编码并使用数据加载器show_batch()方法显示图像批次。

show_batch()将随机选择一组图片进行显示,其中max_n设置每批图片的数量。Fast.ai 的转换默认以 75%的概率进行修改。换句话说,数据集中的四张图像中有三张会被转换。

水*翻转滤镜没有安全级别,无论它是否适用于图像集。Pluto 将使用draw_image_flip()方法并设置aug值,这有所不同。整个翻转包装器代码如下:

# use fast.ai to flip image in wrapper function
def draw_image_flip(self,df,bsize=15):
  aug = [fastai.vision.augment.Flip(p=0.75)]
  item_fms = fastai.vision.augment.Resize(480)
  dsl_org = self._make_data_loader(df, aug,item_fms)
  dsl_org.show_batch(max_n=bsize)
  return dsl_org

aug变量的定义因包装函数不同而有所不同。Pluto 需要在 Python Notebook 中运行一个针对人物数据集的函数,代码如下:

# Show random flip-image batch 15 in Pandas, wraper function
pluto.dls_people = pluto.draw_image_flip(pluto.df_people)

结果如下:

图 3.11 – 人物数据集上的水*翻转

图 3.11 – 人物数据集上的水*翻转

趣味小知识

完整的面向对象代码可以在 Python Notebook 中找到。您可以入侵以显示翻转、旋转、倾斜和其他几十种增强技术。

要确保水*翻转可接受,您可以在 Python Notebook 中重复运行 draw_image_flip() 函数,以查看各种不同的图像批次。水*翻转适用于菌类、海洋动物、食物和商场人群的图片。常识告诉我们,不会有其他预期。以下是菌类数据集的命令:

# use flip wrapper function on Fungi data
pluto.dls_fungi = pluto.draw_image_flip(pluto.df_fungi)

结果如下:

图 3.12 – 菌类数据集的水*翻转

图 3.12 – 菌类数据集的水*翻转

对于医学图像,如 Covid-19 照片,您需要专业领域的专家确认水*翻转不会改变图像的完整性。对于外行人来说,这没有任何区别,但可能会产生误报或漏报。以下是相应的命令:

# use flip wrapper function on covid data
pluto.dls_covid19 = pluto.draw_image_flip(pluto.df_covid19)

结果如下:

图 3.13 – Covid-19 数据集的水*翻转

图 3.13 – Covid-19 数据集的水*翻转

注意,Fast.ai 转换裁剪了图像的中心正方形。因此,在某些图片中,内容会丢失 – 例如,一个大部分面部缺失的女性照片。这是因为 Fast.ai 用于机器学习,所以图像需要是正方形的。默认行为是中心正方形裁剪。

在冥王星开始裁剪和填充之前,他必须通过将水*翻转与垂直翻转结合起来来完成翻转过滤器。人群、Covid-19、菌类和商场人群图片不能垂直翻转,但海洋动物和食品图片可以。

对于此操作,冥王星需要创建 draw_image_flip_both() 方法,并将转换设置为以下内容:

# using fast.ai for fliping
aug = fastai.vision.augment.Dihedral(p=0.8,pad_mode=pad_mode)

现在,冥王星必须使用以下代码在人群数据集上运行该函数:

# use wrapper function on both flip on people images
pluto.dls_people = pluto.draw_image_flip_both(
  pluto.df_people)

结果如下:

图 3.14 – 人群数据集的不安全水*和垂直翻转

图 3.14 – 人群数据集的不安全水*和垂直翻转

他可以将同样的函数应用于食品图片,如下所示:

# use flip wrapper function on food photos
pluto.dls_food = pluto.draw_image_flip_both(pluto.df_food)

结果如下:

图 3.15 – 食品数据集的安全水*和垂直翻转

图 3.15 – 食品数据集的安全水*和垂直翻转

有趣的事实

冥王星喜欢一遍又一遍地玩同一个游戏。你知道,因为他是一只狗。😃 因此,您可以要求冥王星在 Python Notebook 上重复运行任何包装函数,以查看存储在 pandas 中的数据的不同图像批次。每个现实世界的图像数据集包含数千张照片,每批显示 15 张图片;因此,您必须重复运行包装函数,以对数据集有一个良好的思维图像。

接下来我们将看看裁剪和填充的过滤器。

裁剪和填充

复用与编写翻转过滤器时相同的过程,Pluto 可以编写 draw_image_crop() 方法。新的代码行使用了不同的项变换:

# use fast.ai to crop image in wrapper function
item_tfms=fastai.vision.augment.CropPad(480,
   pad_mode="zeros")

填充模式可以是零填充,即填充颜色为黑色;边框填充,即填充重复边缘像素;或者镜像填充,即填充内容为图片的镜像。

经过多次尝试和调整,Pluto 在 Python Notebook 中找到了每个六个数据集的安全裁剪和填充范围。在继续之前,Pluto 鼓励你使用 Python Notebook 找出最佳安全参数。

Pluto 发现对于 people 数据集的安全设置是裁剪后的图像大小为 640,并使用边框填充模式:

# use wrapper function to crop and pad people photo
pluto.dls_people = pluto.draw_image_crop(pluto.df_people,
  pad_mode="border",
  isize=640)

结果如下:

图 3.16 – 对 People 数据集进行水*和垂直翻转

图 3.16 – 对 People 数据集进行水*和垂直翻转

对于下一个数据集,Pluto 发现 fungi 图像的安全设置是裁剪后的图像大小为 240,并使用零填充模式:

# use wrapper function to crop and pad Fungi image
pluto.dls_fungi = pluto.draw_image_crop(pluto.df_fungi,
  pad_mode="zeros",
  isize=240)

结果如下:

图 3.17 – 对 fungi 数据集进行水*和垂直翻转

图 3.17 – 对 fungi 数据集进行水*和垂直翻转

对于食物图片,Pluto 发现安全参数是裁剪后的图像大小为 640,填充模式为镜像填充:

# use wrapper function to crop and pad food image
pluto.dls_food = pluto.draw_image_crop(pluto.df_food,
  pad_mode="reflection",
  isize=640)

结果如下:

图 3.18 – 对食物数据集进行水*和垂直翻转

图 3.18 – 对食物数据集进行水*和垂直翻转

有趣的挑战

找到所有六个图像数据集的安全裁剪参数。如果你能将这些新功能应用到你项目中的图像集或从 Kaggle 网站下载的图像,你将获得额外的加分。

对于其他图像数据集,结果已在 Python Notebook 中。对于海洋动物图像,安全参数为 340 像素,并使用镜像填充;对于商场人群图像,安全参数为 512 像素,并使用边框填充。Covid-19 图片不适用裁剪过滤器。

接下来,Pluto 将进行图像旋转,这与翻转类似。

旋转

旋转指定图像顺时针或逆时针旋转多少度。由于 Pluto 设置了最大旋转值,因此实际旋转角度是在最小值和最大值之间的一个随机数。最小默认值为零。因此,较高的最大值会生成更多的增强图像,因为每次系统获取新的数据批次时,都会选择不同的旋转值。此外,随机性也是选择动态增强选项而非将图像保存到本地硬盘的原因,就像静态选项那样。

为此,Pluto 编写了 draw_image_rotate() 方法,使用 max_rotate = max_rotate 变换参数,其中第二个 max_rotate 是传入的值。包装函数中的关键代码行如下:

# use fast.ai for rotating
aug = [fastai.vision.augment.Rotate(max_rotate,
  p=0.75,
  pad_mode=pad_mode)]

再次,Pluto 在经过多次试验后,在 Python Notebook 上找到了旋转的安全参数,但不要仅仅相信 Pluto 的说法。Pluto 挑战你通过实验 Python Notebook 找出更好的安全参数。

对于海洋动物数据,Pluto 找到了一个安全的最大旋转参数 180.0,并使用反射进行填充。Python Notebook 中的命令如下:

# use wrapper function to rotate sea animal photo
pluto.dls_sea_animal = pluto.draw_image_rotate(
  pluto.df_sea_animal,
  max_rotate=180.0,
  pad_mode='reflection')

结果如下:

图 3.19 – 海洋动物数据集上的旋转

图 3.19 – 海洋动物数据集上的旋转

对于人物图片,Pluto 找到了一个安全的最大旋转参数 25.0,并使用边框进行填充。Python Notebook 中的命令如下:

# user wrapper function to rotate people photo
pluto.dls_people = pluto.draw_image_rotate(pluto.df_people,
  max_rotate=25.0,
  pad_mode='border')

结果如下:

图 3.20 – 人物数据集上的旋转

图 3.20 – 人物数据集上的旋转

对于其他图像数据集,结果已记录在 Notebook 中。安全参数为:对于购物中心人群照片,最大旋转角度为 16.0,并使用边框填充;对于真菌照片,最大旋转角度为 45.0,并使用边框填充;对于食物图像,最大旋转角度为 90.0,并使用反射填充;对于 Covid-19 数据,最大旋转角度为 12.0,并使用零边框填充。我鼓励你在 Notebook 上超出 Pluto 的安全范围进行实验,亲自看看图像会发生什么。

现在,让我们继续探索移动图像的主题。下一个我们要看的滤镜是*移滤镜。

翻译

*移滤镜将图像向左、右、上或下移动。它不是最常用的滤镜之一。Pluto 在 draw_image_shift() 函数中使用了 ImageChops.offset() 方法。负的水*偏移值将图像向左移动,正值将图像向右移动,垂直偏移参数将图像向上或向下移动。包装函数中的相关代码行如下:

# using PIL for shifting image
shift_img = PIL.ImageChops.offset(img,x_axis,y_axis)

为了测试功能,Pluto 选择了一张图片,并将其向左移动 150 像素,向上移动 50 像素。命令如下:

# select an image in Pandas
f = pluto.df_people.fname[30]
# user wrapper function to shift the image
pluto.draw_image_shift_pil(f, -150, -50)

输出如下:

图 3.21 – 使用 PIL 库进行*移;上图为原图

图 3.21 – 使用 PIL 库进行*移;上图为原图

*移滤镜很少使用,因为它很容易为一张图片找到安全水*,但对于整个数据集来说却不容易找到。

到目前为止,Pluto 已经展示了 翻转裁剪填充调整大小旋转*移 等滤镜。然而,还有许多其他几何变换滤镜,如 扭曲缩放倾斜缩放比例。不幸的是,种类繁多,无法全部涵盖,但编码过程是相同的。

有趣的挑战

实现另外两种几何变换技术,例如扭曲和倾斜。提示:从 Pluto 的包装函数中复制并粘贴,修改 augitem_tfms 变量。

从几何变换到光度变换遵循相同的编码过程。首先,Pluto 使用 Albumentations 库编写包装函数,然后使用实际的图像数据集进行测试。

摄影变换

Pluto 选择了 Albumentations 库来支持光度变换。主要原因是 Albumentations 库提供了超过 70 种滤镜,而且可以将其集成到 Fast.ai 框架中。Fast.ai 提供了大多数基本的光度滤镜,例如色调偏移、对比度和光照调整,但只有 Albumentations 提供了更多复杂的滤镜,比如添加雨、运动模糊和 FancyPCA。使用这些高级滤镜时要小心。虽然它们很容易实现,但你应该查阅 AI 学术论文,了解这些滤镜是否对提高准确率有所帮助。

与几何变换的编码过程一样,Pluto 创建基础方法并为每个光度变换编写包装函数。_draw_image_album() 方法用于从数据中选择一个样本集,将其转换为 numpy 数组,执行变换,并以批处理模式显示它们。_draw_image_album() 函数的相关代码如下:

# select random images
samp = df.sample(int(ncol * nrow))
# convert to an array
img_numpy = numpy.array(PIL.Image.open(samp.fname[i]))
# perform the transformation using albumentations
img = aug_album(image=img_numpy)['image']
# display the image in batch modde
ax.imshow(img)

包装函数的代码很简单。例如,亮度滤镜的代码如下:

def draw_image_brightness(self,df,
  brightness=0.2,
  bsize=5):
  aug_album = albumentations.ColorJitter(
    brightness = brightness,
    contrast=0.0,
    saturation=0.0,
    hue=0.0,
    always_apply=True,
    p=1.0)
  self._draw_image_album(df,aug_album,bsize)
  Return

趣味小知识

对于任何 Albumentations 函数,你可以在函数后附加一个问号 (?),并运行代码单元来查看 Python Notebook 中的文档;例如,albumentations.ColorJitter?。附加两个问号 (??) 可以查看该函数的 Python 源代码;例如,albumentations.ColorJitter??。一个有趣的事实是,Albumentations 类型后面跟着一个点——例如,albumentations.——然后稍等片刻。在下拉列表中会显示所有可用的函数,你可以选择其中一个。换句话说,Python Notebook 支持自动完成功能。

aug_albm 变量的定义因包装函数而异。让我们来测试一下亮度滤镜。

亮度

由于你是在书中阅读,大多数光度变换在灰度下难以查看。这更加强调了将 Pluto 与 Notebook 中的编码结合起来的重要性,因为你可以看到颜色。Pluto 不会为每个滤镜显示所有最佳的安全参数,而是会展示一个数据集的 不安全 范围和另一个数据集的安全参数。包装函数中与亮度相关的关键代码行如下:

# use the Albumentations library function for brightness
aug_album = albumentations.ColorJitter(brightness=brightness,
  contrast=0.0,
  saturation=0.0,
  hue=0.0,
  always_apply=True,
  p=1.0)

你可以通过夸大亮度来看到书中的错误——例如,如果图像过亮或过暗。再次提醒,应该在 Notebook 中查看亮度效果的颜色。对于人物照片,不安全 的值是亮度等于 1.7。Pluto 在 Python Notebook 中运行以下命令:

# use the brightness wrapper function for people photo
pluto.draw_image_brightness(pluto.df_people, brightness=1.7)

输出如下:

图 3.22 – 人物数据集的不安全亮度水*

图 3.22 – 人物数据集的不安全亮度水*

人物数据集没有明确的目标。因此,找出安全的参数较为困难。如果目标仅仅是分类人们的年龄,亮度水*可以相对较高,但在不知道数据集的预期用途的情况下,你无法知道应该扭曲多少图片。

Pluto 发现食品数据集的安全亮度值为0.3,但在本书中可能不容易看到效果。以下是他在 Python Notebook 中使用的命令:

# use the brightness wrapper function for food image
pluto.draw_image_brightness(pluto.df_food, brightness=0.3)

输出如下:

图 3.23 – 食品数据集的安全亮度水*

图 3.23 – 食品数据集的安全亮度水*

其他四个数据集的亮度水*类似。Pluto 将实验的任务交给你,你可以在 Python Notebook 中尝试并找到安全的亮度水*。Covid-19 图像是灰度图像,目的是通过胸部 X 光照片预测 Covid-19 患者。亮度水*的增加或减少可能导致假阳性或假阴性预测。你应该与领域专家咨询,以确认 Covid-19 图像的安全参数。

本章前半部分没有讨论灰度滤镜,但它与亮度滤镜相似。

灰度

一些学术论文描述了灰度的好处,例如 2021 年由 Jinyeong Wang 和 Sanghwan Lee 在《Data Augmentation Methods Applying Grayscale Images for Convolutional Neural Networks in Machine Vision》一文中提出,来自韩国首尔汉阳大学机械融合工程系(Hanyang University, Seoul 04763, Korea)。该论文解释了在基于卷积神经网络(CNN)和单目摄像头的机器视觉中,应用灰度图像的数据增强方法。

draw_image_grayscale()方法中,Pluto 使用了如下的 Albumentations 库函数:

# use albumentations for grayscale
aug_album = albumentations.ToGray(p=1.0)

真菌数据集的目标是分类蘑菇是可食用的还是有毒的,而蘑菇的颜色会显著影响分类。因此,转换为灰度图像是不建议的。然而,Pluto 通过以下命令演示了灰度滤镜:

# use the grayscale wrapper function for fungi image
pluto.draw_image_grayscale(pluto.df_fungi)

输出如下:

图 3.24 – 在真菌数据集上不安全的灰度使用

图 3.24 – 在真菌数据集上不安全的灰度使用

商场人群数据集的目标是估计商场内的人员数量。因此,将照片转换为灰度图像不应影响预测。Pluto 执行了以下命令:

# use the grayscale wrapper function for crowd photo
pluto.draw_image_grayscale(pluto.df_crowd)

结果如下:

图 3.25 – 在商场人群数据集上安全使用灰度

图 3.25 – 在商场人群数据集上安全使用灰度

Pluto 已为你留下了其他四个数据集,你可以实验并确定是否可以安全使用灰度滤镜。使用 Python Notebook 探索这些数据集后,回来这里,我们将一起研究对比度、饱和度和色相偏移滤镜。

对比度、饱和度和色相偏移

对比度、饱和度和色相偏移滤镜是有益的。它们已被证明有助于训练 AI 模型,从而提高准确率,例如 Luke Taylor 和 Geoff Nitschke 于 2017 年在 Arxiv 网站上发布的学术论文《Improving Deep Learning using Generic Data Augmentation》中就有论述。

对比度、饱和度和色相偏移的包装函数代码在 Albumentations 库中非常简单。我们来看看:

# for contrast
aug_album = albumentations.ColorJitter(brightness=0.0,
  contrast=contrast, saturation=0.0,
  hue=0.0, always_apply=True, p=1.0)
# for saturation
aug_album = albumentations.ColorJitter(brightness=0.0,
  contrast=0.0, saturation=saturation,
  hue=0.0, always_apply=True, p=1.0)
# for hue shifting
aug_album = albumentations.ColorJitter(brightness=0.0,
  contrast=0.0, saturation=0.0,
  hue=hue, always_apply=True, p=1.0)

Pluto 已将 不安全 值夸大,以便你能在本书中看到结果。海洋动物数据集中对比度的 不安全 参数如下:

# use the contrast wrapper function on sea animal image
pluto.draw_image_contrast(pluto.df_sea_animal,
  contrast=8.5,
  bsize=2)

输出如下:

图 3.26 – 在海洋动物数据集上不安全使用对比度

图 3.26 – 在海洋动物数据集上不安全使用对比度

食品数据集中饱和度的 不安全 参数如下:

# use the contrast wrapper function on food image
pluto.draw_image_saturation(pluto.df_food,
  saturation=10.5)

输出如下:

图 3.27 – 在食品数据集上不安全使用饱和度

图 3.27 – 在食品数据集上不安全使用饱和度

人物数据集中色相偏移的 不安全 参数如下:

# use the contrast wrapper function on people photo
pluto.draw_image_hue(pluto.df_people,hue=0.5)

输出如下:

图 3.28 – 在人物数据集上不安全使用色相偏移

图 3.28 – 在人物数据集上不安全使用色相偏移

对比度、饱和度和色相偏移适用于五个图像数据集,关键是找到每个数据集的安全范围。例外的是医学图像——Covid-19 照片。你需要咨询领域专家,以了解你可以在多大程度上扭曲图像而保持其完整性。

有趣的挑战

这是一个思想实验:你能想到一个可以安全使用色相偏移的图像类别吗?换句话说,在哪种照片主题中,你可以改变色相值而不损害图像的完整性?提示:想想通过声纳或热源捕猎的动物。

接下来我们将介绍噪声注入滤镜,它可以在本书的灰度图像中轻松识别。

噪声注入

噪声注入是一个奇怪的滤镜,因为它是反直觉的。图像增强在安全范围内扭曲原始图像,但向照片中注入噪声会故意使图像退化。

Murtaza Eren Akbiyik 于 2019 年发布的学术论文《Data Augmentation in Training CNNs: Injecting Noise to Images》,并在 ICLR 2020 Conference 上进行了评审,分析了将不同噪声模型应用于 CNN 架构的效果。论文显示,噪声注入有助于更好地理解图像分类的最佳学习程序。

对于draw_image_noise()封装方法,Pluto 使用了 Albumentation 的高斯噪声方法,如下所示:

# use Albumentations for noise injection
aug_album = albumentations.GaussNoise(var_limit=var_limit,
  always_apply=True,
  p=1.0)

Pluto 将噪声水*提升到极限,用于夸张的不安全案例。Python 笔记本中的命令如下:

# use noise wrapper function on fungi photo
pluto.draw_image_noise(pluto.df_fungi,
  var_limit=(10000.0, 20000.0), bsize=2)

输出如下:

图 3.29 – 在真菌数据集上不安全使用噪声注入

图 3.29 – 在真菌数据集上不安全使用噪声注入

由于商场人群数据集的目标是估计人群数量,因此在图像中加入一些噪声是可以接受的。Pluto 发现,安全的噪声水*大约在200400之间。命令如下:

# use noise wrapper function on crowd image
pluto.draw_image_noise(pluto.df_crowd,
  var_limit=(200.0, 400.0),
  bsize=2)

输出如下:

图 3.30 – 在商场人群数据集上安全使用噪声注入

图 3.30 – 在商场人群数据集上安全使用噪声注入

有趣的挑战

这里有一个思考和动手实验。你能为每种图像增强定义一个适用于特定图像主题(如风景、鸟类或家用电器)的范围吗?如果你认为这可能,能否编写一个使用 Pluto 封装函数的 Python 函数?

这是 Pluto 开始尝试更为异域的滤镜时,但他将选择限制在已发表学术论文中研究过的图像增强方法。接下来我们将看两个滤镜:雨和阳光光晕滤镜。

雨和阳光光晕

在图像增强中,雨和阳光光晕效果在 AI 中并不广泛使用。然而,如果图像领域是风景或城市风景,则这是一个可接受的选择。雨和阳光光晕的实现相对简单,因为它们优化的是速度,而非雨或阳光光晕的逼真表现。

如果你需要自然的雨效果,可以参考一篇提出使用生成对抗网络GAN)合成逼真雨景的新方法的论文:《合成雨图像用于去雨算法》,由 Jaewoong Choi、Dae Ha Kim、Sanghyuk Lee、Sang Hyuk Lee 和 Byung Cheol Song 于 2022 年在Neurocomputing 第 492 卷上发表。

由于逼真渲染需要一些时间,因此你应使用预处理增强方法,该方法生成图像并将其保存到本地或云磁盘存储中,然后再训练 AI 模型。

Pluto 无法使用 GAN 方法,因此他使用 Albumentations 库来动态生成效果。draw_image_rain()draw_image_sunflare()封装函数中的关键代码如下:

# for rain
aug_album = albumentations.RandomRain(
  drop_length = drop_length,
  drop_width=drop_width,
  blur_value=blur_value,
  always_apply=True,
  p=1.0)
# for sun flare
aug_album = albumentations.RandomSunFlare(
  flare_roi = flare_roi,
  src_radius=src_radius,
  always_apply=True, p=1.0)

Pluto 将阳光光晕滤镜的效果夸大到不安全的水*。命令如下:

# use sunflare wrapper function with people photo
pluto.draw_image_sunflare(pluto.df_people,
  flare_roi=(0, 0, 1, 0.5),
  src_radius=400,
  bsize=2)

输出如下:

图 3.31 – 在人群数据集上不安全使用阳光光晕滤镜

图 3.31 – 在人群数据集上不安全使用阳光光晕滤镜

Pluto 发现,安全的真菌数据集噪声水*是120的半径,flare-roi(0, 0, 1)。命令如下:

# use the sunflare wrapper function on fungi image
pluto.draw_image_sunflare(pluto.df_fungi, src_radius=120)

输出如下:

图 3.32 – 在真菌数据集上安全使用太阳耀斑滤镜

图 3.32 – 在真菌数据集上安全使用太阳耀斑滤镜

对于 People 数据集,Pluto 发现安全参数是 drop_length 等于 20drop_width 等于 1blur_value 等于 1

# use the rain wrapper function on people photo
pluto.draw_image_rain(pluto.df_people, drop_length=20,
  drop_width=1, blur_value=1)

结果如下:

图 3.33 – 在 People 数据集上安全使用雨滤镜

图 3.33 – 在 People 数据集上安全使用雨滤镜

还有许多其他光度变换可用;例如,Albumentations 提供了超过 70 种图像滤镜。然而,目前 Pluto 将展示两个其他效果:褐色和 FancyPCA 滤镜。

褐色和 FancyPCA

褐色滤镜涉及将颜色调节为棕色。这种棕色类似于墨鱼墨汁的颜色,效果类似于旧照片或经过岁月洗礼的图片。Fancy 主成分分析 (FancyPCA) 色彩增强会沿着图像的自然变化改变 RGB 通道的强度。

一篇学术研究论文使用 FancyPCA 滤镜提高了深度学习预测储层岩性属性的准确性:2022 年,Dokyeong Kim, Junhwan Choi, Dowan Kim 和 Joongmoo Byun 发表的《使用深度神经网络和 Fancy PCA 预测矿物学》一文,在 SEG 国际博览会及年会 上展示。

对于 draw_image_sepia()draw_image_fancyPCA() 包装函数,Pluto 使用了 Albumentations 库:

# for sepia use albumentations library
aug_album = albumentations.ToSepia(always_apply=True, p=1.0)
# for FancyPCA use albumentations library
aug_album = albumentations.FancyPCA(alpha=alpha,
  always_apply=True,
  p=1.0)

你可以在 Python Notebook 的彩色输出图像中看到结果。Pluto 选择 People 数据集来试验褐色和 FancyPCA 滤镜,因为它没有特定目标。假设目标是对人群的年龄范围进行分类,这两个滤镜都适用。对于褐色滤镜,命令如下:

# use the sepia wrapper function on people photo
pluto.draw_image_sepia(pluto.df_people)

输出结果如下:

图 3.34 – 在 People 数据集上安全使用褐色滤镜

图 3.34 – 在 People 数据集上安全使用褐色滤镜

Pluto 将 FancyPCA 滤镜的效果提高到一个不安全的水*,通过将 alpha 值设置为 5.0。命令如下:

# use fancyPCA wrapper function on people photo
pluto.draw_image_fancyPCA(pluto.df_people,alpha=5.0,bsize=2)

结果如下:

图 3.35 – 在 People 数据集上不安全使用 FancyPCA

图 3.35 – 在 People 数据集上不安全使用 FancyPCA

到目前为止,你和 Pluto 已经为光度变换编写了许多包装函数,例如照明、灰度、对比度、饱和度、色调变化、噪声注入、雨、太阳耀斑、褐色和 FancyPCA。但在 Albumentations 库中还有更多的图像滤镜。Pluto 遵循黄金图像增强法则,选择能够提高预测准确度的滤镜,正如一篇已发布的学术论文所描述的那样,例如 Luis Perez, Jason Wang 所著的《使用深度学习的图像分类中数据增强的有效性》一文,发表于 2017 年 12 月的 Cornell University Arxiv

有趣的挑战

这里有一个思维实验:有太多的图像增强技术难以计数。那么,如何知道哪种增强功能适合使用呢?例如,电影变形照片滤镜是否是一种有效的图像增强技术?提示:考虑一下主题领域和处理速度。

在脱离摄影转换后,接下来,Pluto 将深入探讨随机擦除滤镜。

随机擦除

随机擦除添加了一块噪声,而噪声注入则是逐次添加一个像素。

两篇最*发表的论文表明,随机擦除滤镜和扩展随机擦除提高了深度学习模型的预测准确性。第一篇论文是 2020 年由 Zhun Zhong、Liang Zheng、Guoliang Kang、Shaozi Li 和 Yi Yang 提出的《随机擦除数据增强》(Random Erasing Data Augmentation),并在AAAI 人工智能会议上发表。第二篇论文是 2021 年由 Murat Saran、Fatih Nar 和 Ayşe Nurdan Saran 提出的《Perlin 随机擦除数据增强》(Perlin Random Erasing for Data Augmentation),并在第 29 届信号处理与通信应用会议Signal Processing and Communications Applications Conference,简称 SIU)上发表。

Pluto 在draw_image_erasing()封装函数中使用了 Fast.ai 库。相关代码如下:

# use fastai library for random erasing
aug = [fastai.vision.augment.RandomErasing(p=1.0,
  max_count=max_count)]
itfms = fastai.vision.augment.Resize(480)

找到随机擦除的安全级别是具有挑战性的。这取决于图像主题、深度学习基础模型和目标标签。通常,Pluto 会选择一个随机擦除安全参数并训练 AI 模型。如果深度学习模型出现过拟合现象,他会增加随机擦除的效果;如果模型的预测准确性偏离,他会减少随机擦除的参数。以下是食品数据集的安全起点:

# use random erasing wrapper function on food image
pluto.dls_food = pluto.draw_image_erasing(
  pluto.df_food,
  bsize=6,
  max_count=4)

输出结果如下:

图 3.36 – 在食品数据集上不安全地使用 FancyPCA

图 3.36 – 在食品数据集上不安全地使用 FancyPCA

目前,Pluto 每次只使用一个滤镜。接下来,他将结合多个地理和摄影转换与随机擦除。

合并

图像增强的强大之处在于,Pluto 可以将多个图像滤镜合并到一个数据集中。这将通过倍增因子增加训练图像的数量。

有趣的事实

水*翻转滤镜的默认概率设为 50%。结果是图像大小增加了一半——即total_flip = image_size + (0.5 * image_size)。当随机裁剪和填充与填充模式 3 一起使用时,图像大小将按倍数增加——即total_2_combine = total_flip + (3 * (image_size + (0.5 * image_size)) + (image_size * random_cropping_factor)),其中random_cropping_factor介于零与安全裁剪值之间,安全裁剪值小于 1.0。

本章中,Pluto 介绍了 15 种图像增强方法。因此,将大部分或全部滤镜合并到一个数据集中,将大幅增加其大小。在深度学习中,增加训练图像的总数是一种经过验证的方法,可以减少或消除过拟合问题。

针对大多数图像数据集,有一些适用的滤镜和安全参数的通用规则。然而,Pluto 遵循图像增强的黄金法则。这个黄金法则会根据照片的主题和预测模型的目标,选择使用哪些图像滤镜并设置安全参数。换句话说,每个项目的图像增强滤镜和安全参数都不相同。

在展示每个滤镜在六个真实世界图像数据集中的安全参数表之前,Pluto 必须回顾这些图像数据集的主题和目标:

  • Covid-19 数据集包含人类胸部 X 射线图像。目标是预测 Covid-19、病毒性肺炎和正常情况之间的区别。

  • People 数据集包含日常人物的照片。虽然没有明确目标,但 Pluto 假设这些图像可用于分类年龄、性别、种族、情感情绪和面部识别。

  • Fungi 数据集包含自然环境中的真菌照片。目标是预测真菌是可食用的还是有毒的。

  • Sea Animal 数据集包含海洋动物的图像,主要是水下拍摄的。目标是分类提供的 19 种海洋动物。

  • Food 数据集包含常见越南菜肴的图像。目标是对 31 种菜肴进行分类。

  • Mall Crowd 数据集包含典型购物中心中人群的图像。目标是预测人群的大小。

为了为每个图像数据集生成滤镜和安全参数表,Pluto 使用 pandas 编写了一个快速函数 print_safe_parameters(),因为他认为编程很有趣。为了提高可读性,表格分为两部分,如下所示:

图 3.37 – 每个图像数据集的安全参数 – 第一部分

图 3.37 – 每个图像数据集的安全参数 – 第一部分

图 3**.37 显示了大表格的前半部分,而 图 3**.38 显示了后半部分。

图 3.38 – 每个图像数据集的安全参数 – 第二部分

图 3.38 – 每个图像数据集的安全参数 – 第二部分

安全参数来自 Pluto 在 Python Notebook 中的探索,但你可能会找到比 Pluto 更合适的值。图像增强没有严格或固定的规则。因此,你应该使用 Python Notebook 来探索不同的可能性。如果你阅读到有关新图像增强技术的学术论文,可以使用 Albumentations 或其他图像库来实现它。

Pluto 为每个图像数据集编写了六个封装函数,通过编码强化学习。

趣味事实

你可以反复运行这个封装函数,因为它每次都会生成不同的图像集。此外,它还会从真实世界数据集中随机选择其他基础图像。因此,你可以运行一千次,只有一次会看到相同的输出。

每个封装函数定义了一组 Fast.ai 图像增强滤镜;例如:

# use fastai library for brightness and contrast
aug = [
  fastai.vision.augment.Brightness(max_lighting=0.3,p=0.5),
  fastai.vision.augment.Contrast(max_lighting=0.4, p=0.5)]
# use albumentation library
albumentations.Compose([
  albumentations.GaussNoise(var_limit=(100.0, 300.0),
    p=0.5)])

此外,包装函数使用了一个辅助方法来获取Albumentations过滤器——例如,_fetch_album_covid19()

Pluto 在 Python Notebook 中使用以下命令回顾了 Covid-19 数据集的图像增强:

# use covid 19 wrapper function
pluto.draw_augment_covid19(pluto.df_covid19)

输出如下:

图 3.39 – Covid-19 数据集的图像增强

图 3.39 – Covid-19 数据集的图像增强

人物数据集的组合过滤器的相关代码行如下:

# use both fastai and albumentation library
aug = [
  fastai.vision.augment.Brightness(max_lighting=0.3,p=0.5),
  fastai.vision.augment.Contrast(max_lighting=0.4, p=0.5),
  AlbumentationsTransform(self._fetch_album_covid19())]
# use alpbumentation library in the _fetch_albm_covid()
albumentations.Compose([
  albumentations.ColorJitter(brightness=0.3,
    contrast=0.4, saturation=3.5,hue=0.0, p=0.5),
  albumentations.ToSepia(p=0.5),
  albumentations.FancyPCA(alpha=0.5, p=0.5),
  albumentations.GaussNoise(var_limit=(300.0, 500.0), p=0.5)
  ])

Pluto 在 Python Notebook 中使用以下命令回顾了人物数据集的图像增强:

# use people wrapper function
pluto.draw_augment_people(pluto.df_people)

输出如下:

图 3.40 – 人物数据集的图像增强

图 3.40 – 人物数据集的图像增强

真菌组合过滤器的相关代码行如下:

# use both fastai and albumentations libraries
aug = [
  fastai.vision.augment.Flip(p=0.5),
  fastai.vision.augment.Rotate(25.0,p=0.5,pad_mode='border'),
  fastai.vision.augment.Warp(magnitude=0.3,
    pad_mode='border',p=0.5),
  fastai.vision.augment.RandomErasing(p=0.5,max_count=2),
  AlbumentationsTransform(self._fetch_album_fungi())]
# use albumentation inside the _fetch_album_fungi()
albumentations.Compose([
  albumentations.ColorJitter(brightness=0.3,
    contrast=0.4, saturation=2.0,hue=0.0, p=0.5),
  albumentations.FancyPCA(alpha=0.5, p=0.5),
  albumentations.RandomSunFlare(flare_roi=(0, 0, 1, 0.5),
    src_radius=200, always_apply=True, p=0.5),
  albumentations.RandomRain(drop_length=20,
    drop_width=1.1,blur_value=1.1,always_apply=True, p=0.5),
  albumentations.GaussNoise(var_limit=(200.0, 400.0), p=0.5)
  ])

Pluto 使用以下命令回顾了真菌数据集的图像增强:

# use fungi wrapper function
pluto.draw_augment_fungi(pluto.df_fungi)

输出如下:

图 3.41 – 真菌数据集的图像增强

图 3.41 – 真菌数据集的图像增强

海洋动物组合过滤器的相关代码行如下:

# use both fastai and albumentations library
aug = [
  fastai.vision.augment.Dihedral(p=0.5,
    pad_mode='reflection'),
  fastai.vision.augment.Rotate(180.0,
    p=0.5,pad_mode='reflection'),
  fastai.vision.augment.Warp(magnitude=0.3,
    pad_mode='reflection',p=0.5),
  fastai.vision.augment.RandomErasing(p=0.5,max_count=2),
  AlbumentationsTransform(self._fetch_album_sea_animal())]
# use albumentations for _fetch_album_sea_animal()
albumentations.Compose([
  albumentations.ColorJitter(brightness=0.4,
    contrast=0.4, saturation=2.0,hue=1.5, p=0.5),
  albumentations.FancyPCA(alpha=0.5, p=0.5),
  albumentations.GaussNoise(var_limit=(200.0, 400.0),
    p=0.5)])

Pluto 在 Python Notebook 中使用以下命令回顾了海洋动物数据集的图像增强:

# use the sea animal wrapper function
pluto.draw_augment_sea_animal(pluto.df_sea_animal)

输出如下:

图 3.42 – 海洋动物数据集的图像增强

图 3.42 – 海洋动物数据集的图像增强

食品组合过滤器的相关代码行如下:

# use both fastai and albumentations libraries
aug = [
  fastai.vision.augment.Dihedral(p=0.5,
    pad_mode='reflection'),
  fastai.vision.augment.Rotate(180.0,
    p=0.5,pad_mode='reflection'),
  fastai.vision.augment.Warp(magnitude=0.3,
    pad_mode='reflection',p=0.5),
  fastai.vision.augment.RandomErasing(p=0.5,max_count=2),
  AlbumentationsTransform(self._fetch_album_food())]
# use albumentation library for _fetch_album_food()
albumentations.Compose([
  albumentations.ColorJitter(brightness=0.4,
    contrast=0.4, saturation=2.0,hue=1.5, p=0.5),
  albumentations.FancyPCA(alpha=0.5, p=0.5),
  albumentations.GaussNoise(var_limit=(200.0, 400.0),
    p=0.5)])

Pluto 使用以下命令回顾了食品数据集的图像增强:

# use food wrapper function
pluto.draw_augment_food(pluto.df_food)

输出如下:

图 3.43 – 食品数据集的图像增强

图 3.43 – 食品数据集的图像增强

商场人群组合过滤器的相关代码行如下:

# use both fastai and albumentations libraries
aug = [
  fastai.vision.augment.Flip(p=0.5),
  fastai.vision.augment.Rotate(25.0,
    p=0.5,pad_mode='zeros'),
  fastai.vision.augment.Warp(magnitude=0.3,
    pad_mode='zeros',p=0.5),
  fastai.vision.augment.RandomErasing(p=0.5,max_count=2),
  AlbumentationsTransform(self._fetch_album_crowd())]
# use albumentation library for _fetch_album_crowd()
albumentations.Compose([
  albumentations.ColorJitter(brightness=0.3,
    contrast=0.4, saturation=3.5,hue=0.0, p=0.5),
  albumentations.ToSepia(p=0.5),
  albumentations.FancyPCA(alpha=0.5, p=0.5),
  albumentations.GaussNoise(var_limit=(300.0, 500.0),
    p=0.5)])

Pluto 使用以下命令回顾了商场人群数据集的图像增强:

# use the crowd wrapper function
pluto.draw_augment_crowd(pluto.df_crowd)

输出如下:

图 3.44 – 商场人群数据集的图像增强

图 3.44 – 商场人群数据集的图像增强

每次 Pluto 运行任何绘制增强方法时,都有相同的机会选择一个过滤器,并且每个图像在批次中的 50%过滤器将被应用。Pluto 可以通过 bsize 参数覆盖默认的批次大小 15。由于 Pluto 对所有过滤器采用安全范围,您可能不会注意到区别。然而,这是预期的,因为目标是扭曲图像而不破坏目标标签,直到预处理阶段。

有趣的挑战

为真实世界的数据集编写一个新的组合包装函数。如果您尚未下载或导入新的真实世界图像数据集,请现在进行下载并编写像 Pluto 那样的组合包装函数。

这是一个具有挑战性的章节。在这个章节中,你和 Pluto 一起学习了图像增强技术以及如何使用 Python 代码深入理解这些技术。现在,让我们来总结一下本章内容。

总结

本章的第一部分,你和 Pluto 一起学习了分类任务中的图像增强概念。Pluto 将滤镜分为几何变换、光度变换和随机擦除,以便让图像滤镜更加易于管理。

在处理几何变换时,Pluto 介绍了水*和垂直翻转、裁剪与填充、旋转、扭曲和位移等技术。这些滤镜适用于大多数图像数据集,还有其他几何变换,例如倾斜或扭曲。不过,Pluto 遵循了已发布学术论文中描述的金标准图像增强规则,选择那些有助于提高预测准确性的滤镜。

这个金规则更适用于光度变换,因为 Albumentations 库中大约有 70 个图像滤镜,其他图像增强库中还有数百种滤镜可用。本章介绍了在已发布的学术论文中最常用的光度变换:光照、灰度、对比度、饱和度、色调偏移、噪声注入、雨、棕褐色和 FancyPCA。你被鼓励在提供的 Python Notebook 中探索 Albumentations 库中的更多滤镜。

本章的第二部分包含了 Python 代码,用以加深你对各种图像增强技术的理解。Pluto 带你完成了从Kaggle网站下载六个真实世界图像数据集的过程。Pluto 在第二章中编写了获取数据的代码。他重用了获取函数来检索 Covid-19、人类、真菌、海洋动物、食物和购物中心人群这六个真实世界的图像数据集。

在深入代码之前,Pluto 回顾了七个流行的图像增强库:Albumentations、Fast.ai、PIL、OpenCV、scikit-learn、Mahotas 和 GraphicsMagick。Pluto 使用了 Albumentations、Fast.ai 和 PIL 库来编写这些封装函数。

这些封装函数的目标是清楚地解释每个图像滤镜。在所有情况下,函数都使用了库中的增强方法。许多光度变换在 Python Notebook 的彩色输出中更加显著。Pluto 展示了每个滤镜应用于六个图像数据集时的安全和不安全参数。你被鼓励运行甚至修改 Python Notebook 中的代码,因为没有绝对的正确或错误的安全级别。

提供了大量 Python 代码,但这些代码是简单的封装函数,遵循良好的面向对象编程(OOP)标准,没有其他方法。目标是让你深入了解每个图像滤镜,并使你能够轻松探索和修改提供的代码。

在本章结束时,Pluto 整合并创建了一个为每个图像数据集定制的图像滤波器组合表。然后,他为每个图像数据集编写了六个组合增广方法。

在本章中,包含了有趣的事实有趣的挑战。Pluto 希望你能利用这些内容,拓展你的经验,超越本章的范围。

在下一章中,我们将讨论图像分割,这一部分将重用本章中涵盖的许多图像分类功能。

第四章:图像增强用于分割

图像分割,像图像分类一样,是计算机视觉领域的基石。图像分割涉及将属于同一对象的图像部分进行分组,也称为像素级分类。与图像分类不同,图像分类是识别和预测照片的主题或标签,而图像分割则决定一个像素是否属于某个对象列表——例如,一张城市照片包含街道、路标、汽车、卡车、自行车、建筑物、树木和行人。图像分割的任务是判断这个图像像素是否属于汽车、树木或其他物体。

深度学习DL),一种人工神经网络ANN)算法,在图像分割中取得了巨大的突破。例如,深度学习中的图像分割使得自动驾驶车辆和高级驾驶辅助系统ADAS)能够检测可导航的表面或行人。许多医学应用利用分割技术绘制肿瘤边界或测量组织体积。

图像增强方法无论是用于分割还是分类都是相同的,不同的是分割还需要附加的掩膜图像或真实图像。因此,我们在第三章中学到的关于增强图像用于分类的内容,也适用于增强图像分割。

本章旨在提供持续的几何和光度变换,用于图像分割。具体来说,你将学习以下主题:

  • 几何和光度变换

  • 现实世界中的分割数据集

  • 通过 Python 代码强化你的学习

有趣的事实

图像分割或语义分割在许多自动驾驶汽车的 AI 控制系统中都有应用。它用于识别街道上的物体和行人。世界各地的比赛胜负,主要取决于图像分割增强技术,例如Kaggle竞赛中的Udacity 和 Lyft 感知挑战的获胜者,采用了随机调整大小裁剪、水*翻转以及亮度、对比度和饱和度的随机颜色扰动。

让我们从分割的几何和光度变换开始。

几何和光度变换

如在第三章中讨论的那样,几何变换会改变图像的几何形状,例如通过翻转、裁剪、填充、旋转或调整大小。对于图像分割,当水*翻转图像时,必须对掩膜进行相同的处理。Pluto 将向你展示如何翻转原始图像及其对应的掩膜图像;下面是一个预览:

图 4.1 – 图像分割水*翻转

图 4.1 – 图像分割水*翻转

第三章 中讨论的许多安全值大多保持不变。例如,如果图像的主题是人或城市景观,分类增强不能垂直翻转,因为预测人的年龄或城市的名称依赖于图像不被颠倒。然而,分割的目的是将人或车进行分组或勾画轮廓。因此,垂直翻转是可以接受的。

对于许多真实世界的应用,安全范围需要进一步研究。例如,对于自动驾驶汽车,如果你遇到车祸并且你的车辆翻倒了呢?AI 是否仍然需要正确地分类周围环境?

光度变换,如亮度、饱和度、对比度、色相偏移和 FancyPCA,在应用于分割时更具挑战性,因为原始图像会被扭曲,但掩码图像不会。一个大问题是,仅增强原始图像而不增强掩码图像,会否提高预测的准确性?

Albumentations 库定义了 37 种变换,认为它们在扭曲原图和掩码图像时是安全的。

从技术上讲,你可以使用光度变换来进行分割,并用 Python 代码实现,但最好查阅已发布的学术论文以确认。我们在 第三章 中讨论的黄金增强规则也适用于此——你选择一种能提高预测准确性的过滤器,这种方法在已发布的学术论文中有描述。

使用 Python 代码进行学习是理解图像分割的另一种途径。然而,在我们进行之前,让我们请 Pluto 从 Kaggle 下载一些真实世界的分割数据集。

真实世界的分割数据集

Kaggle 网站是一个为数据科学家和机器学习爱好者提供的在线社区*台。它包含了成千上万的真实世界数据集,如在第一章第二章第三章中所提到的。

在寻找图像分割数据集时,Pluto 找到了大约 500 个可用的真实世界分割数据集。这些数据集的主题从自动驾驶汽车和医学到微型化石不等。Pluto 从热门市场领域中挑选了两个分割数据集。

另一个考虑因素是图像类型必须易于在 Albumentations 库中处理。Pluto 使用PILNumPy库来读取并将照片转换成三维数组。原始图像的shape是(宽度、高度和深度),其中深度通常等于三。掩码图像的shape是(宽度、高度),值为 0、1、2 等,直到标签的数量。

有趣的事实

PIL 库可以读取 .jpg.gif.tiff.png 等格式的图像文件,还有大约 50 种其他图像格式。然而,有时真实世界的分割数据集会带有 PIL 无法读取的图像格式。在这种情况下,Pluto 借助 Python 的ImageIO库,该库可以读取超过 100 种图像格式。

选中的两个分割数据集如下:

  • Cambridge-Driving Labeled Video (CamVid) 数据库是第一个真实世界的分割数据集。Kaggle 网站上的背景如下:

Cambridge-Driving Labeled Video Database (CamVid) 提供了将每个像素与 32 个语义类别之一关联的地面真值标签。该数据集常用于(实时)语义分割研究。

它于 2020 年由剑桥大学发布,许可证为CC BY-NC-SA 4.0creativecommons.org/licenses/by-nc-sa/4.0/

  • 第二个真实世界数据集叫做 空中图像语义分割。来自 Kaggle 网站的描述如下:

数据集由通过 MBRSC 卫星获取的迪拜空中图像组成,并通过像素级语义分割标注为 6 个类别。数据集的总容量为 72 张图像,分为 6 个较大的瓦片。

它于 2020 年由叙利亚 Roia 基金会发布,许可证为CC0: 公共领域creativecommons.org/publicdomain/zero/1.0/

选择两个分割数据集后,接下来的四个步骤你应该已经熟悉。如果需要澄清,请复习第二章第三章。步骤如下:

  1. 获取 Python Notebook 和 Pluto。

  2. 下载真实世界的数据。

  3. 将数据加载到 pandas 中。

  4. 查看数据图像。

有趣的挑战

Kaggle 网站或其他来源查找并下载两个额外的图像分割数据集。Kaggle 的竞赛和数据包含数百个图像分割数据集。因此,找到对你或你的工作有意义的图像分割数据集应该不成问题。提示:使用 Pluto 的 fetch_kaggle_dataset() or fetch_kaggle_comp_data() 函数。

让我们从 Pluto 开始。

Python Notebook 和 Pluto

从加载 data_augmentation_with_python_chapter_4.ipynb 文件到 Google Colab 或你选择的 Jupyter Notebook 或 JupyterLab 环境开始。从这一点起,代码片段将来自 Python Notebook,其中包含完整的函数。

接下来,你必须克隆仓库并使用%run命令启动 Pluto:

# clone the github
!git clone 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
# instantiate Pluto
%run 'Data-Augmentation-with-Python/pluto/pluto_chapter_3.py'

输出将如下所示,或类似:

---------------------------- : ---------------------------
            Hello from class : <class '__main__.PacktDataAug'> Class: PacktDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ---------------------------
                fastai 2.6.3 :  actual 2.7.9
---------------------------- : ---------------------------
        albumentations 1.2.1 : actual 1.2.1
---------------------------- : ---------------------------

仔细检查 Pluto 是否已正确加载:

# display Python and libraries version number
pluto.say_sys_info()

输出将如下所示,或根据你的系统类似:

---------------------------- : ---------------------------
                 System time : 2022/10/21 15:46
                    Platform : linux
     Pluto Version (Chapter) : 3.0
       Python version (3.7+) : 3.7.13 (default, Apr 24 2022, 01:04:09) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  CPU speed : NOT available
---------------------------- : ---------------------------

Pluto 已验证 Python Notebook 正常工作。下一步是从 Kaggle 下载真实世界的图像数据集。

真实世界数据

以下下载功能来自第二章。Pluto 已在此处重用:

# Fetch Camvid photo
url = 'https://www.kaggle.com/datasets/carlolepelaars/camvid'
pluto.fetch_kaggle_dataset(url)
# Fetch Aerial image
url = 'https://www.kaggle.com/datasets/humansintheloop/semantic-segmentation-of-aerial-imagery'
pluto.fetch_kaggle_dataset(url)

在查看下载的照片之前,Pluto 需要将数据加载到 pandas DataFrame 中。

Pandas

这里需要进行一些清理任务,比如将目录或文件名中的空格字符替换为下划线,并将原始图像与掩码图像分开。清理后,Pluto 重用make_dir_dataframe()函数将原始图像数据读取到 pandas 数据框中。CamVid 数据的命令如下:

# import data to Pandas
f = 'kaggle/camvid/CamVid/train'
pluto.df_camvid = pluto.make_dir_dataframe(f)

前三条记录的输出如下:

图 4.2 – CamVid pandas 数据框,前 3 行

图 4.2 – CamVid pandas 数据框,前 3 行

掩码图像位于不同的文件夹中,且掩码图像的文件名在原文件名后加上了_L

Pluto 使用 pandas 的主要原因是,为匹配的掩码和原始文件名添加新列是个简单的任务。只有两行关键代码。第一行是在帮助函数中生成正确的掩码图像路径,第二行是创建新列以应用帮助函数。相关代码如下:

# define helper function
@add_method(PacktDataAug)
def _make_df_mask_name(self,fname):
  p = pathlib.Path(fname)
  return (str(p.parent.parent) +
    '/' + str(p.parent.name) + '_labels/' +
    str(p.stem) + '_L' + str(p.suffix))
# method definition
@add_method(PacktDataAug)
def make_df_mask_name(self,df):
  df['mask_name'] = df.fname.apply(self._make_df_mask_name)
  return

完成 CamVid 数据框的命令如下:

# create mask file name
pluto.make_df_mask_name(pluto.df_camvid)

输出结果如下:

图 4.3 – 完整的 CamVid 数据框,前 3 行

图 4.3 – 完整的 CamVid 数据框,前 3 行

一旦 Pluto 将所有信息整理到数据框中,下一步就是展示原始图像与掩码图像。

查看数据图像

Pluto 可以重用第二章中的draw_batch()函数,以分批显示原始图像和掩码图像,但结果无法加强原始图像与掩码图像的结合。因此,Pluto 将修改draw_batch()方法,创建一个新的draw_batch_segmentation()方法,并设计一个名为_draw_batch_segmentation()的帮助函数。

结果展示了原始图像,接着是掩码图像,并重复此过程。显示 CamVid 分割照片的命令如下:

# use new batch display method for segmentation
pluto.draw_batch_segmentation(pluto.df_camvid,
  is_shuffle=True)

输出结果如下:

图 4.4 – CamVid 的原始图像与掩码图像批次

图 4.4 – CamVid 的原始图像与掩码图像批次

分割批次看起来是正确的,因此 Pluto 对航拍分割数据重复相同的过程。

使用以下命令下载数据:

# fetch real-world data
url = 'https://www.kaggle.com/datasets/humansintheloop/semantic-segmentation-of-aerial-imagery'
pluto.fetch_kaggle_dataset(url)

清理目录和文件名,然后使用以下命令将它们导入到 pandas 中:

# import to Pandas
f = 'kaggle/semantic-segmentation-of-aerial-imagery'
pluto.df_aerial = pluto.make_dir_dataframe(f)

前五条记录的输出如下:

图 4.5 – 航拍 pandas 数据框,前 3 行

图 4.5 – 航拍 pandas 数据框,前 3 行

使用新的帮助函数添加掩码的文件名,如下所示:

# create mask filename
pluto.make_df_mask_name_aerial(pluto.df_aerial)

前三条记录的输出如下:

图 4.6 – 完整的航拍数据框,前 3 行

图 4.6 – 完整的航拍数据框,前 3 行

使用以下命令显示分割图像批次:

# draw batch image
pluto.draw_batch_segmentation(pluto.df_aerial,
  is_shuffle=True)

输出结果如下:

图 4.7 – 航拍 pandas 数据框,前五行

图 4.7 – 航拍 pandas 数据框,前五行

有趣的挑战

这是一个思维实验:给定一个图像数据集,你如何为这些照片创建掩膜?提示:你可以使用高级图像软件自动描绘物体或轮廓,然后进行标注。其他选择是使用 Mechanical Turk 或众包。你应该考虑成本与时间的*衡。

Pluto 已经成功下载并展示了 CamVid 和航拍分割照片。现在,让我们用 Python 进行一些图像增强。

强化你的学习

分类图像变换的相同概念适用于分割图像变换。在这里,Pluto 重复使用或稍微修改了第三章中的包装函数。特别地,Pluto 为分割处理黑客化了以下方法:

  • 水*翻转

  • 垂直翻转

  • 旋转

  • 随机调整大小和裁剪

  • 转置

  • 光照

  • FancyPCA

有趣的事实

你无法完成或理解本章节,除非你已经阅读了第三章。这是因为 Pluto 重复使用或稍微修改了现有的图像增强包装函数。

Pluto 选择这些滤镜是因为 Albumentations 库将它们标记为安全的分割方法。所以,让我们从水*翻转开始。

水*翻转

Pluto 在第三章中使用 PIL 库演示了水*翻转,因为代码易于理解。因此,他将draw_image_flip_pil()函数黑客化为draw_image_flip_pil_segmen()函数。转换代码是相同的——即,PIL.ImageOps.mirror(img)。变化之处在于将图像并排显示。

在 Python Notebook 中,翻转 CamVid 数据集图像的命令如下:

# use wrapper function to flip image
pluto.draw_image_flip_pil_segmen(pluto.df_camvid.fname[0])

输出结果如下:

图 4.8 – 使用 PIL 库翻转图像

图 4.8 – 使用 PIL 库翻转图像

Pluto 使用相同的函数处理掩膜图像,并将mask_image列传入 pandas 数据框。这就是这么简单。Pluto 必须使用相同的滤镜来转换原始图像和掩膜图像。

翻转掩膜图像的命令如下:

# use wrapper function to flip image mask
pluto.draw_image_flip_pil_segmen(pluto.df_camvid.mask_name[0]

输出结果如下:

图 4.9 – 使用 PIL 库翻转掩膜

图 4.9 – 使用 PIL 库翻转掩膜

有趣的事实

Pluto 在本书中仅展示相关的代码片段,但完整的面向对象方法可以在 Python Notebook 中找到。本章的代码与第三章中的代码非常相似。Pluto 使用第一章提供的原则布局设计了软件架构。因此,代码看起来简洁,但在后台包含了较高的复杂性。

从底层来看,彩色图像是一个三维数组或Rank 3 张量。图像的形状为(宽度、高度和深度),其中深度通常为 3,而掩码图像的形状为(宽度、高度),其中值为 0、1、2 等,一直到标签数量。因此,镜像Rank 3 张量的操作与镜像Rank 1 张量的操作相同。

对于 Albumentations 库,分割的包装函数与在第三章中提供的非常简单。draw_image_flip_segmen() 方法的代码如下:

# method definition
@add_method(PacktDataAug)
def draw_image_flip_segmen(self,df):
  aug_album = albumentations.HorizontalFlip(p=1.0)
  self._draw_image_album_segmentation(df,aug_album,
    'Horizontal Flip')
  return

它与我们在第三章中提供的 draw_image_flip() 函数相同。不同之处在于,使用了不同的辅助函数。它没有使用 _draw_image_album() 辅助函数,而是使用了 _draw_image_album_segmentation() 方法。

对 CamVid 分割数据在 Python Notebook 中执行水*翻转的命令如下:

# use wrapper function to flip both image and image mask
pluto.draw_image_flip_segmen(pluto.df_camvid)

输出如下:

图 4.10 – CamVid 数据集的水*翻转

图 4.10 – CamVid 数据集的水*翻转

对航拍分割数据执行水*翻转的命令如下:

# use the same flip segmentation wrapper function on arial
pluto.draw_image_flip_segmen(pluto.df_aerial)

输出如下:

图 4.11 – 航拍数据集的水*翻转

图 4.11 – 航拍数据集的水*翻转

如同在第三章中所述,本章中的包装函数每次都会随机选择一批新的图像。

有趣的挑战

这里有一个思维实验:你如何利用图像分割来支持环保组织,例如野生动物保护组织?提示:考虑海关人员如何使用 iPhone 或闭路电视(CCTV)监控系统,在开放市场中发现有人出售濒危物种的部分,如象牙或萨嘎角。

Pluto 使用垂直翻转滤镜完成了翻转操作。

垂直翻转

垂直翻转的包装函数几乎与水*翻转方法相同。Pluto 本可以写一个通用函数来替代每个包装方法的独立实现。但目标是解释每个转换,而不是将其重构为更紧凑或更高效的代码。包装函数的关键代码行如下:

# use albumentations library function
aug_album = albumentations.Flip(p=1.0)

在 Python Notebook 中对 CamVid 分割数据执行垂直翻转的命令如下:

# use flip wrapper function for camvid data
pluto.draw_image_flip_both_segmen(pluto.df_camvid)

输出如下:

图 4.12 – CamVid 数据集的垂直翻转

图 4.12 – CamVid 数据集的垂直翻转

对航拍分割数据执行垂直翻转的命令如下:

# use flip wrapper function for aerial image
pluto.draw_image_flip_both_segmen(pluto.df_aerial)

输出如下:

图 4.13 – 航拍数据集的垂直翻转

图 4.13 – 航拍数据集的垂直翻转

翻转操作到此为止。现在,让我们来看一下旋转。

旋转

旋转的安全参数可以顺时针或逆时针旋转 45 度。Albumentations 方法如下:

# use albumentation library function for rotating
aug_album = albumentations.Rotate(limit=45, p=1.0)

用于在 Python Notebook 中旋转 CamVid 分割数据的命令如下:

# use rotate wrapper function for camvid image
pluto.draw_image_rotate_segmen(pluto.df_camvid)

输出如下:

图 4.14 – 旋转 CamVid 数据集

图 4.14 – 旋转 CamVid 数据集

用于旋转航拍分割数据的命令如下:

# use rotate wrapper function for aerial image
pluto.draw_image_rotate_segmen(pluto.df_aerial)

输出如下:

图 4.15 – 旋转航拍数据集

图 4.15 – 旋转航拍数据集

下一个滤镜是调整大小和裁剪。

调整大小和裁剪

分类模型旨在识别对象,而分割模型则按像素对对象进行分组。因此,裁剪和调整大小是在相对较高的安全参数下可以接受的变换。包装函数的关键代码行如下:

# use albumentations function for resizing and cropping
aug_album = albumentations.RandomSizedCrop(
  min_max_height=(500, 600),
  height=500,
  width=500,
  p=1.0)

用于随机调整大小和裁剪 CamVid 分割数据的 Python Notebook 命令如下:

# use resize and crop wrapper functiion for camvid photo
pluto.draw_image_resize_segmen(pluto.df_camvid)

输出如下:

图 4.16 – 调整大小和裁剪 CamVid 数据集

图 4.16 – 调整大小和裁剪 CamVid 数据集

用于随机调整大小和裁剪航拍分割数据的命令如下:

# use resize and crop wrapper functiion for aerialphoto
pluto.draw_image_resize_segmen(pluto.df_aerial)

输出如下:

图 4.17 – 调整大小和裁剪航拍数据集

图 4.17 – 调整大小和裁剪航拍数据集

接下来,我们将介绍转置滤镜。

转置

Pluto 没有在第三章中使用转置滤镜进行分类,但对于分割是可以接受的。转置是指交换 x 轴y 轴。包装函数的关键代码行如下:

# use albumentations library for transpose
aug_album = albumentations.Transpose(p=1.0)

用于转置 CamVid 分割数据的命令如下:

# use transpose wrapper function for camvid data
pluto.draw_image_transpose_segmen(pluto.df_camvid)

输出如下:

图 4.18 – 转置 CamVid 数据集

图 4.18 – 转置 CamVid 数据集

用于转置航拍分割数据的命令如下:

# use transpose wrapper function for aerial data
pluto.draw_image_transpose_segmen(pluto.df_aerial)

输出如下:

图 4.19 – 转置航拍数据集

图 4.19 – 转置航拍数据集

有趣的挑战

在 Python Notebook 中实现光学畸变。提示:使用与 Albumentations 库函数 albumentations.OpticalDistortion() 方法类似的 Pluto 包装函数。

转置是 Pluto 用于几何变换的最后一个示例。光照,也称为亮度,属于光度变换类。

光照

光照或亮度在 Albumentations 库中是可以接受的分割变换,但它属于光度变换类。原始图像会变更为随机亮度级别,直到安全水*,但掩码图像不会改变。对于两个数据集,安全参数的亮度为 0.5。包装函数中的关键代码行如下:

# use albumentations library for brightness
aug_album = albumentations.ColorJitter(
  brightness=brightness,
  contrast=0.0,
  saturation=0.0,
  hue=0.0,
  always_apply=True,
  p=1.0)

用于对 CamVid 分割数据应用光照的命令如下:

# use the brightmess wrapper function for camvid image
pluto.draw_image_brightness_segmen(pluto.df_camvid)

输出如下:

图 4.20 – 在 CamVid 数据集上使用闪电

图 4.20 – 在 CamVid 数据集上使用闪电

使用闪电处理空中分割数据的命令如下:

# use the brightmess wrapper function for aerial image
pluto.draw_image_brightness_segmen(pluto.df_aerial)

输出如下:

图 4.21 – 在空中数据集上使用闪电

图 4.21 – 在空中数据集上使用闪电

类似于光照滤镜,FancyPCA 属于光度变换类。

FancyPCA

FancyPCA 是 Pluto 演示的最后一个光度变换示例。对于这两个数据集,安全的参数是 alpha 值为 0.3。再次强调,FancyPCA 不会改变掩码图像。包装函数中的关键代码行如下:

# use albumentations library for fancyPCA
aug_album = albumentations.FancyPCA(
  alpha=alpha,
  always_apply=True,
  p=1.0)

使用 FancyPCA 处理 CamVid 分割数据的命令如下:

# use the fancyPCA wrapper function for camvid image
pluto.draw_image_fancyPCA_segmen(pluto.df_camvid)

输出如下:

图 4.22 – 在 CamVid 数据集上使用 FancyPCA

图 4.22 – 在 CamVid 数据集上使用 FancyPCA

使用 FancyPCA 处理空中分割数据的命令如下:

# use the fancyPCA wrapper function for aerial image
pluto.draw_image_fancyPCA_segmen(pluto.df_aerial)

输出如下:

图 4.23 – 在空中数据集上使用 FancyPCA

图 4.23 – 在空中数据集上使用 FancyPCA

有趣的挑战

这里有一个思维实验,或者也许是一个实践题:你能做什么看起来在图像增强中是可接受的,但在实际部署中有很高概率产生 假阳性假阴性 预测?抱歉,没有提示。

Pluto 发现,分割增强与分类增强并没有太大区别。包装函数几乎相同,只有辅助方法以不同的方式显示图像。Pluto 已经展示了翻转、调整大小、裁剪、旋转、转置、光照和 FancyPCA 变换的分割处理。与 第三章 类似,接下来,Pluto 将把各个滤镜组合成一个超级函数。

组合

在 Python 中编码超级组合方法之前,Pluto 需要使用 pandas 汇总本章中的滤镜。分割操作适用更多的变换,因此如果你在 Python 笔记本中试验其他滤镜,可以通过你的新滤镜扩展 pandas 表格。

Pluto 使用以下命令显示汇总表格:

# use Pandas to display the combination filters
pluto.print_safe_parameters_segmen()

输出如下:

图 4.24 – 汇总分割滤镜

图 4.24 – 汇总分割滤镜

使用汇总表格,Pluto 编写了包装函数。关键的代码行如下:

# use albumentations library
aug_album = albumentations.Compose([
  albumentations.ColorJitter(brightness=0.5,
    contrast=0.0,
    saturation=0.0,
    hue=0.0,p=0.5),
  albumentations.HorizontalFlip(p=0.5),
  albumentations.Flip(p=0.5),
  albumentations.Rotate(limit=45, p=0.5),
  albumentations.RandomSizedCrop(
    min_max_height=(500, 600),
    height=500,
    width=500,
    p=0.5),
  albumentations.Transpose(p=0.5),
  albumentations.FancyPCA(alpha=0.2, p=0.5)])

Pluto 显示了 CamVid 数据集的组合分割变换,如下所示:

# use combination wrapper function for camvid photo
pluto.draw_uber_segmen(pluto.df_camvid)

输出如下:

图 4.25 – 组合 CamVid 数据集的滤镜

图 4.25 – 组合 CamVid 数据集的滤镜

空中数据集在 Python 笔记本中的命令如下:

# use combination wrapper function for aerial photo
pluto.draw_uber_segmen(pluto.df_aerial)

输出如下:

图 4.26 – 组合空中数据集的滤镜

图 4.26 – 为航拍数据集组合过滤器

有趣的挑战

Pluto 挑战你重构 Pluto 类,使其更快、更紧凑。你被鼓励创建并上传你的库到 GitHub 和 PyPI.org。此外,你不必将类命名为 PacktDataAug,但如果你引用或提到本书,Pluto 和他的人类伙伴将非常高兴。代码的目标是易于理解、可重用的模式以及在 –Python Notebook 中教学。因此,将代码重构为 Python 库将相对轻松且有趣。

到这里,你已经学会了如何组合分割转换。接下来,我们将总结本章所涵盖的内容。

摘要

图像分割由原始图像和附带的掩膜图像组成。目标是确定某个像素是否属于某个对象列表。例如,一张城市照片包含街道、街道标志、汽车、卡车、自行车、建筑物、树木和行人。图像分割的任务是判断这个像素是属于汽车、树木还是其他物体。

图像分割和图像分类共享相同的转换。换句话说,大多数几何转换,如翻转、旋转、调整大小、裁剪和转置,适用于图像分割中的原始图像和掩膜图像。光度转换,如亮度、对比度和 FancyPCA,技术上可以通过 Python 实现,但这些过滤器不会改变掩膜图像。另一方面,像噪声注入和随机擦除这样的过滤器不适用于分割,因为它们会在原始图像中添加或替换像素。

在本章中,有许多 有趣的事实有趣的挑战。Pluto 希望你能利用这些内容,拓展你的经验,超越本章的范围。

切换话题,下一章将讨论文本增强。Pluto 不能使用任何图像增强功能,但他可以重用用于从 Kaggle 网站下载数据集的包装函数。

第三部分:文本增强

本部分包含以下章节:

  • 第五章文本增强

  • 第六章机器学习中的文本增强

第五章:文本增强

文本增强是一种在自然语言处理NLP)中使用的技术,通过修改或从现有文本数据创建新文本来生成额外数据。文本增强涉及的技术包括字符交换、噪声注入、同义词替换、单词删除、单词插入和单词交换。图像和文本增强的目标相同,它们都旨在增加训练数据集的大小并提高 AI 预测的准确性。

文本增强相对较难评估,因为它不像图像增强那样直观。图像增强技术的意图很明确,比如翻转照片,但字符交换技术可能会让读者感到困惑。因此,读者可能会将其益处视为主观的。

文本增强的效果取决于生成数据的质量以及正在执行的具体 NLP 任务。确定给定数据集所需的适当安全级别的文本增强可能会非常具有挑战性,这通常需要实验和测试才能获得预期的结果。

客户反馈或社交媒体上的聊天内容是文本增强的合理素材,因为这些内容通常杂乱无章,并且大多数包含语法错误。相反,法律文件或书面医疗通讯,如医生处方或报告,则不适合进行文本增强,因为这些内容要求精确表达。换句话说,错误注入、同义词替换甚至 AI 生成的文本可能会改变法律或医学的含义,超出安全水*。

文本增强中的偏差同样很难察觉。例如,通过故意拼写错误单词来使用键盘增强方法添加噪声,可能会引入对现实世界推文的偏见,而这些推文通常包含拼写错误的单词。没有普遍适用的规则可循,答案只有在深入研究数据并审查 AI 预测目标后才能显现出来。

有趣的事实

随着生成型 AI 的普及,你可以使用OpenAI 的 GPT-3Google BardFacebook 的 Roberta系统生成原创文章用于文本增强。例如,你可以让生成型 AI 创建关于公司产品的正面或负面评论,然后使用 AI 编写的文章来训练情感分析预测 AI。

第五章中,你将学习文本增强,并如何在 Python 笔记本中编写相关方法。特别是,我们将涵盖以下主题:

  • 字符增强

  • 单词增强

  • 句子和流程增强

  • 文本增强库

  • 真实世界文本数据集

  • 通过 Python 笔记本强化学习

让我们从最简单的主题开始,字符增强。

字符增强

字符增强会替换或注入字符到文本中。换句话说,它会制造打字错误。因此,这种方法似乎是违反直觉的。然而,就像图像增强中的噪声注入一样,学术论文展示了字符增强在提高 AI 预测准确性方面的好处,例如Zhuosheng Zhang, Yafang Huang, Pengfei Zhu 和 Hai Zhao于 2018 年在《CCF 国际自然语言处理会议》上发表的《有效的字符增强词嵌入用于机器阅读理解》。

三种标准的字符增强方法如下所示:

  • 光学字符识别(OCR)增强功能通过将图像转换为文本来替代 OCR 中常见的错误,例如将字母o转换为数字0,或将大写字母I转换为数字1

  • 键盘增强方法将字符替换为其相邻的其他字符。例如,字符b的常见打字错误是按下v键或n键。

  • 随机字符功能会在文本中随机交换、插入或删除字符。

有趣的事实

计算机编码文本在 1963 年至 1970 年期间有很大不同;例如,计算机会将字母A编码为整数 64 或十六进制 41。这一做法起源于 1964 年的美国国家标准学会ANSI),并在 1970 年左右被国际标准化组织ISO)采纳。1980 年,统一码Unicode)取代了 ISO 标准,适用于所有国际语言。然而,如果你遇到来自 1964 年左右的计算机文本,它可能采用扩展二进制编码十进制交换码EBCDIC),它将字母A编码为 193 或十六进制 C1。作为程序员,你可能需要回答这样一个问题:你的网站或移动应用是否支持 Unicode?

在字符增强之后,接下来的类别是单词增强。

单词增强

单词增强与字符增强具有相同的偏差和安全级别警告。超过一半的这些增强方法会向文本中注入错误,但其他功能则使用同义词或预训练的 AI 模型生成新文本。标准的单词增强功能如下所示:

  • 拼写错误增强功能使用预定义的字典模拟拼写错误。它基于Claude Coulombe在 2018 年发布的学术论文《通过利用 NLP 云 API 简化文本数据增强》。

  • 分割增强功能会将单词随机分成两个词元。

  • 随机词增强方法通过四个参数对文本应用随机行为:替换交换删除裁剪。它基于两篇学术论文:Yonatan Belinkov 和 Yonatan Bisk于 2018 年发表的《Synthetic and Natural Noise Both Break Neural Machine Translation》以及Gozde Gul SahinMark Steedman的《Data Augmentation via Dependency Tree Morphing for Low-Resource Languages》。

  • 同义词增强功能用来自预定义数据库的同义词替换单词。第一个选项是使用WordNet。WordNet 是普林斯顿大学提供的一个广泛的英语词汇数据库。该数据库将名词、动词、形容词和副词分组为认知同义词集。第二个选项是使用同义词数据库PPDB)。PPDB 是一个自动提取的数据库,包含 16 种语言的数百万个同义词。PPDB 旨在通过增强系统对语言变异性和未见过单词的鲁棒性来改善语言处理。整个 PPDB 资源可在美国创意共享署名****3.0许可证下免费获取。

  • 反义词增强功能用反义词替换单词。它基于Tong NiuMohit Bansal于 2018 年发表的学术论文《Adversarial Over-Sensitivity and Over-Stability Strategies for Dialogue Models》。

  • 保留字增强方法在你定义的单词列表中交换目标单词。它与同义词相似,只是这些术语是手动创建的。

有趣的挑战

这里有一个思想实验:你能想出一种新的字符或单词增强技术吗?一个提示是考虑一下阅读障碍者是如何阅读的。

接下来,我们将看看句子增强。

句子增强

句子增强使用生成式 AI 来创建新文本。AI 模型的例子有 BERT、Roberta、GPT-2 等。

三种句子增强方法如下所示:

  • 上下文词嵌入使用 GPT-2、Distilled-GPT-2 和 XLNet。

  • 抽象总结使用 Facebook Roberta 和 T5-Large。

  • Top-n 相似词使用 LAMBADA。

在 Pluto 解释 Python 笔记本中的代码之前,我们先来回顾一下文本增强库。

文本增强库

比起文本增强库,Python 中开源的图像增强库更多。有些库对特定类别的适应性比其他库更强,但通常来说,选择一到两个库并精通它们是一个不错的选择。

知名的库有Nlpaug自然语言工具包NLTK)、生成相似Gensim)、TextBlobTextAugmentAugLy

  • Nlpaug是一个用于深度学习文本增强的库。其目标是通过生成文本数据来提高深度学习模型的表现。GitHub 链接是github.com/makcedward/nlpaug

  • NLTK 是一个用于构建 Python 程序以处理人类语言数据的*台。它提供了对超过 50 种语料库和词汇资源的接口,例如 WordNet。NLTK 包含用于分类、分词、词干提取、标注、解析和语义推理的文本处理库。GitHub 链接是 github.com/nltk/nltk

  • Gensim 是一个流行的开源 NLP 库,用于无监督主题建模。它利用学术模型和现代统计机器学习来执行词向量、语料库、主题识别、文档比较和分析纯文本文档。GitHub 链接是 github.com/RaRe-Technologies/gensim

  • TextBlob 是一个用于处理文本数据的库。它提供了一个简单的 API,方便处理典型的 NLP 任务,如词性标注、名词短语提取、情感分析、分类和翻译。GitHub 链接是 github.com/sloria/TextBlob

  • TextAugment 是一个用于增强 NLP 应用中文本的库。它使用并结合了 NLTK、Gensim 和 TextBlob 库。GitHub 链接是 github.com/dsfsi/textaugment

  • AugLy 是 Facebook 提供的一个数据增强库,支持音频、图像、文本和视频模块,并提供超过 100 种增强方法。每种模态的增强被分类到不同的子库中。GitHub 链接是 github.com/facebookresearch/AugLy

)

与图像增强包装函数类似,Pluto 将编写包装函数,通过库实现底层功能。你可以为一个项目选择多个库,但 Pluto 将使用 Nlpaug 库来支持这些包装函数。

让我们从 Kaggle 网站下载真实世界的文本数据集。

真实世界的文本数据集

Kaggle 网站是一个面向数据科学家和机器学习爱好者的在线社区*台。Kaggle 网站有成千上万的真实世界数据集;Pluto 在其中找到了约 2,900 个 NLP 数据集,并选择了两个 NLP 数据集用于本章内容。

第二章 中,Pluto 以 NetflixAmazon 数据集为例,帮助理解偏差问题。Pluto 保留了 Netflix 的 NLP 数据集,因为电影评论是经过筛选的。虽然存在一些语法错误,但整体上输入文本质量较高。

第二个 NLP 数据集是 Twitter 情感分析 (TSA)。29,530 条真实世界的推文包含许多语法错误和拼写错误。挑战在于将推文分类为两类: (1) 正常,或 (2) 种族歧视和性别歧视。

数据集由 Mayur Dalvi 于 2021 年发布,许可证为 CC0: 公共领域creativecommons.org/publicdomain/zero/1.0/

选择两个 NLP 数据集后,您可以使用相同的四个步骤,通过 Python Notebook 开始实际学习的过程。如果需要澄清,可以参考第二章第三章。步骤如下:

  1. 获取 Python Notebook 和 Pluto。

  2. 下载真实世界数据。

  3. 导入到 pandas。

  4. 查看数据。

让我们从 Pluto 开始。

Python Notebook 和 Pluto

从将 data_augmentation_with_python_chapter_5.ipynb 文件加载到 Google Colab 或您选择的 Jupyter notebook 或 JupyterLab 环境开始。从此开始,代码片段来自 Python Notebook,其中包含完整代码。

下一步是克隆代码库。Pluto 将重用来自第二章的代码,因为它包含下载 Kaggle 数据的方法,而不包含图像增强功能。!git%run 语句用于启动 Pluto。命令如下:

# clone GitHub repo
!git clone 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
# instantiate Pluto
%run 'Data-Augmentation-with-Python/pluto/pluto_chapter_2.py'

输出如下:

---------------------------- : ---------------------------
            Hello from class : <class '__main__.PacktDataAug'> Class: PacktDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ---------------------------

我们需要进行最后一次检查,以确保 Pluto 已经成功加载。以下命令让 Pluto 报告他的状态:

pluto.say_sys_info()

输出应该如下所示,或根据您的系统可能有所不同:

---------------------------- : ---------------------------
                 System time : 2022/10/30 06:52
                    Platform : linux
     Pluto Version (Chapter) : 2.0
             Python (3.7.10) : actual: 3.7.15 (default, Oct 12 2022, 19:14:55) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  *CPU speed : NOT available
---------------------------- : ---------------------------

在这里,Pluto 报告说他来自第二章,也就是版本 2.0。这正是我们所需要的,因为我们不需要来自第三章第四章的任何图像增强功能。下一步是下载真实世界的 NetflixTwitter NLP 数据集。

真实世界的 NLP 数据集

目前尚未为本章编写新代码。Pluto 重用 fetch_kaggle_dataset() 方法下载 Netflix 数据集,具体如下:

# fetch data
url = 'https://www.kaggle.com/datasets/infamouscoder/dataset-netflix-shows'
pluto.fetch_kaggle_dataset(url)

dataset-netflix-shows.zip 文件大小为 1.34 MB,功能会自动解压到 kaggle 目录中。

获取 Twitter 数据集的方法如下:

# fetch data
url = 'https://www.kaggle.com/datasets/mayurdalvi/twitter-sentiments-analysis-nlp'
pluto.fetch_kaggle_dataset(url)

twitter-sentiments-analysis-nlp.zip 文件大小为 1.23 MB,功能会自动解压到 kaggle 目录中。

有趣的挑战

挑战是从 Kaggle 网站搜索并下载两个额外的真实世界 NLP 数据集。提示:使用 pluto.fetch_kaggle_dataset() 方法。Pluto 是一只虚拟的数字西伯利亚哈士奇犬。因此,他会一直开心地获取数据,直到你的磁盘空间用尽。

下一步是将数据加载到 pandas 中。

Pandas

fetch_df() 方法。请注意,df 是 pandas DataFrame 类的典型缩写。

对于 Netflix 数据,Pluto 使用以下两个命令将数据导入 pandas 并打印出数据批次:

# import into Panda
f = 'kaggle/dataset-netflix-shows/netflix_titles.csv'
pluto.df_netflix_data = pluto.fetch_df(f)
# display data batch
pluto.print_batch_text(pluto.df_netflix_data,
  cols=['title', 'description'])

输出如下:

图 5.1 – Netflix 电影描述

图 5.1 – Netflix 电影描述

有趣的事实

fetch_df() 方法随机选择若干记录显示在数据批次中。记录的数量或批次大小是 bsize 参数,默认是 10 条记录。

Netflix 电影评论数据经过整理,因此是干净的。Pluto 不需要清洗这些数据。然而,Twitter 数据就另当别论了。

清洗、导入并批量显示 Twitter 数据到 pandas 的命令如下:

# clean space-char
f = 'kaggle/twitter-sentiments-analysis-nlp'
!find {f} -name "* *" -type f | rename 's/ /_/g'
# import into Pandas
f = 'kaggle/twitter-sentiments-analysis-nlp/Twitter_Sentiments.csv'
pluto.df_twitter_data = pluto.fetch_df(f)
# display data batch
pluto.print_batch_text(pluto.df_twitter_data,cols=['label', 'tweet'])

输出如下:

图 5.2 – Twitter 推文

图 5.2 – Twitter 推文

由于来自 Twitter 的现实世界推文是由公众编写的,它们包含拼写错误、脏话以及各种胡闹。

目标是预测普通推文与种族主义或性别歧视推文。Pluto 重点学习文本论证,因此他希望推文中包含可打印字符,没有 HTML 标签,也没有脏话。

Pluto 编写了两个简单的辅助方法来清洗文本并去除脏话。_clean_text() 函数使用了 regex 库,代码如下:

return (re.sub('[^A-Za-z0-9 .,!?#@]+', '', str(x)))

_clean_bad_word() 辅助函数使用了 filter-profanity 库,代码如下:

return (profanity.censor_profanity(x, ''))

clean_text() 方法利用 pandas 强大的 apply 函数结合这两个辅助函数。利用 pandas 内建的函数,Pluto 用两行代码编写了 clean_text() 函数,而不是用十几行标准的 if-elsefor 循环构造。代码如下:

# clean text
df['clean_tweet'] = df.tweet.apply(self._clean_text)
# remove profanity words
df['clean_tweet'] = df['clean_tweet'].apply(
    self._clean_bad_word)

清洁推文和显示数据批次的命令如下:

# clean tweets
pluto.clean_text(pluto.df_twitter_data)
# display data batch
pluto.print_batch_text(pluto.df_twitter_data,
    cols=['label', 'clean_tweet'])

输出如下:

图 5.3 – 清洁后的 Twitter 推文

图 5.3 – 清洁后的 Twitter 推文

趣味事实

谁能想到狗和熊猫能合作得这么好?下一部 功夫熊猫 电影讲述的是 PoPluto 联手抵御世纪风暴的故事,这场风暴是由全球变暖引起的,它正摧毁着城市墙。

让我们使用 pandas 和其他一些库来可视化 NLP 数据集。

可视化 NLP 数据

第二章 使用 draw_word_count() 方法显示每条记录的*均单词数,以及最短和最长的电影评论。图表的右侧显示了电影评论单词计数的直方图。pandas 库生成了漂亮的单词计数图表。Pluto 重用了这个函数来显示 Netflix NLP 数据,具体如下:

# draw word count
pluto.draw_word_count(pluto.df_netflix_data)

输出如下:

图 5.4 – Netflix 单词计数

图 5.4 – Netflix 单词计数

Netflix 电影描述的*均字数为 23.88 字,最少 10 字,最多 48 字。Pluto 对 Twitter NLP 数据做了同样的处理,具体如下:

# draw word count
pluto.draw_word_count(pluto.df_twitter_data)

输出如下:

图 5.5 – Twitter 单词计数

图 5.5 – Twitter 单词计数

Twitter 推文的*均字数为 12.78 字,最少 1 字,最多 33 字。

Pluto 编写了 draw_text_null_data() 方法来检查是否存在缺失数据,也就是使用 Missingno 库生成图表,关键代码行如下:

missingno.matrix(df,color=color,ax=pic)

Pluto 为 Netflix 数据绘制了 null 数据图表,如下所示:

# draw missing data/null value
pluto.draw_text_null_data(pluto.df_netflix_data)

输出结果如下:

图 5.6 – Netflix 缺失数据

图 5.6 – Netflix 缺失数据

Netflix 数据中的 directorcastcountry 分类存在缺失数据,但 description 分类,也就是电影评论,没有缺失数据。

Pluto 对 Twitter 数据做了相同的操作,如下所示:

# draw missing data/null value
pluto.draw_text_null_data(pluto.df_twitter_data)

输出结果如下:

图 5.7 – Twitter 缺失数据

图 5.7 – Twitter 缺失数据

Twitter 数据中没有缺失数据。

有趣的事实

许多价值数百万美元的 AI 系统失败的主要原因是缺乏对输入数据的控制。例如,2020 年的 Amazon Recruiting 系统失败了,因为数据集中缺乏多样性,最严重的失败是 2016 年的 Microsoft Chatbot Tay。它被 Twitter 用户输入的性别歧视和种族主义推文所破坏。

下一个图表是字词云信息图。这是一种极好的 NLP 文本可视化方法。最常用的词语以大字号显示,而最少使用的词语则以较小字号显示。WordCloud 库生成了信息图表,关键代码片段如下:

# generate word cloud
img = wordcloud.WordCloud(width = 1600,
        height = 800,
        background_color ='white',
        stopwords = xignore_words,
        min_font_size = 10).generate(words_str)
# covert Pandas to word string input
orig = df_1column.str.cat()
word_clean = re.sub('[^A-Za-z0-9 ]+', '', orig)

Pluto 使用 _draw_text_wordcloud() 辅助函数和 draw_text_wordcloud() 方法,展示了真实世界的 Netflix 数据的字词云信息图,如下所示:

# draw word cloud
pluto.draw_text_wordcloud(pluto.df_netflix_data.description,
    xignore_words=wordcloud.STOPWORDS,
    title='Word Cloud: Netflix Movie Review')

输出结果如下:

图 5.8 – Netflix 字词云,包含大约 246,819 个单词

图 5.8 – Netflix 字词云,包含大约 246,819 个单词

Pluto 对真实世界的 Twitter 数据也做了相同的操作,如下所示:

# draw word cloud
pluto.draw_text_wordcloud(pluto.df_twitter_data.clean_tweet,
    xignore_words=wordcloud.STOPWORDS,
    title='Clean Tweets Word Cloud')

输出结果如下:

图 5.9 – Twitter 字词云,包含大约 464,992 个单词

图 5.9 – Twitter 字词云,包含大约 464,992 个单词

有趣的事实

这里有一个关于字词云图的有趣小知识。字词云,又称标签云、Wordle 或加权列表,最早由 Douglas Coupland 在 1995 年的书籍 Microserfs 中以印刷形式使用。但直到 2004 年,字词云才在 Flickr 网站上以数字格式存在。今天,字词云信息图在互联网上和学术论文中广泛应用。

到目前为止,Pluto 已经讨论了字符、单词和句子增强理论,选择了 Nlpaug 文本增强库,并下载了真实世界的 NetflixTwitter NLP 数据集。现在是时候通过 Python 代码执行文本增强来强化他的学习了。

通过 Python Notebook 强化学习

Pluto 使用 Python Notebook 加深我们对文本增强的理解。他使用批处理函数以批次的形式显示文本。它的工作方式类似于图像的批处理函数。换句话说,它会随机选择新的记录,并使用增强方法进行转换。

有趣的事实

Pluto 推荐重复运行批处理函数,以深入了解文本增强方法。在 TwitterAmazon 数据集中有成千上万的文本记录。每次运行批处理函数时,它会显示来自数据集的不同记录。

与图像增强实现类似,包装函数在幕后使用 Nlpaug 库。这个包装函数让你可以专注于文本转换的概念,而不被库的实现所分心。你也可以使用其他文本增强库,包装函数的输入和输出将保持不变。

Pluto 可以编写一个复杂的函数,包含所有文本转换技术,这可能更高效,但这并不是本书的目标。阅读完本书后,你可以自信地选择重写或修改 Python Notebook 以适应你的风格。

在本章中,Pluto 使用 查尔斯·狄更斯 的《双城记》中的开篇句子作为控制文本。Pluto 通过将短语之间的逗号替换为句号来改写文本,因为这样更有利于文本增强过程。控制文本如下:

“这是最好的时代,也是最坏的时代。是智慧的时代,也是愚蠢的时代。是信仰的纪元,也是怀疑的纪元。”

Python Notebook 涵盖以下主题:

  • 字符增强

  • 单词增强

让我们从三种字符增强技术开始。

字符增强

字符增强是指向文本中注入错误。这个过程是违反直觉的,因为它故意向数据中添加错误。换句话说,它使得文本对于人类来说更难理解。相反,计算机使用深度学习算法来预测结果,尤其是 卷积神经网络CNN)和 递归神经网络RNN)算法。例如,推文的情感分类不会受到拼写错误的影响。

特别是,Pluto 将解释以下三种方法:

  • OCR 增强

  • 键盘增强

  • 随机增强

让我们从 OCR 开始。

OCR 增强

OCR 过程将图像转换为文本,在转换过程中常出现错误,如将 0o 混淆。

Pluto 编写了 _print_aug_batch() 辅助函数,随机选择 NLP 数据中的样本记录,应用文本增强方法,并使用 pandas 打印。输入或方法定义如下:

# method definition
def _print_aug_batch(self, df,
    aug_func,
    col_dest="description",
    bsize=3,
    aug_name='Augmented'):

这里,df 是 pandas DataFrame,aug_function 是包装函数中的增强方法,col_dest 是选择的目标列,bsize 是批次中的样本数,默认为三,title 是图表的可选标题。

OCR 包装函数是基础的。两行代码分别是 aug_func 和辅助函数。整个代码如下:

# method definiton
@add_method(PacktDataAug)
def print_aug_ocr(self, df,
    col_dest="description",
    bsize=3,
    aug_name='Augmented'):
    aug_func = nlpaug.augmenter.char.OcrAug()
    self._print_aug_batch(df,
        aug_func,
        col_dest=col_dest,
        bsize=bsize,
        aug_name=aug_name)
    return

Pluto 使用 print_aug_ocr() 方法处理 Netflix 数据,如下所示:

# use OCR method
pluto.print_aug_ocr(pluto.df_netflix_data,
    col_dest='description',
    aug_name='OCR Augment')

输出如下:

图 5.10 – Netflix OCR 增强

图 5.10 – Netflix OCR 增强

图 5.10 中,第一行是 狄更斯 的控制文本,左侧是增强后的文本,右侧是原始文本。接下来的三行是从 Netflix NLP 数据中随机抽取的。Pluto 推荐先阅读左侧的增强文本。停下来并试着解读其含义,然后再阅读原始文本。

趣味事实

Pluto 推荐反复运行 print_aug_ocr() 方法以查看其他电影描述。你可以增加 bsize 来查看一次超过两条记录。

Pluto 同样对 Twitter 的 NLP 数据进行处理,如下所示:

# print the batch
pluto.print_aug_ocr(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='OCR Augment')

输出如下:

图 5.11 – Twitter OCR 增强

图 5.11 – Twitter OCR 增强

接下来,Pluto 从 OCR 方法转向键盘技术。

键盘增强

键盘增强方法通过用键盘上相*的键替换字符。例如,字符 b 的典型打字错误是按了键 v 或键 n。增强变量定义如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.char.KeyboardAug()

Pluto 使用 print_aug_keyboard() 包装函数处理 Netflix 的 NLP 数据,如下所示:

# use keyboard augmentation technique
pluto.print_aug_keyboard(pluto.df_netflix_data,
    col_dest='description',
    aug_name='Keyboard Augment')

输出如下:

图 5.12 – Netflix 键盘增强

图 5.12 – Netflix 键盘增强

Pluto 同样对 Twitter 的 NLP 数据进行处理,如下所示:

# use keyboard augmentation technique
pluto.print_aug_keyboard(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='Keyboard Augment')

输出如下:

图 5.13 – Twitter 键盘增强

图 5.13 – Twitter 键盘增强

三种文本增强方法中的最后一种是随机技术。

随机增强

随机字符功能会随机交换、插入或删除文本中的字符。随机过程的四种模式是 插入删除替换交换。增强变量定义如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.char.RandomCharAug(action=action)

Pluto 在 Netflix 的 NLP 数据中使用 print_aug_random() 包装函数,并将 action 设置为 insert,如下所示:

# use random insert augmentation technique
pluto.print_aug_char_random(pluto.df_netflix_data,
    action='insert',
    col_dest='description',
    aug_name='Random Insert Augment')

输出如下:

图 5.14 – Netflix 随机插入增强

图 5.14 – Netflix 随机插入增强

Pluto 同样对 Twitter 的 NLP 数据进行处理,如下所示:

# use random insert augmentation technique
pluto.print_aug_char_random(pluto.df_twitter_data,
    action='insert',
    col_dest='clean_tweet',
    aug_name='Random Insert Augment')

输出如下:

图 5.15 – Twitter 随机插入增强

图 5.15 – Twitter 随机插入增强

Pluto 在 Netflix NLP 数据上使用 print_aug_random() 包装函数,action 设置为 delete,具体如下:

# use random delete augmentation technique
pluto.print_aug_char_random(pluto.df_netflix_data,
    action='delete',
    col_dest='description',
    aug_name='Random Delete Augment')

输出结果如下:

图 5.16 – Netflix 随机删除增强

图 5.16 – Netflix 随机删除增强

Pluto 对 Twitter 的 NLP 数据也进行了相同处理,具体如下:

# use random delete augmentation technique
pluto.print_aug_char_random(pluto.df_twitter_data,
    action='delete', col_dest='clean_tweet',
    aug_name='Random Delete Augment')

输出结果如下:

图 5.17 – Twitter 随机删除增强

图 5.17 – Twitter 随机删除增强

Pluto 在 Netflix NLP 数据上使用 print_aug_random() 包装函数,action 设置为 substitute,具体如下:

# use random substitute augmentation technique
pluto.print_aug_char_random(pluto.df_netflix_data,
    action='substitute',
    col_dest='description',
    aug_name='Random Substitute Augment')

输出结果如下:

图 5.18 – Netflix 随机替换增强

图 5.18 – Netflix 随机替换增强

Pluto 对 Twitter NLP 数据也进行了相同处理,具体如下:

# use random substitude augmentation technique
pluto.print_aug_char_random(pluto.df_twitter_data,
    action='substitute',
    col_dest='clean_tweet',
    aug_name='Random Substitute Augment')

输出结果如下:

图 5.19 – Twitter 随机替换增强

图 5.19 – Twitter 随机替换增强

Pluto 在 Netflix NLP 数据上使用 print_aug_random() 包装函数,action 设置为 swap,具体如下:

# use random swap augmentation technique
pluto.print_aug_char_random(pluto.df_netflix_data,
    action='swap',
    col_dest='description',
    aug_name='Random Swap Augment')

输出结果如下:

图 5.20 – Netflix 随机交换增强

图 5.20 – Netflix 随机交换增强

Pluto 对 Twitter NLP 数据也进行了相同处理,具体如下:

# use random swap augmentation technique
pluto.print_aug_char_random(pluto.df_twitter_data,
    action='swap',
    col_dest='clean_tweet',
    aug_name='Random Swap Augment')

输出结果如下:

图 5.21 – Twitter 随机交换增强

图 5.21 – Twitter 随机交换增强

有趣的挑战

这里有一个思维实验:如果输入文本包含拼写错误和语法错误,比如推文,那么纠正拼写和语法是否可以作为有效的增强方法?

Pluto 已涵盖 OCR键盘 和四种模式的 随机 字符增强技术。下一步是增强单词。

单词增强

到目前为止,Pluto 可能会觉得文本增强毫不费力,实际上这是真的。我们在 第一章 中打下了坚实的基础,使用面向对象的类并学习如何在学习新增强技术时扩展对象。在 第二章 中,Pluto 添加了用于下载任何 Kaggle 真实世界数据集的函数,第三章第四章 给我们提供了包装函数模式。因此,到了这一点,Pluto 复用了这些方法和模式,使 Python 代码简洁易懂。

单词增强过程类似于字符增强。Pluto 使用相同的 _print_aug_batch() 辅助方法。特别是,Pluto 将涵盖 拼写错误分割随机同义词反义词保留 单词增强技术。

让我们从拼写错误增强技术开始。

拼写错误增强

拼写错误增强函数使用预定义字典模拟拼写错误。增强变量定义如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.word.SpellingAug()

Pluto 在 Netflix NLP 数据上使用 print_aug_word_misspell() 包装函数,具体如下:

# use word missplell augmentation
pluto.print_aug_word_misspell(pluto.df_netflix_data,
    col_dest='description',
    aug_name='Word Spelling Augment')

输出结果如下:

图 5.22 – Netflix 拼写错误单词增强

图 5.22 – Netflix 拼写错误单词增强

Pluto 对Twitter NLP 数据执行相同操作,如下所示:

# use word missplell augmentation
pluto.print_aug_word_misspell(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='Word Spelling Augment')

输出结果如下:

图 5.23 – Twitter 拼写错误单词增强

图 5.23 – Twitter 拼写错误单词增强

拼写错误类似的是分割单词增强技术。

分割增强

分割增强函数随机将单词拆分为两个标记。增强变量定义如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.word.SplitAug()

Pluto 在Netflix NLP 数据上使用 print_aug_word_split() 包装函数,如下所示:

# use word split augmentation
pluto.print_aug_word_split(pluto.df_netflix_data,
    col_dest='description',
    aug_name='Word Split Augment')

输出结果如下:

图 5.24 – Netflix 分割单词增强

图 5.24 – Netflix 分割单词增强

Pluto 对Twitter NLP 数据执行相同操作,如下所示:

# use word split augmentation
pluto.print_aug_word_split(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='Word Split Augment')

输出结果如下:

图 5.25 – Twitter 分割单词增强

图 5.25 – Twitter 分割单词增强

在分割单词方法之后,Pluto 展示了随机单词增强方法。

随机增强

随机单词增强方法对文本应用随机行为,具有四个参数:交换裁剪替换删除。增强变量定义如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.word.RandomWordAug(action=action)

Pluto 在Netflix NLP 数据上使用 print_aug_word_random() 包装函数进行交换模式,如下所示:

# use word random swap augmentation
pluto.print_aug_word_random(pluto.df_netflix_data,
    action='swap',
    col_dest='description',
    aug_name='Word Random Swap Augment')

输出结果如下:

图 5.26 – Netflix 随机交换单词增强

图 5.26 – Netflix 随机交换单词增强

Pluto 对Twitter NLP 数据执行相同操作,如下所示:

# use word random swap augmentation
pluto.print_aug_word_random(pluto.df_twitter_data,
    action='swap',
    col_dest='clean_tweet',
    aug_name='Word Random Swap Augment')

输出结果如下:

图 5.27 – Twitter 随机交换单词增强

图 5.27 – Twitter 随机交换单词增强

Pluto 在Netflix NLP 数据上使用 print_aug_word_random() 包装函数进行裁剪模式,如下所示:

# use word random crop augmentation
pluto.print_aug_word_random(pluto.df_netflix_data,
    action='crop',
    col_dest='description',
    aug_name='Word Random Crop Augment')

输出结果如下:

图 5.28 – Netflix 随机裁剪单词增强

图 5.28 – Netflix 随机裁剪单词增强

Pluto 对Twitter NLP 数据执行相同操作,如下所示:

# use word random swap augmentation
pluto.print_aug_word_random(pluto.df_twitter_data,
    action='crop',
    col_dest='clean_tweet',
    aug_name='Word Random Crop Augment')

输出结果如下:

图 5.29 – Twitter 随机裁剪单词增强

图 5.29 – Twitter 随机裁剪单词增强

所以,Pluto 描述了交换裁剪单词增强方法,但没有涉及替换删除方法。这是因为它们类似于字符增强函数,并且已经在 Python Notebook 中。接下来的内容是同义词增强。

同义词增强

同义词增强函数将单词替换为预定义数据库中的同义词。WordNetPPBD 是两个可选的数据库。增强变量定义该过程如下:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.word.SynonymAug(
    aug_src='wordnet')

Pluto 在Netflix NLP 数据上使用 print_aug_word_synonym() 包装函数,如下所示:

# use word synonym augmentation
pluto.print_aug_word_synonym(pluto.df_netflix_data,
    col_dest='description',
    aug_name='Synonym WordNet Augment')

输出结果如下:

图 5.30 – Netflix 同义词单词增强

图 5.30 – Netflix 同义词单词增强

有趣且好笑的是,It 的同义词对于控制文本来说是 信息技术。写下《双城记》的狄更斯先生,1859 年时肯定无法预见到 IT 是信息技术的流行缩写。Pluto 在 Twitter NLP 数据上做了相同的处理,如下所示:

# use word synonym augmentation
pluto.print_aug_word_synonym(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='Synonym WordNet Augment')

输出如下:

图 5.31 – Twitter 同义词增强

图 5.31 – Twitter 同义词增强

当有同义词时,你也会找到反义词。

反义词增强

反义词增强功能会随机用反义词替换词汇。增强变量定义了这个过程,如下所示:

# define augmentation function variable definition
aug_func = nlpaug.augmenter.word.AntonymAug()

Pluto 使用 print_aug_word_antonym() 包装函数处理 Netflix NLP 数据,如下所示:

# use word antonym augmentation
pluto.print_aug_word_antonym(pluto.df_netflix_data,
    col_dest='description',
    aug_name='Antonym Augment')

输出如下:

图 5.32 – Netflix 反义词增强

图 5.32 – Netflix 反义词增强

Pluto 在 Twitter NLP 数据上做了相同的处理,如下所示:

# use word antonym augmentation
pluto.print_aug_word_antonym(pluto.df_twitter_data,
    col_dest='clean_tweet',
    aug_name='Antonym Augment')

输出如下:

图 5.33 – Twitter 反义词增强

图 5.33 – Twitter 反义词增强

在同义词和反义词增强(自动化处理)之后,保留字增强需要手动词汇表。

保留字增强

保留字增强方法通过定义一个词汇表来交换目标词汇。它与同义词增强相同,只不过这些词是手动创建的。Pluto 使用 NetflixTwitter 的词云图,图 5.85.9,来选择 NLP 数据集中排名前三的重复词汇。增强变量定义了这个过程,如下所示:

# define augmentation function
aug_func = nlpaug.augmenter.word.ReservedAug(
    reserved_tokens=reserved_tokens)
# define control sentence reserved words
pluto.reserved_control = [['wisdom', 'sagacity',
    'intelligence', 'prudence'],
    ['foolishness', 'folly', 'idiocy', 'stupidity']]
# define Netflix reserved words
pluto.reserved_netflix = [['family','household', 'brood',
    'unit', 'families'],
    ['life','existance', 'entity', 'creation'],
    ['love', 'warmth', 'endearment','tenderness']]
pluto.reserved_netflix = pluto.reserved_control +
    pluto.reserved_netflix
# define Twitter reserved words
pluto.reserved_twitter = [['user', 'users', 'customer',
    'client','people','member','shopper'],
    ['happy', 'cheerful', 'joyful', 'carefree'],
    ['time','clock','hour']]
pluto.reserved_twitter = pluto.reserved_control +
    pluto.reserved_twitter

Pluto 使用 print_aug_word_reserved() 包装函数处理 Netflix NLP 数据,如下所示:

# use word reserved augmentation
pluto.print_aug_word_reserved(pluto.df_netflix_data,
    col_dest='description',
    reserved_tokens=pluto.reserved_netflix)

输出如下:

图 5.34 – Netflix 保留字增强

图 5.34 – Netflix 保留字增强

请注意,wisdomfoolishness 被替换为 Intelligenceidiocylife 被替换为 existancefamily 被替换为 brood。Pluto 在 Twitter NLP 数据上做了相同的处理,如下所示:

# use word reserved augmentation
pluto.print_aug_word_reserved(pluto.df_twitter_data,
    col_dest='clean_tweet',
    reserved_tokens=pluto.reserved_twitter)

输出如下:

图 5.35 – Twitter 保留字增强

图 5.35 – Twitter 保留字增强

请注意,wisdomfoolishness 被替换为 sagacityidiocyuser 被替换为 peoplecustomer

保留字 增强是本章的最后一种词汇增强方法。Pluto 涵盖了 拼写错误拆分随机同义词反义词保留字增强,但这些只是你可以使用的一些词汇增强技术。

有趣的挑战

挑战是使用 Augly 库或 NLTK、Gensim 或 Textblob 库编写一个新的包装函数。这相对简单。第一步是复制一个包装函数,比如 print_aug_keyboard() 函数。第二步也是最后一步是将 aug_func = nlpaug.augmenter.char.KeyboardAug() 替换为 aug_func = augly.text.functional.simulate_typos()。Augly 函数中有更多参数。一个提示是使用 augly.text.functional.simulate_typos? 命令来显示该函数的文档。

Nlpaug 库和其他文本增强库,如 NLTKGensimTextblobAugly,提供了更多的文本增强方法。此外,最新发布的学术论文也是发现新文本增强技术的绝佳来源。

让我们总结一下本章内容。

总结

初看之下,文本增强似乎违反直觉且有问题,因为这些技术会向文本中注入错误。然而,基于 CNN 或 RNN 的深度学习仍然能够识别模式,不管是拼写错误还是同义词替换。此外,许多已发布的学术论文都描述了文本增强在提高预测或预报准确性方面的好处。

第五章中,你学习了三种字符增强技术,分别是OCR键盘随机。此外,还有六种单词增强技术,分别是拼写错误分割随机同义词反义词保留词。在 Nlgaug、NLTK、Gensim、TextBlob 和 Augly 库中还有更多文本增强方法。

使用 Python Notebook 实现文本增强方法看似简单。因为 Pluto 在第一章中构建了一个面向对象的类,并学习了如何使用装饰器扩展对象,从而在发现新的增强技术时能够加以利用。在第二章中,Pluto 添加了用于下载任何Kaggle真实世界数据集的功能,第三章第四章为我们提供了包装函数模式。因此,在本章中,Pluto 复用了这些方法和模式,使得 Python Notebook 代码简洁易懂。

在整个章节中,包含了有趣的事实有趣的挑战。Pluto 希望你能够利用这些内容,拓展你的经验,超越本章的范围。

下一章将深入探讨使用机器学习方法的文本增强。具有讽刺意味的是,文本增强的目标是使机器学习和深度学习能够准确预测和预报,而我们将使用相同的 AI 系统来提高文本增强的效率。这是一个循环逻辑或周期性过程。

Pluto 正在下一章等你,使用机器学习进行文本增强

第六章:使用机器学习的文本增强

使用机器学习ML)的文本增强是一种比我们在上一章中介绍的标准文本增强方法更为先进的技术。具有讽刺意味的是,文本增强旨在提高机器学习模型的准确性,但我们使用了一个预训练的机器学习模型来创建额外的训练 NLP 数据。这是一个循环过程。本书不涉及机器学习编程,但理解使用库与使用机器学习进行文本增强之间的区别是非常有益的。

增强库,无论是用于图像、文本还是音频,都会遵循传统的编程方法论,包含结构化数据、循环和条件语句。例如,如在第五章中所示,实施_print_aug_reserved()方法的伪代码可能如下所示:

# define synonym words, pseudo-code
reserved = [['happy', 'joyful', 'cheerful'],
  ['sad', 'sorrowful', 'regretful']]
# substitute the word with its synonym, pseudo-code
for i, word in (input_text)
  for set_word in (reserved)
    for i, syn in set_word
      if (syn == word)
        input_text[i] = set_word[i+1]

正常路径的代码未覆盖错误检查,但重点是该库的功能遵循标准的顺序编码方法。

另一方面,机器学习基于 13 种已知的机器学习算法之一,包括_print_aug_reserved()伪代码算法。

以下是用于图像分类的深度学习(DL)架构表示。它展示了过程化方法与神经网络算法之间的区别。此图是通过LatexOverleaf云系统创建的,输出结果如下:

图 6.1 – 深度学习模型的表示

图 6.1 – 深度学习模型的表示

Overleaf 项目及其代码来自 Duc Haba 先生的公开代码库,网址为www.overleaf.com/project/6369a1eaba583e7cd423171b。你可以克隆并修改代码以展示其他 AI 模型。

本章将介绍使用机器学习的文本增强,特别是以下主题:

  • 机器学习模型

  • 词汇增强

  • 句子增强

  • 真实世界的 NLP 数据集

  • 通过 Python 笔记本强化你的学习

让我们简要描述在 Python 包装函数代码中使用的机器学习模型。

机器学习模型

本章中,文本增强包装函数使用机器学习生成新的文本,用于训练机器学习模型。理解这些模型是如何构建的并不在本书范围内,但对这些机器学习模型及其算法的简要描述是必要的。Python 包装函数将在后台使用以下机器学习模型:

  • Tomáš Mikolov 于 2013 年发布了一个名为Word2Vec的神经网络 NLP 算法。该模型可以根据输入文本提议同义词。

  • 全局词向量表示GloVe)算法由 Jeffrey Pennington、Richard Socher 和 Christopher D. Manning 于 2014 年创建。它是一种无监督学习的自然语言处理(NLP)算法,用于将词语表示为向量格式。其结果是一个线性算法,能够将最接*的相邻词汇聚集在一起。

  • Wiki-news-300d-1M 是一个预训练的机器学习模型,使用了fastText开源库。它是基于维基百科 2017 年文章中的 100 万个单词、UMBC WebBase 语料库(包含超过 30 亿个单词)和 Statmt.org 新闻数据集(包含超过 160 亿个词元)进行训练的。T. Mikolov、E. Grave、P. Bojanowski、C. Puhrsch 和 A. Joulin 在他们的论文《预训练分布式词表示的进展》中介绍了Wiki-news-300d-1M。该模型的许可协议为 Creative Commons Attribution-Share-Alike License 3.0。

  • GoogleNews-vectors-negative300 是一个预训练的Word2Vec模型,使用了包含约 1000 亿个单词和 300 个维度的 Google 新闻数据集。

  • Google 于 2017 年推出了transformer神经网络算法。*期自然语言处理和计算机视觉领域的前沿突破均来源于该变换器模型。

  • BERT 模型由 Jacob Devlin、Ming-Wei Chang、Kenton Lee 和 Kristina Toutanova 于 2018 年提出,专门用于语言推理和预测。

  • RoBERTa 是一种优化过的自监督自然语言处理模型算法,建立在 BERT 的基础上。它在许多自然语言处理推理任务中表现优异。Meta AI 于 2019 年发布了 RoBERTa。

  • Facebook 的wmt19-en-dewmt19-de-en是来自HuggingFace的预训练自然语言处理模型,用于从英语翻译到德语(Deutsch)并相互转换。该模型于 2021 年公开发布。

  • Facebook 的wmt19-en-ruwmt19-ru-en是来自HuggingFace的预训练自然语言处理模型,用于从英语翻译到俄语(Русский)并相互转换。该模型于 2021 年公开发布。

  • XLNet 是一个基于 transformer-XL 的预训练模型,由 Zhilin Yang、Zihang Dai、Yiming Yang、Jaime Carbonell、Russ R. Salakhutdinov 和 Quoc V. Le 于 2021 年在HuggingFace上公开发布。该模型在学术论文《XLNet: 用于语言理解的广义自回归预训练》中进行了介绍。

  • 生成式预训练变换器 2GPT-2)算法是一个开源 AI 模型,由 OpenAI 于 2019 年发布。该模型在生成反馈问题与答案以及文章文本摘要方面表现出色,且与人类写作水*相当。

  • T5T5X 模型使用文本到文本的变换器算法。它们是基于庞大的语料库进行训练的。Colin Raffel、Noam Shazeer、Adam Roberts、Katherine Lee、Sharan Narang、Michael Matena、Yanqi Zhou、Wei Li 和 Peter J. Liu 在 2020 年的论文《探索统一文本到文本变换器的迁移学习极限》中介绍了 T5。

有趣的事实

生成式人工智能,当使用变换器模型时,例如 OpenAI 的 GPT-3、GPT-4 或 Google Bard,能够写出与人类作家一样好的内容,甚至更好。

现在我们了解了一些机器学习模型,接下来我们来看看哪些增强功能使用了哪些机器学习模型。

词汇增强

在这一章中,词语增强技术类似于第五章中的方法,该方法使用了Nlpaug库。不同之处在于,包装函数使用强大的机器学习模型来实现显著的效果,而非 Python 库。有时,输出或重写的文本与人类写作非常相似。

具体来说,你将学习四种新技术,每种技术有两种变体。让我们从 Word2Vec 开始:

  • Word2Vec方法使用神经网络 NLP Word2Vec 算法和 GoogleNews-vectors-negative300 预训练模型。Google 使用包含约 1000 亿个单词和 300 维度的大型语料库进行了训练。替换和插入是两种模式变体。

  • BERT方法使用 Google 的 Transformer 算法和 BERT 预训练模型。替换和插入是两种模式变体。

  • RoBERTa方法是 BERT 模型的一种变体。替换和插入是两种模式变体。

  • 在本章中,我们将介绍的最后一种词语增强技术是使用 Facebook(Meta)的预训练翻译模型进行反向翻译。它将输入的英文文本翻译成另一种语言,然后再翻译回英文。我们将研究的两种变体涉及将英文翻译成德语(Deutsch),然后再翻译回英文,使用的是facebook/wmt19-en-defacebook/wmt19-de-en模型;将英文翻译成俄语(Русский),然后再翻译回英文,使用的是facebook/wmt19-en-rufacebook/wmt19-ru-en模型。

通过查看词语包装函数的输出,这将更容易理解,但在此之前,我们先来描述句子增强。

句子增强

在句子级别进行增强是一个强大的概念,5 年前这是无法实现的。你必须在机器学习研究公司工作,或者是亿万富翁,才能访问这些著名的预训练模型。某些 Transformer 和大型语言模型LLMs)在 2019 和 2020 年作为开源发布,但它们通常用于研究。当时,方便通过 GPU 访问在线 AI 服务器并不普及。LLM 和预训练模型最*才开始向公众开放,可以将它们集成到你的项目中,如 HuggingFace 网站。重要的是,对于独立研究人员或学生来说,LLM 和预训练模型直到 2021 年中才开始变得可访问。

使用机器学习的句子和词语增强方法不能像使用Nlpaug库的方法那样动态进行。换句话说,你必须将增强后的文本写入并保存到本地或云端磁盘空间。其主要原因是每个训练周期的增强步骤所需时间过长。优点是,你可以将原始文本的大小增加 20 到 100 倍。

具体来说,我们将介绍以下技术:

  • 使用T5 NLP 算法进行文本摘要。

  • 顺序有时是两种句子流方法。这些流方法结合了 GloVeBERT NLP 算法。

对于句子增强技术,通过使用真实世界的 NLP 数据集作为输入文本并查看包装函数的输出,更容易理解这些技术。因此,接下来的部分将介绍如何用 Python 代码编写包装函数来深入了解句子增强,但首先,让我们下载真实世界的 NLP 数据集。

真实世界的 NLP 数据集

本章将使用与第五章相同的 Netflix 和 Twitter 真实世界 NLP 数据集。此外,两个数据集已经经过审核、清洗,并存储在本书 GitHub 仓库中的 pluto_data 目录中。启动过程与前几章相似,步骤如下:

  1. 克隆 Python Notebook 和 Pluto。

  2. 验证 Pluto。

  3. 定位 NLP 数据。

  4. 将数据加载到 pandas。

  5. 查看数据。

让我们从 Python Notebook 和 Pluto 开始。

Python Notebook 和 Pluto

首先将 data_augmentation_with_python_chapter_6.ipynb 文件加载到 Google Colab 或您选择的 Jupyter Notebook 或 JupyterLab 环境中。从这一点开始,我们将仅显示代码片段。完整的 Python 代码可以在 Python Notebook 中找到。

下一步是克隆仓库。我们将重用第五章的代码。使用 !git%run 语句来实例化 Pluto:

# clone Packt GitHub repo.
!git clone 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
# Instantiate Pluto
%run 'Data-Augmentation-with-Python/pluto/pluto_chapter_5.py'

输出如下:

---------------------------- : ----------------------------
                        Hello from class : <class '__main__.PacktDataAug'> Class: PacktDataAug
                                     Code name : Pluto
                                     Author is : Duc Haba
---------------------------- : ----------------------------

接下来的设置步骤是检查 Pluto 是否正确加载。

验证

以下命令要求 Pluto 显示他的状态:

# Am I alive?
pluto.say_sys_info()

输出将如下所示,具体取决于您的系统:

---------------------------- : ----------------------------
                 System time : 2022/11/09 05:31
                    Platform : linux
     Pluto Version (Chapter) : 5.0
             Python (3.7.10) : actual: 3.7.15 (default, Oct 12 2022, 19:14:55) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.12.1+cu113
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 12
                  CPU speed : NOT available
---------------------------- : ----------------------------

Pluto 显示他来自第五章(版本 5.0),这是正确的。此外,清洗后的 NLP Twitter 和 Netflix 数据集已存储在 ~/``Data-Augmentation-with-Python/pluto_data 目录中。

真实世界的 NLP 数据

Pluto 正在使用来自第五章的干净版本数据,这些数据没有脏话。它们是来自 Kaggle 网站的 Netflix 和 Twitter NLP 数据集。清洗后的数据集已经保存在本书的 GitHub 仓库中。因此,Pluto 不需要再次下载它们。不过,您仍然可以通过 fetch_kaggle_dataset() 函数下载它们或其他真实世界数据集。Pluto 使用以下命令来定位已清洗的 NLP 数据集:

# check to see the files are there
f = 'Data-Augmentation-with-Python/pluto_data'
!ls -la {f}

输出如下:

drwxr-xr-x 2 root root    4096 Nov 13 06:07 .
drwxr-xr-x 6 root root    4096 Nov 13 06:07 ..
-rw-r--r-- 1 root root 3423079 Nov 13 06:07 netflix_data.csv
-rw-r--r-- 1 root root 6072376 Nov 13 06:07 twitter_data.csv

有趣的事实

Pluto 变懒了,他没有使用 Python 库和用 Python 编码,而是通过下达 Linux Bash 命令行代码作弊。感叹号字符 (!) 允许 Python Notebook 后门进入内核,例如在 Linux 上使用 !ls -la 或在 Windows 上使用 !dir。您可以使用任何操作系统的命令行代码。但这不是可移植的代码,因为 Windows、iOS、Linux、Android 等操作系统(支持 Safari、Chrome、Edge 和 Firefox 等网页浏览器)上的命令是不同的。

下一步是将数据加载到 Pluto 的伙伴 pandas 中。

Pandas

Pluto 重用了 第二章 中的 fetch_df() 方法,将数据加载到 pandas 中。以下命令将真实世界的 Netflix 数据导入 pandas:

# import to Pandas
f = 'Data-Augmentation-with-Python/pluto_data/netflix_data.csv'
pluto.df_netflix_data = pluto.fetch_df(f,sep='~')

同样,加载真实世界 Twitter 数据的命令如下:

# import to Pandas
f = 'Data-Augmentation-with-Python/pluto_data/twitter_data.csv'
pluto.df_twitter_data = pluto.fetch_df(f,sep='~')

有趣的挑战

Pluto 挑战你从 Kaggle 网站找到并下载两个额外的 NLP 数据。提示:使用 Pluto 的 fetch_kaggle_dataset() 函数。使用 fetch_df() 函数将其导入 pandas。

现在,Pluto 已经定位并将数据导入 pandas,加载数据序列的最后一步是查看和验证数据。

查看文本

draw_word_count()draw_null_data() 方法帮助我们理解 NLP 数据,Pluto 建议重新查看 第五章,以查看那些 Netflix 和 Twitter 图表。一种更有趣、更丰富多彩的方法是使用 draw_word_cloud() 函数。

Pluto 使用以下命令绘制 Netflix 词云信息图:

# draw infographic plot
pluto.draw_text_wordcloud(pluto.df_netflix_data.description,
  xignore_words=wordcloud.STOPWORDS,
  title='Word Cloud: Netflix Movie Review')

输出如下:

图 6.2 – Netflix 词云

图 6.2 – Netflix 词云

同样,Pluto 使用以下命令显示 Twitter 词云:

# draw infographic plot
pluto.draw_text_wordcloud(pluto.df_twitter_data.clean_tweet,
  xignore_words=wordcloud.STOPWORDS,
  title='Word Cloud: Twitter Tweets')

输出如下:

图 6.3 – Twitter 词云

图 6.3 – Twitter 词云

除了真实世界的 NLP 数据,Pluto 还使用了查尔斯·狄更斯的《双城记》前几行作为控制文本。在本章中,Pluto 将扩展控制文本,加入狄更斯先生的《双城记》第一页、梅尔维尔的《白鲸》和卡罗尔的《爱丽丝梦游仙境》。这些书籍是公共领域作品,定义见古腾堡计划。

变量分别为 pluto.orig_textpluto.orig_dickens_pagepluto.orig_melville_pagepluto.orig_carroll_page

有趣的事实

机器学习擅长改变典型的人类写作文本,但修改经典作品几乎是犯罪行为。Pluto 只希望阐明增强概念,绝不亵渎经典。这一切都是为了科学。

你已经加载了 Python Notebook,实例化了 Pluto,访问了清理过的 NLP 真实世界数据,并通过词云信息图进行了验证。现在,是时候编写并调试 Python 代码,以更深入地了解机器学习中的单词和句子增强。

通过 Python Notebook 加强你的学习

尽管 NLP ML 非常复杂,包装代码的实现却出奇地简单。这是因为 Pluto 采用了结构化的面向对象方法。首先,我们在第一章中为 Pluto 创建了一个基础类,并使用装饰器在学习新的增强概念时添加了新方法。在第二章中,Pluto 学会了从 Kaggle 网站下载成千上万的真实世界数据集。第三章第四章介绍了包装函数的处理过程,使用了强大的开源库。最后,第五章提出了使用Nlpaug库时的文本增强概念和方法。

因此,基于我们之前的知识,本章中的包装函数使用强大的 NLP ML 预训练模型来执行增强。

本章将特别介绍包装函数和使用以下技术对 Netflix 和 Twitter 真实世界数据集进行增强的结果:

  • Word2Vec 词语增强

  • BERTTransformer 词语增强

  • RoBERTa 增强

  • 回译

  • T5 增强

  • SequentialSometime 增强

让我们从 Word2Vec 开始。

Word2Vec 词语增强

print_aug_ai_word2vec()包装函数的关键参数如下:

# code snippet for print_aug_ai_word2vec()
model_type = 'word2vec',
model_path = 'GoogleNews-vectors-negative300.bin'
action = 'insert'    # or 'substitute'
nlpaug.augmenter.word.WordEmbsAug(model_type,
  model_path,
  action)

完整的函数可以在 Python Notebook 中找到。Pluto 使用真实世界的 NLP Netflix 数据来测试该函数,具体如下:

# augment using word2vec
pluto.print_aug_ai_word2vec(pluto.df_netflix_data,
  col_dest='description',
  action='insert',
  aug_name='Word2Vec-GoogleNews Word Embedding Augment')

趣味事实

当你运行一个包装函数时,新的数据会被随机选择并处理。因此,最好反复运行包装函数,查看来自 Netflix 数据集的不同电影评论或来自 Twitter 数据集的不同推文。

输出如下:

图 6.4 – 使用插入模式的 Word2Vec 在 Netflix 数据上的应用

图 6.4 – 使用插入模式的 Word2Vec 在 Netflix 数据上的应用

图 6.3中,第一行是控制输入。它摘自《双城记》这本书。你会发现,通过将控制文本与数据集中的文本进行对比,增强效果更容易察觉。此外,控制文本对于比较不同增强技术之间的差异也是必需的。

Pluto 发现,在第 1 行中注入的名称,如Punta(一个可信的西班牙作家名字)和Poydras,作为实际名称和可行的添加物,符合这个名人电影评论的背景。虽然这些名字在电影中并不真实出现,但它们在电影情感预测的文本增强中是可以接受的。

第 2 行中,blendingdangerousoriginal 1960s这几个词为电影描述增添了色彩,同时又不改变间谍电影描述的意图。

第 3 行,在漫画《绿箭侠》电影描述中,加入像Kent of Cabus(来自英国 Cabus 村的 Kent)、Rangjung(不丹的一个村庄,作为可能的英雄名字)和Elizabeth(作为反派角色)的名字是 100%合理的情节设定,适合我们的超级英雄。

总的来说,Pluto 对Word2Vec机器学习模型感到惊讶。单词和名字的插入情境非常合适,仿佛是人类作家创作的。然而,狄更斯的控制文本读起来非常有趣,这并不是机器学习的错。系统并不知道这本书是 19 世纪写的,只根据文本的前几行做出了推断。电影评论是完整的思路,而控制文本只是片段之一。

Pluto 对真实世界的 Twitter 数据执行类似的命令,具体如下:

# augment using word2vec
pluto.print_aug_ai_word2vec(pluto.df_twitter_data,
  col_dest='clean_tweet',
  action='insert',
  aug_name='Word2Vec-GoogleNews Word Embedding Augment')

输出如下:

图 6.5 – Word2Vec 在 Twitter 数据上的插入模式

图 6.5 – Word2Vec 在 Twitter 数据上的插入模式

由于推文就像是没有经过深思熟虑或编辑的随机想法,在图 6.4中,Word2Vec的插入就像一个无聊的高中生一边做作业一边玩电脑游戏。Pluto 无法判断修改后的文本是否合理。这会增加还是减少 AI 在情感分析中的预测准确性?

对于狄更斯的控制文本,Pluto 感到震惊。它非常糟糕,但他承诺当使用变换器和生成 AI 时,后续模型会更好。

现在我们看过了insert模式,让我们看看Word2Vec模型在substitute模式下的表现。

Substitute

Substitute模式会替换单词,并且在句子中添加单词。Pluto 将Word2Vec模型以substitute模式应用于 Netflix 数据,具体如下:

# augmenting using word2vec
pluto.print_aug_ai_word2vec(pluto.df_netflix_data,
  col_dest='description',
  action='substitute',
  aug_name='Word2Vec-GoogleNews Word Embedding Augment')

输出如下:

图 6.6 – Word2Vec 在 Netflix 数据上的替换模式

图 6.6 – Word2Vec 在 Netflix 数据上的替换模式

图 6.5中,第 0 行是控制文本,而第 1 行中,zany adventure适合儿童冒险电影,但liquid viagra显然不合适。

第 2 行,将police替换为troopersjob替换为plum assignmentwrest替换为must takefigure替换为hand,以及将offenders替换为criminals,这些在警匪电影中是合适的。因此,Word2Vec模型做了适当的增强处理。

第 3 行,将cinematic distillation替换为Scorcese decaffeination是一个有趣的选择,值得人类作家考虑。将electrifying改为sparkling很聪明,因为电力可以产生火花。将shadowy替换为clandestine是个不错的选择,但将seven改为five则显得不必要。

再次说明,Word2Vec模型在控制文本的处理上本可以做得更好。

Pluto 对 Twitter 数据做了同样的处理,命令如下:

# augmenting using word2vec
pluto.print_aug_ai_word2vec(pluto.df_twitter_data,
  col_dest='clean_tweet',
  action='substitute',
  aug_name='Word2Vec-GoogleNews Word Embedding Augment')

输出如下:

图 6.7 – Word2Vec 在 Twitter 数据上使用替换模式

图 6.7 – Word2Vec 在 Twitter 数据上使用替换模式

图 6.6中,推文杂乱无章,许多内容是不完整的想法。Word2Vec模型尽力而为,而 Pluto 认为没有人类能做得更好。

接下来我们要探讨的技术是 BERT,它使用变压器模型和生成性 AI。

BERT

BERT 是一个由 Google 开发的变压器模型,经过大量语料库的训练。结果是接*完美的人类质量输出。从 2022 年 8 月中旬开始,BERT 和许多其他变压器模型通过 HuggingFace 向公众开放,易于获取。

print_aug_ai_bert() 函数的关键代码行如下:

# code snippet for print_aug_id_bert()
model_path='bert-base-uncased'
aug_func = nlpaug.augmenter.word.ContextualWordEmbsAug(
  action=action,
  model_path=model_path)

完整的函数可以在 Python Notebook 中找到。Pluto 使用 insert 模式将 NLP Netflix 数据输入,命令如下:

# Augmenting using BERT
pluto.print_aug_ai_bert(pluto.df_netflix_data,
  col_dest='description',
  action='insert',
  aug_name='BERT Embedding Insert Augment')

结果如下:

图 6.8 – BERT 在 Netflix 数据上使用插入模式

图 6.8 – BERT 在 Netflix 数据上使用插入模式

图 6.7中,Pluto 立刻识别出与 Word2Vec 模型的改进。在控制文本第 0 行中,插入的单词是可以接受的。虽然缺乏散文的优雅,但如果必须在文本中加入单词,这样的文本看起来像人类写的。

第 1 行,添加的短语恰到好处,如 afterward(之后)、financial dubious(财务可疑)、knee surgery(膝盖手术)、和 to play a national film stage(演奏国家级电影舞台)。

第 2 行,增强的短语质量达到了人类作家的水*,如 whilst in hiding(在隐藏中)、deeply suspect(深度可疑)、unknown maid(未知的女仆)、perhaps his only(或许是他唯一的)、outside Russian world(俄罗斯外部世界)、以及 maybe hiding quite something(也许隐藏着某种东西)。

第 3 行,Pluto 对结果印象深刻,例如 arriving in February(二月到达)、little Indian lad(小印度男孩)、despite sparse funding(尽管资金稀缺)、funding mathematics and physics(资助数学和物理)、和 first functioning airplane(第一架有功能的飞机)。

有趣的事实

你是否像 Pluto 一样对 BERT 模型的输出感到惊讶?它就像是一个真人,而不是一个人工神经网络(ANN)。

请重新运行包装函数,查看 BERT 对其他电影评论的增强效果。你读得越多,就越能欣赏使用 变压器 模型的先进突破。它是生成性 AI 的基础。

接下来,Pluto 使用插入模式将 Twitter 数据输入 BERT 模型,命令如下:

# augmenting using BERT
pluto.print_aug_ai_bert(pluto.df_twitter_data,
  col_dest='clean_tweet',
  action='insert',
  aug_name='BERT Embedding Insert Augment')

结果如下:

图 6.9 – BERT 在 Twitter 数据上使用插入模式

图 6.9 – BERT 在 Twitter 数据上使用插入模式

有趣的事实

图 6.8中,BERT 模型给出了另一版本的狄更斯控制文本。每次 Pluto 运行包装函数时都会得到一个新的版本。可能性是无穷无尽的。Pluto 必定运行了超过 50 次包装函数。每次结果都不同。

Pluto 发现有比推文更适合研究的 NLP 数据,但它们代表了真实世界,因此值得继续使用。当 Pluto 反复运行包装函数时,他更喜欢 BERT 增强版的推文而不是原始推文,因为插入文本使其更易阅读。

当切换到替换模式时,BERT 的输出优于普通人类写作。

替换

接下来,Pluto 使用以下命令将 Netflix 数据以替换模式输入到 BERT 中:

# augmenting using BERT
pluto.print_aug_ai_bert(pluto.df_netflix_data,
  col_dest='description',
  action='substitute',
  aug_name='BERT Embedding Substitute Augment')

结果如下:

图 6.10 – BERT 在 Netflix 数据上使用替换模式

图 6.10 – BERT 在 Netflix 数据上使用替换模式

图 6.9中,对于控制文本,第 #0 行,BERT 将它是愚蠢的时代替换为死亡是爱的时代

有趣的事实

停止。Pluto 的思维被震撼了。甚至 Pluto 的人类伙伴也无言以对。Pluto 期待像 BERT 这样的变压器模型能做到很好,但哲学思考或诗歌是另一个层次的。现在,你对 BERT 印象深刻了吗?

剩余的电影评论增强内容,如第 #1 行第 #2 行第 #3 行,完美无瑕。增强后的词语与电影的类型和背景契合。就像 BERT 理解了电影的意义,但这并不真实。BERT 模型并不像烤面包机那样具备意识。然而,BERT 确实能很好地模仿人类写作。

一个有趣的注释是,在第 #1 行中,在描述一对情侣关系的电影描述中,BERT 使用了词汇gay,这在上一章关于数据偏见中有讨论过。因为gay是一个形容轻松和无忧无虑的词汇,但在现代语境下,gay通常与一个人的同性恋倾向,尤其是男性的同性恋倾向相关联。

再次提醒,Pluto 鼓励你在 Python Notebook 上反复运行包装函数。你将会超越技术成就的欣赏,觉得 BERT 甚至有了个性。

Pluto 使用以下命令对 Twitter 数据进行了相同的处理:

# augmenting using BERT
pluto.print_aug_ai_bert(pluto.df_twitter_data,
  col_dest='clean_tweet',
  action='substitute',
  aug_name='BERT Embedding Substitute Augment')

结果如下:

图 6.11 – BERT 在 Twitter 数据上使用替换模式

图 6.11 – BERT 在 Twitter 数据上使用替换模式

当 Pluto 在 Python Notebook 上反复运行包装函数时,在图 6.10中,他发现增强后的推文比原始文本更易于阅读。

对于控制文本,第 #0 行,Pluto 发现将增强后的文本它是青春的时代替换原文它是信仰的时代,是非常合适的。这与狄更斯先生书中的背景和风格非常契合。

有趣的挑战

这个挑战是一个思维实验。BERT 是基于人工神经网络(ANN)算法构建的。它不包含语法规则,比如名词和动词用来构造句子。没有语法规则,它是如何写出如此流利的英语的呢?提示:考虑模式。BERT 在庞大的语料库上进行了训练。单词和句子的数量大到五年前根本无法想象。很少有人知道神经网络算法是如何学习的。这不是复杂的数学问题。它是梯度下降和矩阵乘法推动数十亿个节点(或神经元),但这些节点的集合又是如何写出让人信服的英语的呢?

冥王星可以花几天时间讨论 BERT,但让我们继续深入了解RoBERTaRoberta)。这听起来像是 BERT 的女性版。

RoBERTa

RoBERTa 是 BERT 的自监督优化算法。虽然 BERT 是由谷歌创建的,但 RoBERTa 是 Meta AI(或 Facebook)开发的。

冥王星用以下命令将 Netflix 数据输入 RoBERTa 的插入模式:

# augmenting using Roberta
pluto.print_aug_ai_bert(pluto.df_netflix_data,
  col_dest='description',
  model_path='roberta-base',
  action='insert',
  aug_name='Roberta Embedding Insert Augment')

结果如下:

图 6.12 – RoBERTa 在 Netflix 数据上使用插入模式

图 6.12 – RoBERTa 在 Netflix 数据上使用插入模式

图 6.11中的输出与BERT的输出相似,令人印象深刻。单词并不是随机插入句中的。它们表达了可能的解释,并给人一种RoBERTa理解单词意义的印象。这样的技术成就 1 年前是无法实现的,而RoBERTa几个月前才发布。

冥王星反复运行包装函数,并且从未厌倦阅读结果。他用以下命令对 Twitter 数据做了相同的操作:

# augmenting using Roberta
pluto.print_aug_ai_bert(pluto.df_twitter_data,
  col_dest='clean_tweet',
  model_path='roberta-base',
  action='insert',
  aug_name='Roberta Embedding Insert Augment')

结果如下:

图 6.13 – RoBERTa 在 Twitter 数据上使用插入模式

图 6.13 – RoBERTa 在 Twitter 数据上使用插入模式

冥王星无法将铅变成金子,而 RoBERTa 也无法将如图 6.12所示的包含拼写错误和不完整想法的推文转化为连贯的句子。尽管如此,RoBERTa 仍然是增强现实世界推文的最佳选择之一。

接下来,冥王星将尝试使用替换模式的RoBERTa

替换

在替换模式下,RoBERTa 将根据上下文和写作风格,以惊人的准确度替换单词或短语。

冥王星将 Netflix 数据以替换模式输入 RoBERTa 模型,使用以下命令:

# augmenting using Roberta
pluto.print_aug_ai_bert(pluto.df_netflix_data,
  col_dest='description',
  model_path='roberta-base',
  action='substitute',
  aug_name='Roberta Embedding Substitute Augment')

输出如下:

图 6.14 – RoBERTa 在 Netflix 数据上使用替换模式

图 6.14 – RoBERTa 在 Netflix 数据上使用替换模式

无论冥王星执行多少次包装函数,他仍然对 RoBERTa 在图 6.13中提供的输出感到惊讶。例如,在第 1 行,她将短语Alex discovers he has little in common with the local改为Alex discovers Flix had special romantic chemistry with the local。RoBERTa 真是富有想象力。这就是人类写作时的方式吗?

冥王星使用以下命令对 Twitter 数据执行相同操作:

pluto.print_aug_ai_bert(pluto.df_twitter_data,
  col_dest='clean_tweet',
  model_path='roberta-base',
  action='substitute',
  aug_name='Roberta Embedding Substitute Augment')

结果如下:

图 6.15 – RoBERTa 在 Twitter 数据上的替代模式使用

图 6.15 – RoBERTa 在 Twitter 数据上的替代模式使用

图 6.14所示,文本增强不必是枯燥或临床的。使用 BERT 和 RoBERTa 等变换器模型,增强过程既有趣又充满奇迹。例如,在控制文本中,第 0 行,RoBERTa 写道,它对傲慢宣讲了诅咒,取代了这是一个信仰的时代

有趣的事实

冥王星的人类伴侣需要经过长时间的思考,才能得出结论:增强文本确实与图 6.14中的原始文本——控制文本——意义相同。很容易被误导,认为 RoBERTa 有良知。我们将智能与意识相联系,意味着如果你有智能,你必须是自我意识的,反之亦然,但我们知道这并不成立。例如,一名职业政治家非常自我意识。他一直在谈论自己,但他聪明吗?

继续使用最新的强大 ML 模型,冥王星将通过使用反向翻译技术走上不同的文本增强道路。

反向翻译

反向翻译是文本增强中的一个新概念,因为在两年前是不可行的。机器学习的自然语言处理(ML NLP)技术早已存在,Google 翻译也一直在推进。但只有少数数据科学家能够使用变换器和进行语言翻译所需的强大服务器,访问大型语言模型。

文本增强的技术是将文本翻译成另一种语言,然后再翻译回原语言。通过这种方式,结果将是原始文本的增强版本。没有任何语言翻译是完美的,因此扩展版本会与原始文本略有不同。例如,原文是英文的。使用强大的 NLP 模型,我们将其翻译成德语,然后再翻译回英语。翻译后的英语文本将与原始的英语文本有所不同。

Word2VecBERTRoBERTa相比,反向翻译方法可能更具鲁棒性。这是因为翻译回原文时,第二次或第三次得到的结果是相同的。换句话说,其他方法的输出会产生成千上万种变化,而反向翻译则只有两三种增强版本。

冥王星在HuggingFace网站上找到了两个来自 Facebook(或 Meta AI)的 NLP 预训练翻译模型,它们支持英语到德语(Deutsch)和英语到俄语(Русский)。还有更多的模型,但这两个足以展示该技术。让我们从德语开始。

德语 (Deutsch)

print_aug_ai_back_translation()方法遵循与其他包装函数相同的结构。它看起来 deceptively 简单,只有五行代码,但实际上包含了复杂的理论和编码技巧。这让 Pluto 想起了艾萨克·牛顿爵士的名言:“如果我看得更远,那是因为站在了 巨人的肩膀上。

关键代码行如下:

# code snippet for back translation
from_model_name='facebook/wmt19-en-de'
to_model_name='facebook/wmt19-de-en'
aug_func = nlpaug.augmenter.word.BackTranslationAug(
  from_model_name=from_model_name,
  to_model_name=to_model_name)

完整的函数可以在 Python Notebook 中找到。Pluto 使用以下命令将 Netflix 数据输入:

# augmenting using back translation
pluto.print_aug_ai_back_translation(pluto.df_netflix_data,
  col_dest='description',
  from_model_name='facebook/wmt19-en-de',
  to_model_name='facebook/wmt19-de-en',
  aug_name='FaceBook Back Translation: English <-> German Augment')

结果如下:

图 6.16 – 回译,Netflix 数据中的德语

图 6.16 – 回译,Netflix 数据中的德语

趣事

图 6.15中的输出令人失望,因为它与原文相似,但这一技术成就令人震惊。首先,你需要一位专家将英语翻译成德语。这对人类来说是一个具有挑战性的任务。其次,你必须将其无误地翻译回英语。选择类似词语的差异体现在表达上。也许只有全球 5% 的人能完成这个任务。让机器全天候、每周 7 天、维持同样的准确性水*来完成这项任务是神奇的。没有人类能够达到这个水*。

图 6.15中的输出提供了几乎完美的英德回译。Pluto 用以下命令对 Twitter 数据做了相同的操作:

# augmenting using back translation
pluto.print_aug_ai_back_translation(pluto.df_twitter_data,
  col_dest='clean_tweet',
  from_model_name='facebook/wmt19-en-de',
  to_model_name='facebook/wmt19-de-en',
  aug_name='FaceBook Back Translation: English <-> German Augment')

输出如下:

图 6.17 – 回译,Twitter 数据中的德语

图 6.17 – 回译,Twitter 数据中的德语

图 6.16中,将无意义的推文翻译成德语并回译对人类来说更困难,因为我们的思维更容易疲劳并且会放弃。只有机器才能全天候完成这项工作。控制文本的德语回译是可以接受的。

将文本翻译成俄语并回译会产生类似的结果。我们来看看。

俄语(Русский)

Pluto 选择重复相同的英俄回译技术,因为他好奇选择非罗曼语族语言是否会对增强结果产生不同的影响。

使用相同的print_aug_ai_back_translation()函数,Pluto 将俄语翻译的 Facebook 模型定义如下:

# code snippet for back translation to Russian
from_model_name='facebook/wmt19-en-ru'
to_model_name='facebook/wmt19-ru-en'

完整的函数代码可以在 Python Notebook 中找到。Pluto 将 Netflix 数据传递给包装函数如下:

# augmenting using back translation
pluto.print_aug_ai_back_translation(pluto.df_netflix_data,
  col_dest='description',
  from_model_name='facebook/wmt19-en-ru',
  to_model_name='facebook/wmt19-ru-en',
  aug_name='FaceBook Back Translation: English <-> Russian Augment')

结果如下:

图 6.18 – 回译,Netflix 数据中的俄语

图 6.18 – 回译,Netflix 数据中的俄语

值得注意的是,在图 6.17中,NLP T5 模型将一种罗曼语族语言(英语)翻译成一种东斯拉夫语言(俄语)并回译,几乎达到了完美的准确性。语法规则、句子结构、字母表、历史、文化和语言都不同,但机器能够在没有意识的情况下完成这项任务。

推文不适合测试,但并非所有项目都是合乎逻辑的。Pluto 曾参与过一些构思不周的现实世界 NLP 项目。向包装函数提供推特数据的命令如下:

# augmenting using back translation
pluto.print_aug_ai_back_translation(pluto.df_twitter_data,
  col_dest='clean_tweet',
  from_model_name='facebook/wmt19-en-ru',
  to_model_name='facebook/wmt19-ru-en',
  aug_name='FaceBook Back Translation: English <-> Russian Augment')

结果如下:

图 6.19 – 反向翻译,推特数据上的俄语

图 6.19 – 反向翻译,推特数据上的俄语

如果俄罗斯人不能理解推文,那么还有谁能呢?阅读图 6.18中的控制文本,Pluto 可以判断翻译是否正确。由于某些推文较短,翻译成俄语后再翻回英语非常完美。

有趣的挑战

这个挑战是一个思想实验。你能否使用相同的技术来增强德语?或者你能否将几个反向翻译组合在一起——例如,从英语翻译到德语,再到俄语,最后回到英语?

反向翻译RoBERTaBERTWord2Vec NLP 机器学习模型是文本增强的最先进技术。下一个层次是使用摘要和顺序及有时技术的句子增强。

句子增强

句子级别使用了多种词汇增强方法的结合。但在此之前,Pluto 将使用T5 NLP 模型生成文本摘要。摘要技巧是最*才实现的一项新概念。它可以将一页、一篇文章甚至一本书生成一个摘要,用于 NLP 文本增强模型中。

摘要技巧

对于文本增强,摘要技巧可能会带来几个不同的版本进行训练。然而,假设 Pluto 将摘要技巧结合起来,例如,向技巧提供摘要文本,而不是原始文本,在这种情况下,它将生成许多新的原始文本用于训练。

有趣的事实

Pluto 首创了摘要到流的概念,用于文本增强。他在网上和学术出版物中做了初步搜索,但他需要帮助找到摘要到流技巧的参考文献。如果没有找到相关资料,那么 Pluto 就是第一个实现该策略的人。

Pluto 不会使用 Netflix 电影描述或 Twitter 推文作为摘要方法。这是因为它们太短,无法展示 T5 NLP 模型的强大功能。相反,Pluto 将使用以下现实世界 NLP 数据部分提到的书籍的第一页:

  • 双城记 由狄更斯所著

  • 白鲸 由梅尔维尔所著

  • 爱丽丝梦游仙境 由卡罗尔所著

再次强调,这些书籍是公有领域的,如古腾堡计划所定义。

此外,Pluto 将使用本章的第一页,因为你已经读过这本书,但你可能没有读过那三本经典书籍。

print_aug_ai_t5()包装函数的关键代码行如下:

aug_func = nlpaug.augmenter.sentence.AbstSummAug(
  model_path='t5-base')

普鲁托正在和你玩猜谜游戏。首先,他将列出四条命令行来生成四个摘要,但他会将输出结果打乱顺序。因此,你必须猜出哪个摘要属于哪本书。你将再次对T5 NLP 模型的输出质量感到惊讶,它可与人类作家相媲美。

深刻的意义在于,你或普鲁托可以通过几行 Python 代码自动生成书籍、论文、文档、文章和帖子摘要。几年前,这项任务被认为是不可能完成的。

有趣的挑战

这里有一个思维实验。你能在不懂德语的情况下成为德国法律的专家吗?一年前这是不可能的,因为当时没有机器学习的突破,但今天,你可以使用 Python Notebook 中的代码作为基础,翻译所有德国语法书籍。

获取我们将要查看的四本书第一页摘要的四条命令如下:

# Alice in Wonderland
pluto.df_t5_carroll = pluto.print_aug_ai_t5(
  pluto.orig_carroll_page,
  bsize=1)
# Tale of Two Cities
pluto.df_t5_dickens = pluto.print_aug_ai_t5(
  pluto.orig_dickens_page,
  bsize=1)
# Moby Dick
pluto.df_t5_melville = pluto.print_aug_ai_t5(
  pluto.orig_melville_page,
  bsize=1)
# This chapter first page
pluto.df_t5_self = pluto.print_aug_ai_t5(
  pluto.orig_self,
  bsize=1)

打乱顺序的结果如下:

图 6.20 – 摘要 T5 NLP 引擎 – 1

图 6.20 – 摘要 T5 NLP 引擎 – 1

第二个输出如下:

图 6.21 – 摘要 T5 NLP 引擎 – 2

图 6.21 – 摘要 T5 NLP 引擎 – 2

第三个输出如下:

图 6.22 – 摘要 T5 NLP 引擎 – 3

图 6.22 – 摘要 T5 NLP 引擎 – 3

第四个输出如下:

图 6.23 – 摘要 T5 NLP 引擎 – 4

图 6.23 – 摘要 T5 NLP 引擎 – 4

有趣的挑战

你能将摘要与书籍匹配起来吗?T5 引擎并不像 OpenAI GPT3、GPT4 或 Google Bard 那样是一个生成型人工智能引擎,但它的摘要非常准确。

双城记书籍,如图 6.19所示,是一本相对较难读的书,普鲁托觉得非常有趣的是,现代政治评论员大卫·罗斯科普夫竟然与狄更斯的这本书有关联。书的第一页确实提到了英国臣民在美国的议会。因此,罗斯科普夫先生的关联是一个很好的猜测,也许普鲁托应该将章节的前 10 页输入到T5 NLP 引擎中,并查看摘要。

白鲸的第一页摘要非常到位,如图 6.20所示。它可以与人类作家的作品相媲美,第一页的第一个词是以实马利。普鲁托希望T5 NLP 模型能在他上学的早期就出现。

普鲁托的人类伙伴高兴地承认,这一章节第一页的摘要更为精准且易于阅读,如图 6.21所示。也许T5 NLP 引擎应该和普鲁托一起共写这本书,这样他的伙伴就能在阳光明媚的下午享受追逐松鼠的乐趣。

爱丽丝梦游仙境的第一页摘要完美无缺,如图 6.22所示。T5 NLP 引擎无误地捕捉到了开篇的内容。作为额外奖励,普鲁托只输入了前五句话。输出如下:

图 6.24 – 摘要 T5 NLP 引擎 – 《爱丽丝梦游仙境》前五行

图 6.24 – 总结 T5 NLP 引擎 – 《爱丽丝梦游仙境》的前五行

图 6.23中,T5如何知道白兔是故事中的关键?兔子只在输入文本的最后一句话中出现,称爱丽丝为雏菊链的制造者非常有趣。

句子增强的下一步是将这些摘要输入到方法中。

总结到流技术

流技术中的顺序方法按顺序应用增强列表。Pluto 创建了两个文本增强方法,如下所示:

# augment using uloVe
pluto.ai_aug_glove = nlpaug.augmenter.word.WordEmbsAug(
    model_type='glove', model_path='glove.6B.300d.txt',
    action="substitute")
# augment using BERT
pluto.ai_aug_bert = nlpaug.augmenter.word.ContextualWordEmbsAug(
  model_path='bert-base-uncased',
  action='substitute',
  top_k=20)

第一个使用print_aug_ai_sequential()包装函数,它使用增强列表和关键代码行,如下所示:

# augment using sequential
aug_func = nlpaug.flow.Sequential(
  [self.ai_aug_bert, self.ai_aug_glove])

Pluto 将四个摘要输入流方法,如下所示:

# Alice in Wonderland
pluto.print_aug_ai_sequential(pluto.df_t5_carroll)
# Tale of Two Cities
pluto.print_aug_ai_sequential(pluto.df_t5_dickens)
# Moby Dick
pluto.print_aug_ai_sequential(pluto.df_t5_melville)
# This chapter
pluto.print_aug_ai_sequential(pluto.df_t5_self)

让我们来看一下结果。

《爱丽丝梦游仙境》的增强摘要输出如下:

图 6.25 – 总结到流方法,爱丽丝梦游仙境

图 6.25 – 总结到流方法,爱丽丝梦游仙境

《双城记》的增强摘要输出如下:

图 6.26 – 总结到流方法,双城记

图 6.26 – 总结到流方法,双城记

《白鲸》的增强摘要输出如下:

图 6.27 – 总结到流方法,白鲸

图 6.27 – 总结到流方法,白鲸

本章的增强摘要输出如下:

图 6.28 – 总结到流方法,本章

图 6.28 – 总结到流方法,本章

Pluto 喜欢阅读增强后的摘要。有些聪明,有些夸张,但对于增强文本来说,它们足够了。

下一步是print_aug_ai_sometime()包装函数,位于 Python Notebook 中,但他认为在这一章解释结果不会带来更多的洞察。你可以在 Python Notebook 中运行这个包装函数并查看结果。

有趣的挑战

Pluto 挑战你重构Pluto 类,使其更快、更紧凑。你还应包含前几章的所有图片包装器和辅助函数。Pluto 鼓励你创建并上传你的库到GitHubPyPI.org。此外,你不必将类命名为PacktDataAug,但如果你引用或提到这本书,Pluto 和他的人类伙伴会露出灿烂的笑容。代码目标是为了易于理解、可重用的模式,以及在Python Notebook中的教学。因此,将代码重构为 Python 库会相对轻松且有趣。

总结到流技术是本章最后将介绍的方法。现在,让我们总结一下这一章。

摘要

使用机器学习(ML)进行文本增强是一项高级技术。我们使用了一个预训练的 ML 模型来创建额外的训练 NLP 数据。

在输入前三个段落后,T5 NLP ML 引擎为本章写出了前面的总结。它非常完美,体现了本章的精神。因此,Pluto 保留了这个总结不做更改。

此外,我们讨论了 14 种 NLP ML 模型和四种词语增强方法。它们分别是Word2VecBERTRoBERTa回译

Pluto 展示了 BERT 和 RoBERTa 能与人类写作相媲美。增强后的文本不仅仅是合适的,还富有启发性,例如将这是愚蠢的时代替换为死亡是爱的时代,或者将这是信仰的时代替换为这是青春的时代

对于回译方法,Pluto 使用 Facebook 或 Meta 的 AI NLP 模型将文本翻译成德语和俄语,然后再翻译回英语。

对于句子增强,Pluto 通过 T5 NLP ML 引擎精准总结了三本经典书籍的第一页,给大家留下了深刻印象。此外,他还开创了从总结到流的文本增强概念。Pluto 可能是第一个实现从总结到流策略的人。

在本章中,有许多有趣的事实有趣的挑战。Pluto 希望你能充分利用这些内容,拓展你的经验,超越本章的范围。

下一章将讨论音频增强,这将带来不同的挑战,但 Pluto 已经准备好应对它们。

第四部分:音频数据增强

本部分包括以下章节:

  • 第七章音频数据增强

  • 第八章使用谱图进行音频数据增强

第七章:音频数据增强

与图像和文本增强类似,音频数据增强的目标是扩展数据集,从而在生成 AI 系统中获得更高的准确预测或预测。音频增强具有成本效益,并且当获取额外音频文件既昂贵又耗时时,是一个可行的选择。

关于音频增强方法的写作面临独特的挑战。首先,音频不像图像或文本那样具有视觉特性。如果格式是有声书、网页或移动应用,我们播放声音,但介质是纸张。因此,我们必须将音频信号转换为可视化的表示形式。波形图,也称为时间序列图,是表示音频信号的标准方法。你可以在附带的 Python 笔记本中聆听音频。

在本章中,你将学习如何编写 Python 代码从零开始读取音频文件并绘制波形图。Pluto 在这里提供了一个预览,以便我们可以讨论波形图的各个组成部分。功能如下:

# sneak peek at a waveform plot
pluto.draw_audio(pluto.df_audio_control_data)

以下是 D 大调钢琴音阶的波形图:

图 7.1 – D 大调钢琴音阶

图 7.1 – D 大调钢琴音阶

图 7.1中,Pluto 将波形图中的正振幅用蓝色表示,负振幅用黄色表示。这使得图表更易于阅读,也更加美观。振幅Y轴的值。它衡量空气分子振动或压缩与膨胀的程度。振幅越大,空气位移越大。换句话说,零振幅值代表静音,离零点越远的绝对值代表声音越响亮。

频率,也称为采样率,是X轴的值。采样率衡量的是每秒钟记录的振幅值次数。声音频率或采样率的单位是赫兹Hz)。例如,1,000 Hz 或 1 千赫kHz)的采样率意味着你在 1 秒钟内记录了 1,000 个振幅值。换句话说,你每毫秒记录一个振幅值。因此,频率越高,声音越精确,声音文件的大小也越大。这是因为记录了更多的振幅值。1 kHz 等于 1,000 Hz。

趣味事实

人类的听力范围是 20 Hz 到 20 kHz。年幼的孩子能够听到超过 20 kHz 的声音,而年长的成年人则无法听到超过 17 kHz 的声音。深沉的低音乐音频在 20 Hz 到 120 Hz 之间,而日常人类语言的频率范围是 600 Hz 到 5 kHz。与此相对,犬类的听力频率大约是 40 Hz 到 60 kHz,优于人类的听力频率。这就是为什么你无法听到超过 20 kHz 的狗哨声的原因。

音高频率相同,但从人类的角度来看。它指的是声音的响亮程度,单位是分贝dB)。因此,高音高频率。

分贝(dB)是响度的单位。火箭声约为 165 dB,繁忙交通的噪音约为 85 dB,人类语音约为 65 dB,雨声约为 45 dB,零分贝表示静音。

MP3 和其他音频格式的标准采样率为 22.05 kHz。高质量声音的频率,也被称为光盘CD)音频的频率为 44.1 kHz。

在计算机上存储音频文件时,比特深度表示振幅值的准确性。16 位有 65,536 个细节级别,而24 位有 16,777,216 个信息级别。比特深度越高,数字录音越接*模拟声音,同时音频文件的大小也会更大。

比特率类似于采样率,比特率衡量的是每秒传输的比特数。在音频处理过程中,播放功能使用比特率,而录制功能使用采样率。

单声道音频只有一个通道(1 通道),而立体声音频有两个通道(2 通道)。立体声音频为右耳提供一个通道,为左耳提供另一个通道。

图 7.1中的底部图显示了一个放大的波形图。它只显示 100 个采样率点,从顶部波形图的中点开始。仔细观察,波形是一个简单的时间序列图。许多数据类型,如文本和图像,都可以表示为时间序列图,因为 Python 可以将数据表示为一维数组,而不考虑数据类型。

趣味小知识

音高修正是指在录音中调整人声表现,使得歌手能够准确地唱出音符。你可以使用Antares Auto-Tune ProWaves Tune Real Time等软件来修正歌声的高低音。它可以节省重新录音的时间和成本。在 1977 年之前,音高修正相对较少见,而在Antares Audio Technology发布Auto-Tune 音高修正插件后,音高修正得到了广泛应用。如今,大约 90%的广播、电视、网站或应用中的歌曲都使用了音高修正。自动调音用于声效,而音高修正则用于修正歌声。

由于大多数数据可以用于波形图,Pluto 可以为短语“玛丽有只小羊羔,它的羊毛像雪一样白。玛丽走到哪里,小羊就跟到哪里”绘制时间序列图。Pluto 使用以下函数:

# fun use of waveform graph
pluto.draw_time_series_text(pluto.text_marry_lamb)

输出如下:

图 7.2 – 文本作为时间序列图

图 7.2 – 文本作为时间序列图

图 7.2中,蓝色表示字母数字字符,黄色表示标点符号。Y轴表示字符的 ASCII 值。

转换过程是直接的,因为每个字母都被编码为ASCII值,例如“A”是 65,“B”是 66,依此类推。同样,一个由三维数组(宽度、高度和深度)组成的图像也有 RGB 值。通过乘以 RGB 值来压缩深度维度的结果介于零和 16,581,375 之间。将剩余的二维数组展*成一维数组,并将其绘制为时间序列图。

本章将介绍使用波形变换进行音频增强,特别是以下主题:

  • 标准音频增强技术

  • 滤波器

  • 音频增强库

  • 现实世界的音频数据集

  • 强化你的学习

让我们先讨论一些常见的音频增强方法。

标准音频增强技术

类似于第三章中的图像增强,许多音频库提供了比增强所需的更多功能。因此,我们只会介绍所选音频库中一些可用的方法。

在图像增强中,安全水*的定义是指不改变或扭曲原始图像超过可接受的水*。对于将原始音频信号扭曲到超出允许范围的情况,并没有标准的术语。因此,安全真实这两个词将交替使用,表示音频信号的极限点。

有趣的挑战

这里有一个思想实验:所有音频文件都以时间序列格式表示数字。那么,你能创建一个不考虑人类听觉感知的统计有效的增强方法吗?换句话说,使用数学操作统计有效的数字数组,但从不听取前后效果。毕竟,音频增强的目的是为了提供更多数据,以增强 AI 预测,而 AI 并不能理解人类的言语或区分好音乐和坏音乐。

以下是音频增强中常用的功能:

  • 时间拉伸

  • 时间位移

  • 音高缩放

  • 噪声注入

  • 极性反转

我们从时间拉伸开始。

时间拉伸

时间拉伸是指延长或缩短音频信号的持续时间,而不改变音高。例如,在人类的语言中,你会放慢语速,拖长词语,或者加快语速,像松鼠卡通角色一样说话。

时间拉伸安全水*是多少?这取决于音频类型和 AI 预测的目标。一般来说,你可以加速或减慢人类的言语,并且仍然能听懂。但如果目标是预测说话者的名字,那么你可以对语音应用小范围的时间拉伸,同时保持真实的说话风格。

另一方面,音乐通常被认为对时间拉伸是不安全的。改变音乐片段的节奏会改变音乐,超出真正音乐家的意图。

环境或自然声音通常在可接受的安全范围内对时间拉伸是安全的。

本增强技术,以及所有其他方法,都在 Python Notebook 中讲解;因此,通过听原始音频和增强后的音频,可以更容易理解效果。

类似于时间拉伸的是时间移位。

时间移位

时间移位是指将音频片段向前或向后移动。例如,如果你想在演讲者的宣布和观众的掌声之间制造更戏剧性的暂停,你可以将掌声向前移几秒钟。

带翻转的时间移位意味着最后的声音将被添加到开头。如果没有翻转,根据你是向前移位还是向后移位,音频的开头或结尾将会有静音。

例如,假设 AI 预测的目标是识别城市中的枪声并报警。那么,带翻转的时间移位是一种可接受的安全增强技术。另一个良好的使用带翻转时间移位的例子是循环的背景音乐。

人类语音或音乐通常对于时间移位来说是不安全的,因为顺序对保持音频的真实性至关重要。

离开时间后,音高移位或音高缩放是另一个增强参数。

音高移位

音高移位音高缩放是在不改变速度或时间移位的情况下改变声音的频率。例如,男性的声音音高低于女性。增加声音记录中的音高水*可能会使男性听起来像女性。

在增强人类语音、音乐、环境和自然音频文件时,音高移位应谨慎使用。对于相同的数据集,安全级别可能会根据 AI 预测目标的不同而大幅变化。

例如,记录日常草地的声音可以用来统计每天有多少只鸟访问草地,或者 AI 可以预测哪些种类的鸟类栖息在该领域。用于计算鸟类数量的音高移位安全范围比用于识别鸟类的范围要高。将音高移位应用于鸟鸣声可能会无意中使一种鸟的叫声听起来像其他鸟的叫声。

另一种音高变化方法是极性反转。

极性反转

极性反转是指将幅度值从正数转为负数,反之亦然。从数学角度来看,它通过负值乘以幅度。从图形角度来看,它改变了蓝色并将其变为黄色,反之亦然,详见图 7.1

对大多数人来说,极性反转后的播放听起来与原始音频相同。当与相位意识模型一起使用时,它对机器学习最为有利。没有安全范围,因为它要么被使用,要么不被使用。

以下增强方法是向音频文件中添加噪声。

噪声注入

噪声注入向音频文件添加信号噪声。添加噪声的效果是增强后的声音看起来像是由爆裂声和噼啪声组成的。通常用于音频增强的五种噪声类型是背景噪声高斯噪声随机噪声信噪比SNR)和短暂 突发噪声

噪声或安全级别的高低取决于 AI 项目的目标和录音内容。有时,您可能需要聘请领域专家来达到安全级别。

许多其他技术可以归类为常用的音频增强技术,如剪辑、增益过渡、归一化、填充或反向处理,但我们接下来将讨论滤波器和掩蔽技术。

滤波器

音频滤波器有助于消除音频录音中的不必要干扰或噪声。其结果是改善人声、音乐、自然和环境录音的音调和播放效果。

音频滤波器通过增加增强放大一定范围的频率来改变频率。滤波器还可以减少删除切除衰减通过某个频率范围。例如,使用低通滤波器,可以去除城市中两人对话录音中的交通噪声。

特别地,我们将介绍以下滤波器:

  • 低通滤波器

  • 高通滤波器

  • 带通滤波器

  • 低架滤波器

  • 高架滤波器

  • 带阻滤波器

  • 峰值滤波器

让我们从低通滤波器开始。

低通滤波器

低通滤波器切除或删除低频声音,如交通噪声、机器发动机轰鸣声或大象叫声。

通常,最小截止频率为 150 Hz,最大截止频率为 7.5 kHz,最小滚降为 12 dB,最大滚降为 24 dB。

这里有个有趣的事实:大象的叫声低于 20 Hz,或进入次声波范围。接下来我们要讨论的滤波器是高通滤波器。

高通滤波器

与低通滤波器类似,高通滤波器切除高频声音,如口哨声、婴儿哭声、指甲刮擦声或钟声。

通常,最小和最大截止频率分别为 20 Hz 和 2.4 kHz,最小和最大滚降分别为 12 dB 和 24 dB。

有趣的事实:人类的口哨声音大约在 3 到 4 kHz 之间。我们还需要了解另一个滤波器:带通滤波器。

带通滤波器

带通滤波器将声波限制在一定范围的频率内。换句话说,它结合了低带和高带滤波器。例如,带通滤波器可以让您更清楚地听到巴黎户外餐厅中两人对话的录音。同样,它也可以用于在嘈杂的亚马逊丛林中隔离鸟鸣录音。

通常,最小和最大中心频率分别为 200 Hz 和 4 kHz,最小和最大带宽比例分别为 0.5 和 1.99,最小和最大滚降分别为 12 dB 和 24 dB。

现在,让我们从通滤波器转到架滤波器。

低架滤波器

架滤波也叫做架均衡。特别是,低架滤波器会提升或削减频谱低端的频率。例如,你可以使用低架滤波器来减少重金属歌曲中的低音。

通常,最小和最大中心频率分别为 50 Hz 和 4 kHz,最小和最大增益分别为-18 dB 到 18 dB。

下一个技术是高架滤波器。

高架滤波器

类似地,高架滤波器会增加或减少频谱高端的频率幅度。例如,你可以使用高架滤波器来使音乐录音更加明亮。

通常,最小和最大中心频率分别为 300 Hz 和 7.5 kHz,最小和最大增益分别为-18 dB 和 18 dB。

带阻滤波器是我们接下来要讲解的技术。

带阻滤波器

带阻滤波器也叫做带阻滤波器陷波滤波器。它删除位于两个截止点之间或在频率范围两侧的频率。此外,它在内部使用低通和高通滤波器。例如,带阻滤波器可以去除后院音乐会即兴演奏中的不需要的尖峰和噪音。

通常,最小和最大中心频率分别为 200 Hz 和 4 kHz,最小和最大带宽分数分别为 0.5 和 1.99,最小和最大滚降分别为 12 dB 和 24 dB。

峰值滤波器是本章将要讲解的最后一种音频增强技术。

峰值滤波器

峰值钟形滤波器与带阻滤波器相反。换句话说,它增强具有窄带和更高增益信号的架滤波器,或允许围绕中心频率进行增益或削减。

通常,最小和最大中心频率分别为 50 Hz 和 7.5 kHz,最小和最大增益分别为-24 dB 和 24 dB。

音频增强库中有很多方法。因此,下一步是为 Pluto 的包装函数选择一个或两个音频增强库。

音频增强库

有许多商业和开源的音频数据增强库。在本章中,我们将重点介绍GitHub上可用的开源库。有些库比其他库更强大,有些库专注于某一特定主题,例如人类语音。Pluto 将使用提供的库编写包装函数来进行繁重的计算,因此,你可以在项目中选择多个库。如果一个库是用CPU实现的,它可能不适合在机器学习训练周期中进行动态数据增强,因为它会减慢过程。因此,选择一个可以在GPU上运行的库。选择一个强大且易于实现的库,以便学习新的音频增强技术或将增强后的数据输出到本地或云端磁盘空间。

知名的开源音频增强库如下:

  • Librosa 是一个开源的 Python 库,用于音乐和音频分析。它在 2015 年发布,并长期以来一直是流行的选择。许多其他音频处理和增强库将 Librosa 的功能作为构建模块。它可以在 GitHub 上找到,网址为 github.com/librosa/librosa

  • Audiomentations 是一个专门用于音频数据增强的 Python 库。其主要优点是其鲁棒性和易于集成到项目中。它被许多 Kaggle 比赛的获胜者引用。它可以在 GitHub 上找到,网址为 github.com/iver56/audiomentations

  • Facebook 或 Meta 研究发布了 Augly,这是一个用于图像和音频增强的开源 Python 库。其目标是为实际项目提供特定的数据增强。它可以在 GitHub 上找到,网址为 github.com/facebookresearch/AugLy/tree/main/augly/audio

  • Keras 是一个用于音频和音乐信号预处理的 Python 库。它实现了频率转换和使用 GPU 预处理的数据增强。它可以在 GitHub 上找到,网址为 github.com/keunwoochoi/kapre

  • Nlpaug 是一个多功能的 Python 库,适用于语言和音频数据增强。第五章使用 Nlpaug 进行文本增强,但在本章中,我们将使用音频库。它可以在 GitHub 上找到,网址为 github.com/makcedward/nlpaug

  • Spotify 的音频智能实验室发布了 Pedalboard Python 库。其目标是为机器学习提供工作室级别的音频效果。它可以在 GitHub 上找到,网址为 github.com/spotify/pedalboard

  • Pydiogment 是一个旨在简化音频增强的 Python 库。它易于使用,但不如其他音频增强库强大。它可以在 GitHub 上找到,网址为 github.com/SuperKogito/pydiogment

  • Torch-augmentationsAudiomentations 库在 GPU 上的实现。它可以在 GitHub 上找到,网址为 github.com/asteroid-team/torch-audiomentations

趣味事实

Audiomentations 库的版本 0.28.0 包含 36 个增强函数,Librosa 库的版本 0.9.2 包含超过 400 个方法,Pydiogment 库的最新更新(2020 年 7 月)包含 14 个增强方法。

Pluto 将主要使用 AudiomentationsLibrosa 库来演示我们在 Python 代码中提到的概念。但首先,我们将下载 Pluto 并使用它从 Kaggle 网站下载真实世界的音频数据集。

真实世界的音频数据集

到现在为止,你应该已经熟悉如何从 Kaggle 网站下载 Pluto 和真实世界数据集。我们选择从 第二章 下载 Pluto,因为在 第三章第四章 中展示的图像增强功能,以及在 第五章第六章 中展示的文本增强技术,对于音频增强并没有太大帮助。

我们将使用的三个真实世界音频数据集如下:

  • 来自 Kaggle 的 Musical Emotions ClassificationMEC)真实世界音频数据集包含 2,126 首歌曲,分为 训练测试 文件夹。它们是器乐音乐,目标是预测 快乐悲伤 的音乐。每首歌曲大约 9 到 10 分钟,格式为 *.wav。该数据集于 2020 年发布,并对公众开放,许可证为 Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)creativecommons.org/licenses/by-sa/4.0/

  • 来自 Kaggle 的 Crowd Sourced Emotional Multimodal Actors DatasetCREMA-D)真实世界音频数据集包含 7,442 个来自 91 位演员的原始片段。这些演员中,48 位为 男性,43 位为 女性,年龄介于 20 至 74 岁之间,种族包括 非裔美国人亚洲人白人西班牙裔未指定。此外,语音片段表达了六种不同的情感,包括 愤怒恶心恐惧快乐中立悲伤。该数据集没有固定的目标,但你可以用它来预测年龄、性别、种族或情感。该数据集于 2019 年发布,并对公众开放,许可证为 Open Data Commons Attribution License (ODC-By) v1.0opendatacommons.org/licenses/by/1-0/index.html

  • 来自 Kaggle 的 urban_sound_8kUS8K)真实世界数据集包含来自城市环境的 8,732 个标注音频片段。每个片段长度为 2 到 4 秒,分类包括 空调、汽车喇叭、儿童玩耍、狗吠、钻孔、发动机怠速、枪声、电锯声、警笛声和街头音乐。该数据集于 2021 年发布并对公众开放,许可证为 CC0 1.0 Universal (CC0 1.0) Public Domain Dedicationcreativecommons.org/publicdomain/zero/1.0/

这三个音频数据集——音乐、人类语音和环境声音——代表了你每天听到的典型声音。

以下四个步骤在每一章中都是相同的。如果需要澄清,请回顾 第二章第三章。步骤如下:

  1. 获取 Python Notebook 和 Pluto。

  2. 下载真实世界的数据。

  3. 将数据加载到 pandas 中。

  4. 听并查看音频。

让我们从在 Python Notebook 中下载 Pluto 开始。

Python Notebook 和 Pluto

首先,将data_augmentation_with_python_chapter_7.ipynb文件加载到 Google Colab 或您选择的 Jupyter Notebook 或 JupyterLab 环境中。从此开始,代码片段将来自 Python Notebook,包含完整的函数。

下一步是克隆仓库。我们将重用来自第二章的代码。!git%run语句用于启动冥王星:

# clone the GitHub repo.
f='https://github.com/PacktPublishing/Data-Augmentation-with-Python'
!git clone {f}
# instantiate Pluto
%run 'Data-Augmentation-with-Python/pluto/pluto_chapter_2.py'

输出将如下所示或类似:

---------------------------- : ----------------------------
            Hello from class : <class '__main__.PacktDataAug'> Class: PacktDataAug
                   Code name : Pluto
                   Author is : Duc Haba
---------------------------- : ----------------------------

我们需要再做一次检查,以确保冥王星已正确加载。以下命令会要求冥王星报告其状态:

# How are you doing Pluto?
pluto.say_sys_info()

输出将如下所示或类似,具体取决于您的系统:

---------------------------- : ----------------------------
                 System time : 2022/12/30 19:17
                    Platform : linux
     Pluto Version (Chapter) : 2.0
             Python (3.7.10) : actual: 3.8.16 (default, Dec  7 2022, 01:12:13) [GCC 7.5.0]
            PyTorch (1.11.0) : actual: 1.13.0+cu116
              Pandas (1.3.5) : actual: 1.3.5
                 PIL (9.0.0) : actual: 7.1.2
          Matplotlib (3.2.2) : actual: 3.2.2
                   CPU count : 2
                  CPU speed : NOT available
---------------------------- : ----------------------------

接下来,冥王星将下载音频数据集。

现实世界数据与 pandas

冥王星已通过fetch_kaggle_dataset(url)函数从第二章下载了现实世界的音乐数据集 MEC。他发现数据集由逗号分隔的变量(CSV)头文件组成。因此,他使用fetch_df(fname)函数将其导入到 pandas 中:

# download from Kaggle
url = 'https://www.kaggle.com/datasets/kingofarmy/musical-emotions-classification'
pluto.fetch_kaggle_dataset(url)
# import to Pandas
f = 'kaggle/musical-emotions-classification/Train.csv'
pluto.df_music_data = pluto.fetch_df(f)
# out a few header record
Pluto.df_music_data.head(3)

结果如下:

图 7.3 – 音乐(MEC)前三条记录

图 7.3 – 音乐(MEC)前三条记录

_append_music_full_path()fetch_music_full_path()辅助函数。关键代码行如下:

# helper function snippet
y = re.findall('([a-zA-Z ]*)\d*.*', x)[0]
return (f'kaggle/musical-emotions-classification/Audio_Files/Audio_Files/Train/{y}/{x}')
# main function snippet
df['fname'] = df.ImageID.apply(self._append_music_full_path)

函数的代码可以在 Python Notebook 中找到。结果如下:

图 7.4 – 音乐(MEC)前三条记录修订版

图 7.4 – 音乐(MEC)前三条记录修订版

来自 Kaggle 的下一个现实世界数据集是人类语音(CREMA-D)。冥王星必须使用以下命令下载并将其导入到 pandas 中:

# download the dataset
url = 'https://www.kaggle.com/datasets/ejlok1/cremad'
pluto.fetch_kaggle_dataset(url)
# import to Pandas and print out header record
f = 'kaggle/cremad/AudioWAV'
pluto.df_voice_data = pluto.make_dir_dataframe(f)
pluto.df_voice_data.head(3)

输出如下:

图 7.5 – 声音(CREMA-D)前三条记录修订版

图 7.5 – 声音(CREMA-D)前三条记录修订版

来自 Kaggle 的第三个音频数据集是城市声音(US8K)。顺便提一下,截至 2022 年 12 月,Kaggle 包含大约 1,114 个现实世界的音频数据集。冥王星必须下载并使用以下命令将其导入到 pandas 中:

# download dataset from Kaggle website
url='https://www.kaggle.com/datasets/rupakroy/urban-sound-8k'
pluto.fetch_kaggle_dataset(url)
# import to Pandas and print header records
f = 'kaggle/urban-sound-8k/UrbanSound8K/UrbanSound8K/audio'
pluto.df_sound_data = pluto.make_dir_dataframe(f)
pluto.df_sound_data.head(3)

输出如下:

图 7.6 – 城市声音(US8K)前三条记录修订版

图 7.6 – 城市声音(US8K)前三条记录修订版

最后,在pluto_data目录中,他将控制剪辑存储在pluto.audio_control_dmajor变量中。

有趣的挑战

冥王星挑战你搜索并下载一个额外的音频数据集,来自Kaggle网站或你的项目。如果你使用与你有关的数据工作,它将更具意义。只要你下载并将其导入到 pandas 中,所有的数据增强包装函数都会对你的音频文件起作用。提示:使用冥王星的fetch_kaggle_dataset()fetch_df()函数。

至此,冥王星已下载了三个现实世界的音频数据集。下一步是播放音频并查看音频波形图。

听取和查看

Pluto 写了三个新函数来播放音频并展示 _draw_area_with_neg() 辅助方法,该方法展示同一数据集中正负数的面积图。顺便提一下,Pandas 和 Matplotlib 面积图只能显示正值。该函数的核心代码行如下:

# draw area code snippet fill top/positive/blue section
pic.fill_between(
    i, xzero, ndata, where=(ndata >= xzero),
    interpolate=True, color=tcolor, alpha=alpha,
    label="Positive"
)
# fill bottom/negative/yellow section
pic.fill_between(
    i, xzero, ndata, where=(ndata < xzero),
    interpolate=True, color=bcolor, alpha=alpha,
    label="Negative"
)

完整的函数代码可以在 Python Notebook 中找到。下一个辅助函数是 _draw_audio()。它的主要目标是使用 Librosa 库加载或读取音频文件,绘制两个 Waveform 图表,并显示播放音频按钮。Pandas 使用与提取音频数据集时相同的文件名。该函数的关键代码行如下:

# code snippet, load/read and import to Pandas DataFrame
data_amp, sam_rate = librosa.load(samp.fname[0], mono=True)
# draw the Waveform graphs
self._draw_area_with_neg(data_amp,pic[0])
# draw the zoom in Waveform plot
self._draw_area_with_neg(data_amp[mid:end],pic[1])
# display the play-audio button
display(IPython.display.Audio(data_amp, rate=sam_rate))

该函数的完整内容可以在 Python Notebook 中找到。draw_audio() 方法调用了两个辅助函数。此外,它还从 Pandas DataFrame 中选择了一个随机音频文件。因此,Pluto 会反复执行命令,以便聆听并查看来自现实世界数据集的不同音频文件。

Pluto 可以使用以下命令展示来自 MEC 数据集的音乐片段:

# display the play button the waveform plot
pluto.draw_audio(pluto.df_music_data)

音频播放按钮如下:

图 7.7 – 音频播放按钮

图 7.7 – 音频播放按钮

Waveform 图表如下:

图 7.8 – 音乐波形图 (Happy36521)

图 7.8 – 音乐波形图 (Happy36521)

图 7.77.8 中的音频播放按钮 (Happy36521.wav) 将播放包含长笛、鼓和吉他的器乐音乐。

有趣的事实

Pluto 将该函数命名为 draw_audio() 而非 play_audio(),因为本书需要一个 Waveform 图表,并且要听音频,你必须进入 Python Notebook 并点击 图 7.7 中显示的播放按钮。像所有包装函数一样,你可以反复运行 draw_audio() 方法,查看并听取数据集中不同的音频文件。

Pluto 使用以下命令展示来自 CREMA-D 数据集的人类语音片段:

# display the play button the waveform plot
pluto.draw_audio(pluto.df_voice_data)

音频播放按钮的输出此处没有显示,因为它与 图 7.7 中的播放按钮相同。Waveform 图表的结果如下:

图 7.9 – 人类语音波形图 (1078_TIE_HAP_XX)

图 7.9 – 人类语音波形图 (1078_TIE_HAP_XX)

图 7.9 的音频 (1078_TIE_HAP_XX.wav) 是一位女性说出短语:这正是发生的事情。她听起来很开心,年龄中等。

Pluto 使用以下命令展示来自 US8K 数据集的城市声音片段:

# display the play button the waveform plot
pluto.draw_audio(pluto.df_sound_data)

Waveform 图表的结果如下:

图 7.10 – 城市声音波形图 (119455-5-0-7)

图 7.10 – 城市声音波形图 (119455-5-0-7)

图 7.10 的音频 (119455-5-0-7.wav) 是电锤的声音。

到这里,我们已经讨论了各种音频增强概念,选择了音频库,下载了 Pluto,并要求他获取音乐、人声和城市声音的真实世界数据集。现在,Pluto 也会播放音频并显示每个文件的波形图。

下一步是从头开始编写 Python 包装代码,以更深入地理解我们所涵盖的音频增强技术。

强化你的学习

_audio_transform()辅助函数的主要目标是选择一个随机剪辑,使用 Audiomentations 库函数进行增强,使用_fetch_audio_data()_draw_audio()辅助函数显示波形图,并显示音频播放按钮。关键代码如下:

# code snippet, use Pandas to select a random/sample record
p = df.sample(dsize)
# fetch the audio data
data_amp, sam_rate, fname = self._fetch_audio_data(lname)
# do the transformation
xaug = xtransform(data_amp, sample_rate=sam_rate)
# display the Waveform graphs and the audio play button
self._draw_audio(xaug, sam_rate, title + ' Augmented: ' + fname)
display(IPython.display.Audio(xaug, rate=sam_rate))

完整函数的代码可以在 Python 笔记本中找到。Pluto 将按之前讨论的顺序编写音频增强的 Python 包装函数,具体如下:

  • 时间位移

  • 时间拉伸

  • 音高缩放

  • 噪声注入

  • 极性反转

让我们从时间位移开始。

时间位移

play_aug_time_shift()函数的定义和关键代码如下:

# function definition
def play_aug_time_shift(self, df,
  min_fraction=-0.2,
  max_fraction=0.8,
  rollover=True,
  title='Time Shift'):
# code snippet for time shift
xtransform = audiomentations.Shift(
  min_fraction = min_fraction,
  max_fraction = max_fraction,
  rollover = rollover,
  p=1.0)

完整函数的代码可以在 Python 笔记本中找到。Pluto 测试了音频控制文件上的时间位移包装函数,如下所示:

# augment using time shift
pluto.play_aug_time_shift(
  pluto.audio_control_dmajor,
  min_fraction=0.2)

时间位移增强音频剪辑的输出如下:

图 7.11 – 时间位移(control-d-major.mp3)

图 7.11 – 时间位移(control-d-major.mp3)

包装函数显示了增强后的音频剪辑,图 7.11,以及原始音频剪辑,图 7.12,以便进行比较。有时,您需要查看底部的放大波形图来观察增强效果。听到增强效果的另一种方式是点击播放按钮,如图 7.13所示,听听在 Python 笔记本中播放前后的音频文件:

图 7.12 – 原始时间位移(control-d-major.mp3)

图 7.12 – 原始时间位移(control-d-major.mp3)

Pluto 通过点击 Python 笔记本中的音频播放按钮播放音频:

图 7.13 – 音频播放按钮,前后对比

图 7.13 – 音频播放按钮,前后对比

有趣的事实

每次运行包装函数命令时,您将看到并听到一个具有随机位移的新音频文件,位移范围在最小和最大值之间。它将从真实世界数据集中选择不同的音频文件。

图 7.11中的音频显示,D 大调的钢琴音阶几乎被移位至中点。因此,它从C#音阶向下到D,然后从D音阶向上到C#。因此,对于具有时间顺序依赖关系的音乐,时间位移技术并不是最佳选择。

接下来是三个数据集中的第一个,Pluto 使用默认参数在 MEC 数据集中的音乐剪辑上运行时间位移功能,如下所示:

# augment audio using time shift
pluto.play_aug_time_shift(
  pluto.df_music_data)

增强后的输出文件如下:

图 7.14 – 时间移位,音乐片段 (Sad17422.wav)

图 7.14 – 时间移位,音乐片段 (Sad17422.wav)

用于比较的原始文件输出如下:

图 7.15 – 时间移位的原始音乐片段 (Sad17422.wav)

图 7.15 – 时间移位的原始音乐片段 (Sad17422.wav)

在波形图中,很难看到 图 7.14图 7.15 之间的效果,但如果 Pluto 专注于较低的缩放图表,他可以看到它已经发生了偏移。当 Pluto 播放音频时,他无法察觉前后片段之间的任何区别。

图 7.14 中的音乐听起来像是一部西部电影的冒险电影乐队片段,在循环中重复播放,因此移位和循环回放效果完美。Pluto 反复运行包装函数以获取不同的音频文件,并确认没有不良影响。因此,使用默认参数对 MEC 数据集中的音乐进行时间移位是 安全 的。

转到第二个真实世界数据集,Pluto 知道在人类语音是时间序列依赖的 CREMA-D 数据集中。因此,0.5 让你可以看到有害的结果。命令如下:

# augment audio using time shift
pluto.play_aug_time_shift(pluto.df_voice_data,
  min_fraction=0.5)

增强后的时间移位音频片段输出如下:

图 7.16 – 时间移位语音片段 (1027_IEO_DIS_HI.wav)

图 7.16 – 时间移位语音片段 (1027_IEO_DIS_HI.wav)

包装函数还显示了原始音频片段以便比较:

图 7.17 – 原始时间移位语音片段 (1027_IEO_DIS_HI.wav)

图 7.17 – 原始时间移位语音片段 (1027_IEO_DIS_HI.wav)

图 7.16 的音频中,一位男士的声音说:“十一点 [停顿] 是的”,而在 图 7.17 的音频中,他说:“是十一点”。再次证明,时间移位技术对人类语音 (CREMA-D) 数据集并不是一个安全的选项。

在第三个数据集中,Pluto 重复运行以下命令来处理来自 US8K 数据库的城市声音:

# augment audio using time shift
pluto.play_aug_time_shift(pluto.df_sound_data,
  min_fraction=0.5)

增强后的时间移位音频片段输出如下:

图 7.18 – 时间移位城市声音 (135526-6-3-0.wav)

图 7.18 – 时间移位城市声音 (135526-6-3-0.wav)

包装函数还显示了原始音频片段以便比较:

图 7.19 – 原始时间移位城市声音 (135526-6-3-0.wav)

图 7.19 – 原始时间移位城市声音 (135526-6-3-0.wav)

图 7.17图 7.18 是带有高水*城市噪音的枪声音频。时间移位使枪声稍微延后。经过多次运行命令后,Pluto 发现时间移位的 最小分数 0.5 对于 US8K 真实世界数据集是可以接受的。

接下来我们要介绍的音频增强技术是时间拉伸。

时间拉伸

play_aug_time_stretch() 函数的定义和关键代码行如下:

# function definition
def play_aug_time_stretch(self, df,
  min_rate=0.2,
  max_rate=6.8,
  leave_length_unchanged=True,
  title='Time Stretch'):
# code snippet for time stretch
xtransform = audiomentations.TimeStretch(
  min_rate = min_rate,
  max_rate = max_rate,
  leave_length_unchanged = leave_length_unchanged,
  p=1.0)

填充函数的代码可以在 Python Notebook 中找到。Pluto 使用音频控制文件和 5.4 来测试时间拉伸包装函数,如下所示:

# augment using time stretch
pluto.play_aug_time_stretch(pluto.audio_control_dmajor,
  max_rate=5.4)

时间拉伸增强音频片段的输出如下:

图 7.20 – 时间拉伸 (control-d-major.mp3)

图 7.20 – 时间拉伸 (control-d-major.mp3)

包装函数还会显示原始音频片段以供对比:

图 7.21 – 原始时间拉伸 (control-d-major.mp3)

图 7.21 – 原始时间拉伸 (control-d-major.mp3)

Pluto 多次运行包装函数,每次都能辨认出音频的音调。图 7.20 中的音频播放了 D 大调片段,大约是原速的三倍,但音调仍然可以辨认出来。

包装函数在控制音频文件上运行良好,因此 Pluto 对音乐(MEC)数据集应用 3.0,如下所示:

# augment using tim stretch
pluto.play_aug_time_stretch(pluto.df_music_data,
  max_rate=3.0)

时间拉伸增强音频片段的输出如下:

 图 7.22 – 时间拉伸音乐 (Sad44404.wav)

图 7.22 – 时间拉伸音乐 (Sad44404.wav)

包装函数还会显示原始音频片段以供对比:

图 7.23 – 原始时间拉伸音乐 (Sad44404.wav)

图 7.23 – 原始时间拉伸音乐 (Sad44404.wav)

图 7.22图 7.23 中的音频是一个下午花园午餐的声音,伴随着强烈的主奏吉他和电影交响乐片段。在 3.0 的时间拉伸滤镜下,图 7.22 中的音频播放速度稍微加快,但 Pluto 没有注意到音乐情绪的下降。Pluto 多次在 MEC 数据集上运行包装函数,并得出结论,时间拉伸技术的安全范围是 3.0

有趣的挑战

为所有类型的音乐(MEC)找到一个通用的 安全 范围。你可以使用 Python Notebook 来找到 MEC 数据集的安全范围,并从 Kaggle 网站下载其他音乐数据集。另一方面,这是否是一个不可能完成的任务?对于流行音乐、古典音乐、民间音乐、乡村音乐和嘻哈音乐,是否存在一个通用的安全范围?

Pluto 对人声(CREMA-D)数据集进行了相同的处理。命令如下:

# augment using time stretch
pluto.play_aug_time_stretch(pluto.df_voice_data,
  max_rate=3.5)

时间拉伸增强音频片段的输出如下:

图 7.24 – 时间拉伸语音片段 (1073_WSI_SAD_XX.wav)

图 7.24 – 时间拉伸语音片段 (1073_WSI_SAD_XX.wav)

包装函数还会显示原始音频片段以供对比:

图 7.25 – 原始时间拉伸语音片段 (1073_WSI_SAD_XX.wav)

图 7.25 – 原始时间拉伸语音片段 (1073_WSI_SAD_XX.wav)

图 7.247.25 中的音频是一个女人的声音说:“我们休息几分钟”,而 图 7.24 中的音频稍微快一些,但仍然可以辨认出来。Pluto 多次在 CREMA-D 数据集上运行包装函数,使用 3.5,并且没有发现录音质量下降。因此,他得出结论,CREMA-D 数据集的安全范围是 3.5

Pluto 对城市声音(US8K)数据集也做了同样的操作。命令如下:

# augment using time stretch
pluto.play_aug_time_stretch(pluto.df_sound_data,
  max_rate=2.4)

时间拉伸增强音频片段的输出如下:

图 7.26 – 时间拉伸城市声音(76266-2-0-50.wav)

图 7.26 – 时间拉伸城市声音(76266-2-0-50.wav)

包装函数还会显示原始音频片段以供比较:

图 7.27 – 原始时间拉伸城市声音(76266-2-0-50.wav)

图 7.27 – 原始时间拉伸城市声音(76266-2-0-50.wav)

图 7.26图 7.27 中的音频是城市声音,录音中包含成人和儿童在操场上说话的声音,以及高强度交通或风声。图 7.26 中的音频播放略快。Pluto 在 US8K 数据集上反复运行包装函数,并使用了2.4,他得出结论,US8K 数据集对时间拉伸技术是安全的。

接下来,我们将介绍的技术是音高缩放

音高缩放

play_aug_pitch_scaling()函数的定义和关键代码行如下:

# function definition
def play_aug_pitch_scaling(self, df,
  min_semitones = -6.0,
  max_semitones = 6.0,
  title='Pitch Scaling'):
# code snippet for pitch shift
xtransform = audiomentations.PitchShift(
  min_semitones = min_semitones,
  max_semitones = max_semitones,
  p=1.0)

Pluto 使用默认参数测试音高缩放包装函数,音频控制文件如下所示:

# augment using pitch scaling
pluto.play_aug_pitch_scaling(pluto.audio_control_dmajor)

输出的增强音频片段如下:

图 7.28 – 音高缩放(control-d-major.mp3)

图 7.28 – 音高缩放(control-d-major.mp3)

包装函数还会显示原始音频片段以供比较:

图 7.29 – 原始音高缩放(control-d-major.mp3)

图 7.29 – 原始音高缩放(control-d-major.mp3)

Pluto 无法从图 7.28图 7.29中的完整波形图中看出区别,但如果他聚焦于放大的图表,就可以看到差异。听音频文件是最好的方法。为此,你必须进入 Python 笔记本并点击音频播放按钮。图 7.28中的音频听起来更像是大键琴,而不是原始的大调钢琴音阶。

接下来,Pluto 将音高缩放包装函数应用于音乐(MEC)数据集,如下所示:

# augment using pitch scaling
pluto.play_aug_pitch_scaling(pluto.df_music_data,
  min_semitones=-11.0,
  max_semitones=-9.0)

增强音频片段的输出如下:

图 7.30 – 音高缩放音乐(Sad11601.wav)

图 7.30 – 音高缩放音乐(Sad11601.wav)

包装函数还会显示原始音频片段以供比较:

图 7.31 – 原始音高缩放音乐(Sad11601.wav)

图 7.31 – 原始音高缩放音乐(Sad11601.wav)

图 7.30 中的音频播放较为温暖,旋律感强,突出了戏剧性电影片段的情绪变化。就像是戏剧性转折前的宁静黄昏。Pluto 通过设置-11.0-9.0,故意夸大了音高效果。图 7.31 中的音频播放的是原始片段。使用默认参数,Pluto 发现 MEC 数据集的音高缩放效果极小。因此,这是一种安全的技术。

使用默认参数值,Pluto 对语音 (CREMA-D) 数据集执行相同操作。命令如下:

# augment using pitch scaling
pluto.play_aug_pitch_scaling(pluto.df_voice_data)

增强音频片段的输出如下:

图 7.32 – 音高缩放语音 (1031_IEO_ANG_LO.wav)

图 7.32 – 音高缩放语音 (1031_IEO_ANG_LO.wav)

包装函数还会显示原始音频片段以供比较:

图 7.33 - 原始音高缩放语音 (1031_IEO_ANG_LO.wav)

图 7.33 - 原始音高缩放语音 (1031_IEO_ANG_LO.wav)

Pluto 比较了 图 7.327.33 中的放大图,以查看效果。在听这些音频文件时,他听到了增强版,从 图 7.32 中的一个高音调孩子的声音说:“现在是十一点。” 原版是一个成年男子的声音。经过反复运行包装命令,并将安全的 最小和最大半音 设置为 -2.4 和 2.4,Pluto 发现这对 CREMA-D 数据集的效果最小化。

城市声音 (US8K) 数据集具有多样化的频率范围。机器噪声是重复的低频声音,而警笛是高频声音。除非他限制了 4.014.0,否则 Pluto 找不到安全范围。命令如下:

# augment using pitch scaling
pluto.play_aug_pitch_scaling(pluto.df_sound_data,
  min_semitones=4.0,
  max_semitones=11.0)

增强音频片段的输出如下:

图 7.34 – 音高缩放城市声音 (93567-8-3-0.wav)

图 7.34 – 音高缩放城市声音 (93567-8-3-0.wav)

包装函数还会显示原始音频片段以供比较:

图 7.35 – 原始音高缩放城市声音 (93567-8-3-0.wav)

图 7.35 – 原始音高缩放城市声音 (93567-8-3-0.wav)

图 7.347.35 中的音频播放的是繁忙城市街道上警笛的城市片段。图 7.34 中的音频警笛声音更清晰,交通噪声干扰稍少。

有趣的挑战

这个挑战是一个思维实验。你能为哪些音频增强方法适用于特定的音频类别(例如人声、音乐、鸟鸣等)定义规则吗?例如,能否安全地使用小范围音高变化来增强人声?

我们接下来要看的技术是 噪声注入

噪声注入

play_aug_noise_injection() 函数的定义和关键代码行如下:

# function definition
def play_aug_noise_injection(self, df,
  min_amplitude = 0.002,
  max_amplitude = 0.2,
  title='Gaussian noise injection'):
# code snippet for noise injection
xtransform = audiomentations.AddGaussianNoise(
  min_amplitude = min_amplitude,
  max_amplitude = max_amplitude,
  p=1.0)

完整的函数代码可以在 Python Notebook 中找到。Pluto 在这里不会解释结果,因为它们与之前三种音频增强技术相似。你应该在 Python Notebook 中尝试它们,查看和听取结果。

对于 背景噪声注入 方法,代码片段如下:

# code snippet for adding background noise
xtransform = audiomentations.AddBackgroundNoise(
  sounds_path="~/background_sound_files",
  min_snr_in_db=3.0,
  max_snr_in_db=30.0,
  noise_transform=PolarityInversion(),
  p=1.0)

对于 短噪声注入 方法,代码片段如下:

# code snippet for adding short noise
xtransform = audiomentations.AddShortNoises(
  sounds_path="~/background_sound_files",
  min_snr_in_db=3.0,
  max_snr_in_db=30.0,
  noise_rms="relative_to_whole_input",
  min_time_between_sounds=2.0,
  max_time_between_sounds=8.0,
  noise_transform=audiomentations.PolarityInversion(),
  p=1.0)

完整的函数代码可以在 Python Notebook 中找到。接下来我们要看的技术是 极性反转

极性反转

play_aug_polar_inverse() 函数的定义和关键代码行如下:

# function definition
def play_aug_polar_inverse(self, df,
  title='Polarity inversion'):
# code snippet for polarity inversion
xtransform = audiomentations.PolarityInversion(
  p=1.0)

再次说明,Pluto 在这里不会解释结果,因为它们与之前看到的输出类似。你可以在 Python Notebook 中尝试它们,查看和听取结果。Pluto 已经为你编写了 Python 代码。

有趣的事实

有一个关于极性反转技术的有趣事实:你不会听出增强录音和原始录音之间的任何差异。你甚至在波形图中也看不出差别,但你可以在放大图表中看到。蓝色/正和黄色/负被翻转了。

例如,Pluto 将包装函数应用于语音(CREMA-D)数据集,如下所示:

# augment using polar inverse
pluto.play_aug_polar_inverse(pluto.df_voice_data)

增强音频片段的输出如下:

图 7.36 – 极性反转语音(1081_WSI_HAP_XX.wav)

图 7.36 – 极性反转语音(1081_WSI_HAP_XX.wav)

包装函数还会显示原始音频片段以供比较:

图 7.37 – 原始极性反转语音(1081_WSI_HAP_XX.wav)

图 7.37 – 原始极性反转语音(1081_WSI_HAP_XX.wav)

另一个有趣的事实是,极性反转就像将振幅数组乘以负一,像这样:

# implement using numpy
xaug = numpy.array(data_amp) * -1

有趣的挑战

这里有一个思想实验:为什么极性反转不会影响声音?毕竟,这在数据上是一个剧烈的变化,如波形图所示。提示:考虑从压缩和膨胀引起的分子振动的技术复杂性,涉及绝对测量。

接下来我们将介绍一些使用滤波器的技巧。

低通滤波器

在 Pluto 深入解释滤波器的音频技巧之前,他只会部分展示本书中的所有滤波器。这是因为过程是重复的,通过在 Python Notebook 中运行代码,你能获得更多的洞察力。Pluto 将详细解释低通带通滤波器的代码和波形图;对于其他滤波器,他将解释代码,但不解释输出的波形图。

play_aug_low_pass_filter() 函数的定义和关键代码行如下:

# function definition
def play_aug_low_pass_filter(self, df,
  min_cutoff_freq=150, max_cutoff_freq=7500,
  min_rolloff=12, max_rolloff=24,
  title='Low pass filter'):
# code snippet for low pass filter
xtransform = audiomentations.LowPassFilter(
  min_cutoff_freq = min_cutoff_freq,
  max_cutoff_freq = max_cutoff_freq,
  min_rolloff = min_rolloff,
  max_rolloff = max_rolloff,
  p=1.0)

完整功能的代码可以在 Python Notebook 中找到。Pluto 使用默认参数,测试低通滤波器包装函数与音频控制文件,如下所示:

# augment using low pass filter
pluto.play_aug_low_pass_filter(pluto.audio_control_dmajor)

增强音频片段的输出如下:

图 7.38 – 低通滤波器控制(control-d-major.mp3)

图 7.38 – 低通滤波器控制(control-d-major.mp3)

包装函数还会显示原始音频片段以供比较:

图 7.39 – 原始低通滤波器控制(control-d-major.mp3)

图 7.39 – 原始低通滤波器控制(control-d-major.mp3)

Pluto 没有检测到 图 7.387.39 中的增强录音与原始录音之间的任何区别。初看 WaveForm 图,Pluto 没有看到任何差异,直到他检查了放大图。正值(蓝色)幅度略有减少,相反,负值(黄色)略有增加。换句话说,前后音频的绝对差异表现为幅度值略低。

接下来,Pluto 将低通滤波器包装函数应用于音乐 (MEC) 数据集,如下所示:

# augment using low pass filter
pluto.play_aug_low_pass_filter(pluto.df_music_data)

增强后的音频片段的输出如下:

图 7.40 – 低通滤波音乐 (Sad21828.wav)

图 7.40 – 低通滤波音乐 (Sad21828.wav)

包装函数还显示了原始音频片段以供比较:

图 7.41 – 原始低通滤波音乐 (Sad21828.wav)

图 7.41 – 原始低通滤波音乐 (Sad21828.wav)

图 7.407.41 中的音频是一段电影管弦乐音乐片段,伴随着强烈的鼓点。这可能是印第安纳·琼斯电影中,在巨石滚下山洞前的背景音乐。特别是 图 7.40 中显示的增强文件声音更为*滑,边缘已被修整。Pluto 反复使用默认参数设置运行包装函数处理 MEC 数据集,发现增强后的音频文件并未改变音乐的悲伤或快乐情感。因此,这是一个 安全的 技术。

对于语音 (CREMA-D) 数据集,Pluto 做了同样的处理:

# augment using low pass filter
pluto.play_aug_low_pass_filter(pluto.df_voice_data)

增强后的音频片段的输出如下:

图 7.42 – 低通滤波语音 (1067_IEO_HAP_LO.wav)

图 7.42 – 低通滤波语音 (1067_IEO_HAP_LO.wav)

包装函数还显示了原始音频片段以供比较:

图 7.43 – 原始低通滤波语音 (1067_IEO_HAP_LO.wav)

图 7.43 – 原始低通滤波语音 (1067_IEO_HAP_LO.wav)

图 7.427.43 中的音频都说了 现在是十一点。此外,图 7.42 中的音频较少有啪嗒声和爆裂声。Pluto 有一个不太科学的想法,即放大图显示了一个更*滑的曲线,较少的波动和凹陷,这可能意味着增强录音中的声音更加清晰。在反复将包装函数应用于 CREMA-D 数据集之后,Pluto 认为低通滤波器是 安全的

三个真实世界数据集中的最后一个是城市声音 (US8K) 数据集。Pluto 通过以下方式应用包装函数:

# augment using low pass filter
pluto.play_aug_low_pass_filter(pluto.df_sound_data)

增强后的音频片段的输出如下:

图 7.44 – 低通滤波城市声音 (185373-9-0-6.wav)

图 7.44 – 低通滤波城市声音 (185373-9-0-6.wav)

包装函数还显示了原始音频片段以供比较:

图 7.45 – 原始低通滤波城市声音 (185373-9-0-6.wav)

图 7.45 – 原始低通滤波器城市声音(185373-9-0-6.wav)

图 7.44图 7.45 中的音频是带有交通和城市噪声的街头音乐。重复执行包装函数时,US8K 数据集的结果混合。Pluto 不知道哪些参数值是安全的,他需要咨询领域专家——即音响工程师。

我们接下来要了解的技巧是带通滤波器

带通滤波器

play_aug_band_pass_filter() 函数的定义及关键代码行如下:

# function definition
def play_aug_band_pass_filter(self, df,
  min_center_freq=200, max_center_freq=4000,
  min_bandwidth_fraction=0.5, max_bandwidth_fraction=1.99,
  min_rolloff=12, max_rolloff=24,
  title='Band pass filter'):
# code snippet for band pass filter
xtransform = audiomentations.BandPassFilter(
  min_center_freq = min_center_freq,
  max_center_freq = max_center_freq,
  min_bandwidth_fraction = min_bandwidth_fraction,
  max_bandwidth_fraction = max_bandwidth_fraction,
  min_rolloff = min_rolloff,
  max_rolloff = max_rolloff,
  p=1.0)

完整的函数代码可以在 Python Notebook 中找到。Pluto 使用默认参数测试带通滤波器包装函数与音频控制文件,命令如下:

# augment using band pass filter
pluto.play_aug_band_pass_filter(pluto.audio_control_dmajor)

增强音频片段的输出如下:

图 7.46 – 带通滤波器控制(control-d-major.mp3)

图 7.46 – 带通滤波器控制(control-d-major.mp3)

包装函数还会显示原始音频片段以供对比:

图 7.47 – 原始带通滤波器控制(control-d-major.mp3)

图 7.47 – 原始带通滤波器控制(control-d-major.mp3)

图 7.46中,Pluto 可以推测声音略有改变。听音频文件时,他确认音阶是一样的,但听起来有一种嗡嗡声。

接下来,Pluto 对音乐(MEC)数据集应用带通滤波器函数。命令如下:

# augment using band pass filter
pluto.play_aug_band_pass_filter(pluto.df_music_data)

增强音频片段的输出如下:

图 7.48 – 带通滤波器音乐(Happy15804.wav)

图 7.48 – 带通滤波器音乐(Happy15804.wav)

包装函数还会显示原始音频片段以供对比:

图 7.49 – 原始带通滤波器音乐(Happy15804.wav)

图 7.49 – 原始带通滤波器音乐(Happy15804.wav)

该音频片段的声音是一段快乐随意的电影音乐,并带有一丝鼓点。增强后的声音,显示在图 7.48中,显得更明亮、更紧凑,同时也更加*滑。Pluto 对MEC 数据集重复执行包装函数,它增强了更快乐的情绪音乐,并为更悲伤的片段注入了更有深度的音调。因此,它对 MEC 数据集是安全的。

Pluto 对语音(CREMA-D)数据集做了相同的处理。命令如下:

# augment using band pass filter
pluto.play_aug_band_pass_filter(pluto.df_voice_data)

增强音频片段的输出如下:

图 7.50 – 带通滤波器语音(1071_IWL_NEU_XX.wav)

图 7.50 – 带通滤波器语音(1071_IWL_NEU_XX.wav)

包装函数还会显示原始音频片段以供对比:

图 7.51 – 原始带通滤波器语音(1071_IWL_NEU_XX.wav)

图 7.51 – 原始带通滤波器语音(1071_IWL_NEU_XX.wav)

图 7.507.51 中的音频是一个女人说的,“我想要一个新的闹钟”。增强后的音频文件听起来更清晰,噪声干扰比原始片段少。对 CREMA-D 数据集中的大多数文件进行了相同的处理,得到了相似的结果。因此,CREMA-D 数据集对于带通滤波器技术是安全的

Pluto 怀疑对城市声音(US8K)数据集进行相同的改进,或者至少达到一个安全的水*。命令如下:

# augment using band pass filter
pluto.play_aug_band_pass_filter(pluto.df_sound_data)

增强后的音频片段输出如下:

图 7.52 – 带通滤波器城市声音 (95404-3-0-0.wav)

图 7.52 – 带通滤波器城市声音 (95404-3-0-0.wav)

这个包装函数还展示了原始音频片段以供比较:

图 7.53 – 原始带通滤波器城市声音 (95404-3-0-0.wav)

图 7.53 – 原始带通滤波器城市声音 (95404-3-0-0.wav)

这段音频文件是一个有风的后院,鸟儿在唱歌,远处有狗叫的声音。增强后的音频文件,图 7.52,听起来更为清晰,但带有隧道回声效果。Pluto 认为带通滤波器对 US8K 数据集是安全的

有趣的挑战

Pluto 挑战你实现反向音频技术。你能想到一个使用反向音频的应用场景吗?它是一个 play_aug_time_shift() 的包装函数。将 xtransform = audiomentations.Shift() 改为 xtransform = audiomentations.Reverse()

音频增强过程略显重复,但结果非常有趣。因此,Pluto 分享了以下音频滤波器技术的代码,但生成的波形图和音频播放按钮位于 Python 笔记本中。

接下来我们要介绍的滤波器是高通滤波器

高通和其他滤波器

play_aug_high_pass_filter() 函数的定义和关键代码行如下:

# function definition
def play_aug_high_pass_filter(self, df,
  min_cutoff_freq=20, max_cutoff_freq=2400,
  min_rolloff=12, max_rolloff=24,
  title='High pass filter'):
# code snippet for high pass filter
xtransform = audiomentations.HighPassFilter(
  min_cutoff_freq = min_cutoff_freq,
  max_cutoff_freq = max_cutoff_freq,
  min_rolloff = min_rolloff,
  max_rolloff = max_rolloff,
  p=1.0)

结果可以在 Python 笔记本中找到。

有趣的挑战

Pluto 挑战你实现 Audiomentations 库中的其他音频滤波器,如 audiomentations.HighPassFilteraudiomentations.LowShelfFilteraudiomentations.HighShelfFilteraudiomentations.BandStopFilteraudiomentations.PeakingFilter

至此,我们已经涵盖了音频增强的基本原理并实践了相关编码。接下来,我们将总结这一章的内容。

概要

正如我们一开始所看到的,音频增强是一个具有挑战性的主题,因为我们无法直接听到待处理的音频录音,但我们可以通过波形图和放大图来可视化技术的效果。然而,仍然没有什么能代替直接聆听增强前后音频录音。你可以访问包含完整代码和音频播放按钮的 Python 笔记本,以便播放增强后的音频和原始录音。

首先,我们讨论了音频文件的理论和概念。音频文件的三个基本组成部分是振幅频率采样率。频率的单位是赫兹Hz)和千赫kHz)。音高类似于频率,但测量单位是分贝dB)。类似地,比特率比特深度是表示采样率的其他形式。

接下来,我们解释了标准的音频增强技术。三个基本要素是时间拉伸时间偏移音高缩放。其他的包括噪声注入极性反转。增强库中还提供了更多方法,比如剪辑、增益、归一化和双曲正切tanh)失真。

在下载现实世界的音频数据集之前,我们讨论了八大开源音频增强库。有许多强大的音频增强库可供选择。Pluto 选择了Librosa库——毕竟,它是最成熟的。其次是Audiomentations库,因为它功能强大且易于与其他库集成。Facebook 的Augly库也很有竞争力,Pluto 在其他项目中也使用过它们。最终,因 Pluto 使用了包装函数的概念,他可以选择任何库或库的组合。

与图像和文本增强一样,Pluto 从Kaggle网站下载了三个现实世界的音频数据集。每个数据集代表日常经验中的一个音频类别:音乐、人声和城市声音。

在 Python Notebook 中编写代码帮助我们巩固对每种音频增强技术的理解。Pluto 会详细解释代码和输出结果。

输出非常棒,但编码过程看起来有些重复。这很简单,因为 Pluto 遵循了创建可重用类、添加新方法、从Kaggle网站下载现实世界数据、导入 pandas、利用一流的增强库并编写新的包装函数的既定模式。

在本章中,有很多有趣的事实有趣的挑战。Pluto 希望你能利用这些内容,扩展你在本章之外的经验。

在下章中,Pluto 将用频谱图揭开音频的神秘面纱。

第八章:使用频谱图进行音频数据增强

在上一章中,我们使用波形图可视化了声音。音频频谱图是另一种可视化音频成分的方法。频谱图的输入是一个一维的 幅度 值数组和 采样率。它们与波形图的输入相同。

音频 频谱图 有时也称为 声谱图声纹图声印图语音图。频谱图是比波形图更详细的声音表现方式。它展示了频率和幅度(响度)随时间变化的关系,有助于可视化信号中的频率成分。频谱图使得识别音乐元素、检测旋律模式、识别基于频率的效果、以及比较不同音量设置的结果变得更加容易。此外,频谱图在识别信号的非音乐方面也更为有用,例如噪声和其他频率的干扰。

典型的应用场景包括音乐、人类语音和声呐。其简短的标准定义是:时间持续下的频率映射谱。换句话说,y 轴表示频率(单位为 Hz 或 kHz),x 轴表示时间(单位为 秒或毫秒)。有时,图表会附带一个用于幅度等级的颜色索引。

Pluto 会在本章后面解释 Python Notebook 中的代码,但这里先简单展示一下音频频谱图。绘制 D 大调控制钢琴音阶 音频文件的命令如下:

# draw Spectrogram
pluto.draw_spectrogram(pluto.audio_control_dmajor)

输出如下:

图 8.1 – D 大调钢琴音阶的音频频谱图

图 8.1 – D 大调钢琴音阶的音频频谱图

在 Pluto 阐明音频频谱图之前,如果音频概念和关键词对你来说很陌生,应该先复习一下 第七章。本章内容很大程度上依赖于 第七章 中的知识和实践。

图 8.1 中,Pluto 使用 Matplotlib 库绘制音频频谱图。主要输入是幅度数组和采样率。该库执行所有复杂的计算,其他库,如 Librosa 或 SciPy 也能完成相同的任务。特别地,Matplotlib 能够从相同的输入生成多种类型的音频频谱图。Pluto 会在稍后深入探讨频谱图的类型,但首先,让我们分解一下该库是如何构建音频频谱图的。主要的五个步骤如下:

  1. 将音频流分割成重叠的片段,也称为 窗口

  2. 对每个窗口计算 短时傅里叶变换STFT)值。

  3. 将窗口的值转换为 分贝dB)。

  4. 将窗口链接在一起,形成原始音频序列。

  5. 在图表中展示结果,y 轴表示 Hz,x 轴表示秒,dB 为颜色编码值。

前面五个步骤的数学计算比较复杂,本章的目标是通过频谱图可视化声音并增广音频文件。因此,我们依赖音频库来执行数学计算。

如前所述,表示频谱图的底层数据与波形格式相同。因此,音频增广技术也是相同的。因此,生成的增广音频文件听起来是一样的。唯一的区别是频谱图和波形图的视觉表示。

本章的大部分内容将介绍音频频谱图标准格式、频谱图的变体梅尔频谱图色度STFT。增广技术部分较短,因为你在上一章已经学习了该方法。本章将涵盖以下主题:

  • 初始化与下载

  • 音频频谱图

  • 各种频谱图格式

  • 梅尔频谱图和色度 STFT 图

  • 频谱图增广

  • 频谱图图像

趣味事实

凯电气公司于 1951 年推出了首个商业化的音频频谱分析机器。该黑白图像被称为声谱仪或声谱图,用于可视化鸟鸣声。1966 年,圣马丁出版社使用声谱学为书籍 《北美鸟类黄金田野指南》 制作插图。到 1995 年,频谱图术语逐渐取代了声谱图术语,尤其是在数字时代。早期,频谱图或声谱图的应用并不限于鸟类研究。美国军方在 20 世纪 40 年代初期就使用频谱图进行加密,直到今天仍然如此,这一点可以通过 2019 年密码学历史中心出版的《密码学季刊》第 38 期得到证明。

本章将重用上一章中介绍的音频增广函数和真实世界的音频数据集(参见 第七章)。因此,我们将从初始化 Pluto 并下载真实世界数据集开始。

初始化与下载

从 Google Colab 或你选择的 Python Notebook 或 JupyterLab 环境加载 data_augmentation_with_python_chapter_8.ipynb 文件开始。从此时起,代码片段来自 Python Notebook,其中包含完整的函数。

以下初始化和下载步骤应该对你来说比较熟悉,因为我们已经做了六次。以下代码片段与 第七章中的代码相同:

# Clone GitHub repo.
url = 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
!git clone {url}
# Intialize Pluto from Chapter 7
pluto_file = 'Data-Augmentation-with-Python/pluto/pluto_chapter_7.py'
%run {pluto_file}
# Verify Pluto
pluto.say_sys_info()
# Fetch Musical emotions classification
url = 'https://www.kaggle.com/datasets/kingofarmy/musical-emotions-classification'
pluto.fetch_kaggle_dataset(url)
f = 'kaggle/musical-emotions-classification/Train.csv'
pluto.df_music_data = pluto.fetch_df(f)
# Fetch human speaking
url = 'https://www.kaggle.com/datasets/ejlok1/cremad'
pluto.fetch_kaggle_dataset(url)
f = 'kaggle/cremad/AudioWAV'
pluto.df_voice_data = pluto.make_dir_dataframe(f)
# Fetch urban sound
url='https://www.kaggle.com/datasets/rupakroy/urban-sound-8k'
pluto.fetch_kaggle_dataset(url)
f = 'kaggle/urban-sound-8k/UrbanSound8K/UrbanSound8K/audio'
pluto.df_sound_data = pluto.make_dir_dataframe(f)

趣味挑战

Pluto 挑战你从 Kaggle 网站或你的项目中搜索并下载额外的真实世界音频数据集。提示是使用 Pluto 的 fetch_kaggle_data()fetch_df() 方法,以及任何音频增广包装函数。

一些背后的方法使得这个过程变得非常简便。Pluto 强烈建议你在继续学习频谱图之前,先回顾一下 第七章

音频频谱图

在解析频谱图之前,让我们回顾一下频谱图与波形图的基本区别。频谱图显示了声音信号随时间变化的频率成分,重点是频率和强度。相比之下,波形图专注于声音的时序和振幅。它们的区别在于声音波形的可视化表示。底层的数据表示和转换方法是相同的。

音频频谱图是声音波形的另一种可视化表示,您在第七章中看到了波形图。_draw_spectrogram() 辅助方法使用 Librosa 库导入音频文件,并将其转换为幅度数据一维数组以及采样率(以赫兹为单位)。下一步是使用 Matplotlib 库绘制频谱图。同样,Pluto 从 Librosa 库函数获取输出,并使用 Matplotlib 函数绘制第七章中的漂亮蓝色和黄色波形图。相关代码片段如下:

# read audio file
data_amp, sam_rate = librosa.load(lname, mono=True)
# draw the spectrogram plot
spectrum, freq, ts, ax = pic.specgram(data_amp, Fs=sam_rate)

返回的值如下:

  • spectrumnumpy.array 类型,具有 shape(n,m)。例如,绘制 D 大调音频文件的控制钢琴音阶频谱图的结果 shape()(129, 1057)。它表示每个片段或窗口的周期图的 m 列。

  • freqnumpy.array 类型,具有 shape(n,)。以相同的例子为例,freq shape(129,)。它表示与 spectrum 数组中的元素(行)对应的频率。

  • tsnumpy.array 类型,具有 shape(n,)。以之前的例子为例,ts shape(1057,)。它表示与 spectrum 的 n 列中点对应的时间。

  • axmatplotlib.image.AxesImage 类型。它是来自 Matplotlib 库的图像。

Pluto 使用以下命令为 D 大调音频文件绘制控制钢琴音阶的频谱图:

# plot the Spectrogram
pluto.draw_spectrogram(pluto.audio_control_dmajor)

输出结果如下:

图 8.2 – 钢琴大调音阶的音频频谱图

图 8.2 – 钢琴大调音阶的音频频谱图

Pluto 在 Python 笔记本中显示音频播放按钮,您可以点击按钮听音频。按钮的图像如下所示:

图 8.3 – 音频播放按钮

图 8.3 – 音频播放按钮

为了进行比较,以下是来自第七章的波形图,使用了辅助函数:

# plot the Waveform
pluto._draw_audio(data_amp, sam_rate, 'Original: ' + fname)

输出结果如下:

图 8.4 – 钢琴大调音阶的音频波形

图 8.4 – 钢琴大调音阶的音频波形

音乐声音相同,只有视觉展示不同。

声音工程师训练阅读频谱图以识别和去除不需要的噪声,例如:

  • 嗡嗡声:通常是录音中的电噪声,其频率范围通常在 50 Hz 到 60 Hz 之间。

  • 嗡嗡声:这与低频的嗡嗡声相反。它是高频的电气噪声。常见的来源有荧光灯、摄像机麦克风和高频电机。

  • 嘶嘶声:这是一种宽带噪声,区别于嗡嗡声和嗡声。它通常集中在上下频谱的特定频率。常见的来源是供暖、通风和空调HVAC)系统或电动风扇。

  • 间歇性噪声:这些噪声通常是由城市环境中的声音引起的,例如雷声、鸟鸣、风声、警笛、汽车喇叭声、脚步声、敲击声、咳嗽声或手机铃声。

  • 数字削波:当音频太响,无法被录制时,就会发生数字削波。这是音频信号峰值的丧失。

  • 间隙:间隙或丢失是由于音频录制中的缺失切割部分导致的静音。

  • 点击声和爆裂声:这些是由黑胶唱片和其他有槽介质录音设备产生的噪声。

Pluto 使用Matplotlib库函数,该函数有许多参数控制频谱图的显示。我们将使用三个真实世界的音频数据集来展示频谱图的其他可视化表示。

各种频谱图格式

Pluto 可以将许多参数传递给 Matplotlib 库的底层specgram()方法。他将重点介绍其中的一些参数。

有趣的事实

你可以通过在 Python Notebook 中在函数后加上问号(?)来打印任何函数的文档。

例如,打印specgram()函数文档的命令如下:matplotlib.pyplot.specgram? 部分输出如下:

图 8.5 – specgram()的部分打印定义

图 8.5 – specgram()的部分打印定义

你可以在 Python Notebook 中查看图 8.5的完整输出。另一个示例是打印 Pluto 的draw_spectrogram()函数文档,命令如下:pluto.draw_spectrogram?

输出如下:

图 8.6 – draw_spectrogram()的打印定义

图 8.6 – draw_spectrogram()的打印定义

图 8.5可以看出,简单的方法是改变颜色映射(cmap)变量。Matplotlib 库中有超过 60 种颜色映射。因此,Pluto 将为每个音频数据集选择不同的cmap颜色。声音工程师可能使用不同的颜色映射来突出特定频率属性,以便识别模式或噪声。更改视觉表示不会影响声音质量或数据。因此,仅根据个人喜好选择颜色映射是可以接受的。如果你喜欢鲜艳的粉色和蓝色,可以选择cool cmap值。

音乐数据集的频谱图代码如下:

# plot the spectrogram in different color map
pluto.draw_spectrogram(pluto.df_music_data, cmap='plasma')

输出如下:

图 8.7 – 音乐文件的频谱图(Sad39910)

图 8.7 – 音乐文件的频谱图(Sad39910)

每次 Pluto 运行 draw_spectrogram() 包装函数时,都会从数据集中随机选择一个音频文件。图 8**.7 是具有强烈大提琴主奏的电影音乐音频,plasma 色图是一种从亮黄色过渡到橙色和深蓝紫色的色彩。

同样,对于人声数据集,命令如下:

# plot the Spectrogram in different color map
pluto.draw_spectrogram(pluto.df_voice_data, cmap='cool')

输出如下:

图 8.8 – 人声的频谱图 (1076_TAI_FEA_XX)

图 8.8 – 人声的频谱图 (1076_TAI_FEA_XX)

图 8**.8 是一位女性说“飞机几乎满了”的音频。cool 色图是从紫红色过渡到淡蓝色。

接下来,Pluto 使用以下命令对城市声音数据集执行相同操作:

# plot the Spectrogram with different color map
pluto.draw_spectrogram(pluto.df_sound_data, cmap='brg')

输出如下:

图 8.9 – 城市声音的频谱图 (24347-8-0-88)

图 8.9 – 城市声音的频谱图 (24347-8-0-88)

图 8**.9 听起来像是一辆救护车的警笛声。brg 色图是蓝色、红色和绿色,形成了一个引人注目且戏剧性的图形。

有趣的挑战

这个挑战是一个思维实验。对于不同类型的音频(如城市声音或音乐),使用具有多种颜色的色图(例如 rainbow cmap)还是使用两种颜色(如 ocean cmap)更有利?换句话说,用粉色和品红色阴影来显示人类演唱的音频片段,还是用多彩的地球色调更好?

在音频工程中,window_hanning 参数使用加权余弦函数来减少音频频谱的幅度。Hanning 窗口是一种用于减少音频信号频域伪影的技术。它使用 window 函数在信号的边缘附**滑地衰减信号的幅度,从而最小化频谱泄漏的影响,并减少信号中的不必要噪音。Hanning 窗口还提高了信号的时域分辨率,使得更容易精确地识别开始和结束的时刻。

Pluto 的 draw_spectrogram() 方法将其用作默认值。如果 Pluto 想查看没有 window_hanning 的原始信号怎么办?他可以在控制和语音数据集上使用 window_none,如下命令所示:

# control audio file
pluto.draw_spectrogram(pluto.audio_control_dmajor,
  window=matplotlib.mlab.window_none)
# Human speech
pluto.draw_spectrogram(pluto.df_voice_data,
  cmap='cool',
  window=matplotlib.mlab.window_none)

控制钢琴音阶(D 大调)音频文件的输出如下:

图 8.10 – 使用 window_none 的频谱图,钢琴音阶(控制-D-大调)

图 8.10 – 使用 window_none 的频谱图,钢琴音阶(控制-D-大调)

人声数据集的输出如下:

图 8.11 – 使用 window_none 的人声频谱图 (1058_IEO_ANG_LO)

图 8.11 – 使用 window_none 的人声频谱图 (1058_IEO_ANG_LO)

window 参数的其他值包括 numpy.blackmannumpy.bartlettscipy.signalscipy.signal.get_window图 8**.11 中的音频是一个女人说“现在是 11 点钟”。

有趣的挑战

这是一个思维实验。给定一个频谱图作为图像,你能否逆向工程并从图像中播放音频?提示是研究逆频谱图软件和理论。

Pluto 继续绘制各种频谱图和色彩图,因为音频工程师可能需要夸大或突出特定的频率或音频属性。此外,增强技术与上一章类似。因此,花更多时间扩展你对频谱图的理解是值得的。

Pluto 可以单独使用参数,也可以组合多个参数来产生不同的结果,例如在真实音乐数据集上使用 sides 参数,或将 sidesmode 参数组合在控制钢琴音阶数据上。命令如下:

# the control piano scale in D major
pluto.draw_spectrogram(pluto.df_music_data,
  cmap='plasma',
  sides='twosided')
# the music dataset
pluto.draw_spectrogram(pluto.audio_control_dmajor,
  window=matplotlib.mlab.window_none,
  sides='twosided',
  mode='angle')

sides等于twosided时,音乐的输出如下:

图 8.12 – 具有 twosided 的频谱图,音乐(Sad27307)

图 8.12 – 具有 twosided 的频谱图,音乐(Sad27307)

sides等于twosidedmode等于angle时,控制钢琴音阶音频的输出如下:

图 8.13 – 具有 twosided 和 angle 的频谱图,音乐(control-d-major)

图 8.13 – 具有 twosided 和 angle 的频谱图,音乐(control-d-major)

有趣的挑战

Pluto 在 Python 笔记本中有更多的参数组合。因此,最好修改或破解代码。体验不同的频谱图如何呈现不同的真实世界数据集将会很有趣。

接下来是 Mel 频谱图和 Chroma STFT 图。它们与频谱图类似。

Mel 频谱图和 Chroma STFT 图

Pluto 花更多时间绘制各种频谱图,因为增强技术与第七章中的波形图相同。Pluto 将编写更少的新包装函数。他将重用上一章的方法,但在此之前,让我们绘制更多频谱图。

音高的主观单位,也称为 Mel 音阶,是一种音高单位,音高之间的距离是相等的。S. S. Stevens、John Volkmann 和 E. B. Newmann 在 1937 年发表于名为《音高心理量度的音阶》的学术论文中提出了 Mel 音阶。

Mel 频率尺度的数学计算很复杂。因此,Pluto 依赖于 Librosa 库中的 melspectrogram() 方法来执行计算。Pluto 的 draw_melspectrogram() 包装方法使用 Librosa 的 melspectrogram() 函数,代码片段如下:

# code snippeet for the melspectrogram
mel = librosa.feature.melspectrogram(y=data_amp,
  sr=sam_rate,
  n_mels=128,
  fmax=8000)
mel_db = librosa.power_to_db(mel, ref=numpy.max)
self._draw_melspectrogram(mel_db, sam_rate, data_amp,
  cmap=cmap,
  fname=tname)

整个函数代码在 Python 笔记本中。Pluto 为控制钢琴音阶和人类语音数据集绘制了 Mel 频谱图,结果如下:

# Control piano scale
pluto.draw_melspectrogram(pluto.audio_control_dmajor)
# Music dataset
pluto.draw_melspectrogram(pluto.df_voice_data, cmap='cool')

控制钢琴音阶的 Mel 频谱图输出如下:

图 8.14 – Mel 频谱图,控制钢琴音阶(control-d-major)

图 8.14 – Mel-谱图控制钢琴音阶(control-d-major)

人类语音数据集的 Mel-谱图输出如下:

图 8.15 – Mel-谱图音乐(1016_MTI_FEA_XX)

图 8.15 – Mel-谱图音乐(1016_MTI_FEA_XX)

图 8**.15 的音频是一个男人说:“也许明天会很冷。” 每个 Mel-谱图在 Python Notebook 中都有一个音频播放按钮,你可以听到音频文件。

Chroma STFT 是信号的正弦频率和局部阶段内容随着时间变化的表现。Dennis Gabor 博士 在 1944 年的学术论文《通信理论》中首次提出 STFT,也被称为 Gabor 变换,并在 1945 年进行了修订。

Chroma STFT 是一种通过将音乐音频信号分解为其成分频率和振幅与时间的关系来分析音乐音频信号的方法。它用于表征所使用的乐器,并在短小的音乐片段中识别独特的特征。Chroma STFT 最常用于识别音乐信号的谱特征,从而能够对这些成分进行量化,并与同一乐曲的其他版本进行比较。

Pluto 在 draw_melspectrogram() 包装方法中稍作修改,以适应 Chroma STFT 图。新增的参数是 is_chroma,默认值为 False_draw_melspectrometer() 辅助函数没有变化。代码片段如下:

# code snippet for the chroma_stft
stft = librosa.feature.chroma_stft(data_amp,
  sr=sam_rate)
self._draw_melspectrogram(stft, sam_rate, data_amp,
  cmap=cmap,
  fname=tname,
  y_axis=yax,
  y_label=ylab)

整个函数代码位于 Python Notebook 中。Pluto 会为控制钢琴音阶、音乐和城市声音数据集绘制 Chroma STFT 图,如下所示:

# Control piano scale
pluto.draw_melspectrogram(pluto.audio_control_dmajor,
  is_chroma=True)
# Music dataset
pluto.draw_melspectrogram(pluto.df_music_data,
  is_chroma=True,
  cmap='plasma')
# Urban sound dataset
pluto.draw_melspectrogram(pluto.df_sound_data,
  is_chroma=True,
  cmap='brg')

D 大调控制钢琴音阶的 Chroma STFT 图如下:

图 8.16 – Chroma STFT,控制钢琴音阶(control-d-major)

图 8.16 – Chroma STFT,控制钢琴音阶(control-d-major)

音乐数据集的输出如下:

图 8.17 – Chroma STFT,音乐(Sad19513)

图 8.17 – Chroma STFT,音乐(Sad19513)

城市声音数据集的输出如下:

图 8.18 – Chroma STFT,城市声音(192123-2-0-11)

图 8.18 – Chroma STFT,城市声音(192123-2-0-11)

图 8**.17 的音频是带有强烈小提琴主旋律的电影配乐,而 图 8**.18 听起来像是在户外操场上玩耍的嘈杂孩子们的声音。

有趣的事实

在生成新图像或图表时,Pluto 会自动将图像文件写入或导出到~/Data-Augmentation-with-Python/pluto_img目录。因此,Pluto 会自动保存增强的图像到第三章第四章,以及波形图、音频声谱图、梅尔声谱图和色度 STFT 图表到第七章第八章。辅助函数的名称为_drop_image(),文件格式为pluto[id].jpg,其中id是来自self.fname_id变量的自增整数。

我们已经详细讨论并编写了音频声谱图、梅尔声谱图和色度 STFT 的 Python 代码。接下来,Pluto 将描述如何使用声谱图进行音频增强。

声谱图增强

Pluto 将重用大部分第七章中的包装函数。如果以下代码看起来有些难度,您可以重新阅读前一章。Pluto 将简化对包装函数的解释,因为他假设您已经是编写音频增强包装函数的专家。

音频声谱图、梅尔声谱图、色度 STFT 和波形图表从 Librosa 的load()函数读取音频文件时返回的幅度数据和采样率。这些数据经过了额外的变换,但它们的共同目标是可视化声波和频率。

在审阅了许多学术论文后,Pluto 得出结论,第七章中的音频增强技术同样适用于音频声谱图、梅尔声谱图和色度 STFT。特别是,他参考了 2015 年 Tom Ko、Vijayaditya Peddinti、Daniel Povey 和 Sanjeev Khudanpur 发表的学术论文《Speech Recognition 的音频增强》;2020 年 Loris Nannia、Gianluca Maguoloa 和 Michelangelo Paci 发表的《提高动物音频分类的数据增强方法》;以及 2017 年 Justin Salamon 和 Juan Pablo Bello 发表的《深度卷积神经网络与环境声音分类的数据增强》。

直观地说,这与第七章中的技术应该没有区别,因为底层的幅度数据和采样率是相同的。换句话说,您可以使用第七章中的音频增强函数来处理音频声谱图、梅尔声谱图和色度 STFT,像以下这些技术:

  • 时间拉伸

  • 时间偏移

  • 音高缩放

  • 噪声注入

  • 极性反转

  • 低通滤波器

  • 高通滤波器

  • 带通滤波器

  • 低棚滤波器

  • 高棚滤波器

  • 带阻滤波器

  • 峰值滤波器

还有其他功能,如MaskingGaps,它们可以通过audiomentation库获得。前一章中提到的安全级别同样适用于音频声谱图、Mel-声谱图和 Chroma STFT。

有趣的事实

你可以通过在correct类中覆盖任何 Python 函数来进行更改。Pluto 的函数属于PacktDataAug类。因此,你可以通过在函数定义之前添加@add_method(PacktDataAug)代码行来黑客入侵并覆盖 Pluto 的任何方法。

Pluto 需要修改_audio_transform()辅助函数,并包括新的is_waveform参数,默认设置为True,以便它不会影响第七章中的方法。新方法的定义如下:

# add is_waveform parameter
@add_method(PacktDataAug)
def _audio_transform(self, df, xtransform,
  Title = '',
  is_waveform = True):

更新后的代码片段如下:

# keep the default to be same for Chapter 7, Waveform graph
if (is_waveform):
  # augmented waveform
  self._draw_audio(xaug, sam_rate,
    title + ' Augmented: ' + fname)
  display(IPython.display.Audio(xaug, rate=sam_rate))
  # original waveform
  self._draw_audio(data_amp, sam_rate, 'Original: ' + fname)
# update to use spectrogram, me-spectrogram, and Chroma
else:
  xdata = [xaug, sam_rate, lname, 'Pluto']
  self.draw_spectrogram(xdata)
  self.draw_melspectrogram(xdata)
  self.draw_melspectrogram(xdata, is_chroma=True)

因此,is_waveform参数用于在第七章中使用波形图,或音频声谱图、Mel-声谱图和 Chroma STFT 图表。就是这样,这也是我们喜欢使用 Pluto 编程的原因。他遵循最佳的面向对象编程实践,所有函数都在一个类中。

Pluto 将新参数添加到play_aug_time_shift()包装函数中,并用控制数据进行测试。命令如下:

# augment the audio with time shift
pluto.play_aug_time_shift(pluto.audio_control_dmajor,
  min_fraction=0.8,
  is_waveform=False)

音频声谱图的输出如下:

图 8.19 – 声谱图,时间偏移,钢琴音阶(control-d-major)

图 8.19 – 声谱图,时间偏移,钢琴音阶(control-d-major)

Mel-声谱图的输出如下:

图 8.20 – Mel-声谱图,时间偏移,钢琴音阶(control-d-major)

图 8.20 – Mel-声谱图,时间偏移,钢琴音阶(control-d-major)

Chroma STFT 的输出如下:

图 8.21 – Chroma STFT,时间偏移,钢琴音阶(control-d-major)

图 8.21 – Chroma STFT,时间偏移,钢琴音阶(control-d-major)

图 8.19图 8.20图 8.21 将钢琴音阶(D 大调)向左偏移约 2 秒。换句话说,音频以G 音开始,循环后以F#音结束。Pluto 建议听听 Python 笔记本中的前后效果,这样是理解它的最简单方法。

Pluto 对人声数据集做相同的操作,使用以下命令:

# augment audio using time shift
pluto.play_aug_time_shift(pluto.df_voice_data,
  min_fraction=0.8,
  is_waveform=False)

音频声谱图的输出如下:

图 8.22 – 声谱图,时间偏移,人声(1085_ITS_ANG_XX)

图 8.22 – 声谱图,时间偏移,人声(1085_ITS_ANG_XX)

Mel-声谱图的输出如下:

图 8.23 – Mel-声谱图,时间偏移,人声(1085_ITS_ANG_XX)

图 8.23 – Mel-声谱图,时间偏移,人声(1085_ITS_ANG_XX)

Chroma STFT 的输出如下:

图 8.24 – Chroma STFT,时间偏移,人声(1085_ITS_ANG_XX)

图 8.24 – Chroma STFT,时间偏移,人声(1085_ITS_ANG_XX)

图 8**.22图 8**.23图 8**.24的原始音频是一位男性的声音,说:“我们将在几分钟内停下。”增强版本则变成了“停下几分钟[静音]我们将停下。”Pluto 可以在 Python Notebook 中听到增强前后的差异。音频增强的目标对于谱图和波形图是相同的,即通过增加输入数据来提高 AI 的预测准确性。

音乐和城市声音数据集的结果变化类似。Pluto 在 Python Notebook 中有时间偏移的代码,你可以运行它并看到、听到结果。此外,Pluto 将跳过在本章中描述其他音频增强功能的结果。因为结果与第七章中的相同,包装函数代码也在 Python Notebook 中。然而,他会解释play_aug_noise_injection()函数,因为这个函数可以扩展到特定话题,讨论声音工程师如何使用谱图。

声音工程师使用标准的音频谱图和其他各种谱图来发现并去除不需要的噪声,如嗡嗡声、嗡嗡声、嘶嘶声、剪辑、间隙、点击声和爆裂声。音频增强的目标是相反的。我们在安全范围内向录音中加入不需要的噪声。因此,我们增加了训练数据集并提高了 AI 的预测准确性。

Pluto 使用以下命令将白噪声添加到音乐数据集中:

# augment audio with noise injection
pluto.play_aug_noise_injection(pluto.df_music_data,
  min_amplitude=0.008,
  max_amplitude=0.05,
  is_waveform=False)

音频谱图的输出如下:

图 8.25 – 谱图,噪声注入,音乐(Happy41215)

图 8.25 – 谱图,噪声注入,音乐(Happy41215)

Mel-谱图的输出如下:

图 8.26 – Mel-谱图,噪声注入,音乐(Happy41215)

图 8.26 – Mel-谱图,噪声注入,音乐(Happy41215)

Chroma STFT 的输出如下:

图 8.27 – Chroma STFT,噪声注入,音乐(Happy41215)

图 8.27 – Chroma STFT,噪声注入,音乐(Happy41215)

图 8**.25图 8**.26图 8**.27播放重鼓、轻电子铃声和重电子吉他,伴有中等强度的白噪声。

有趣的挑战

这是一个思维实验。你是一个自动驾驶汽车系统开发团队的一员,你的目标是在驾驶时识别或识别汽车鸣笛声。你将如何增强音频数据?一个提示是考虑现实世界中的驾驶条件,例如交通或城市噪声。

如果你有嗡嗡声、嗡嗡声或爆裂声的音频文件,你可以通过交替使用play_aug_noise_injection()包装函数将它们注入到录音中,如下所示:

# Original use white noise, code snippet
xtransform = audiomentations.AddGaussianNoise(
  min_amplitude=min_amplitude,
  max_amplitude=max_amplitude,
  p=1.0)
# Update to using unwanted noise file
xtransform = audiomentations.AddShortNoises(
  sounds_path="~/path_to_unwanted_noise_file",
  min_snr_in_db=3.0,
  max_snr_in_db=30.0,
  noise_rms="relative_to_whole_input",
  min_time_between_sounds=2.0,
  max_time_between_sounds=8.0,
  noise_transform=PolarityInversion(),
  p=1.0)

前面的代码片段和完整文档可以在 GitHub 上的audiomentations库中找到。

下一个话题是使用谱图作为深度学习图像分类的图像输入的新颖想法。

谱图图像

从根本上讲,音频数据是时间序列数据。因此,AI 使用时间序列算法,如自回归积分滑动*均ARIMA)或指数*滑ES)算法进行音频分类。然而,还有更好的方法。你可以使用声谱图作为代表音频声音的图像输入,而不是时间序列数值数组。使用图像作为输入数据,你可以利用强大的神经网络算法更准确地对音频进行分类。

严格来说,这个话题并不直接涉及新的音频增强技术。然而,它是数据科学家必须理解的重要话题。尽管如此,Pluto 不会编写用于构建神经网络模型的 Python 代码,使用声谱图作为输入。

深度学习图像分类,也就是使用人工神经网络算法的机器学习模型,最*达到了前所未有的准确度,超过了 98%。许多 AI 科学家将深度学习技术应用于音频数据集,例如 Lonce Wyse 在 2017 年发布的《Audio Spectrogram Representations for Processing with Convolutional Neural Networks》和 Ciro Rodriguez、Daniel Angeles、Renzo Chafloque、Freddy Kaseng、Bishwajeet Pandey 于 2020 年发布的《Deep Learning Audio Spectrograms Processing to the Early COVID-19 Detection》。

该技术将音频声谱图作为图像输入,而不是音频振幅、采样率或 Mel 频率尺度。例如,音乐数据集(MEC)的目标是将一段音乐片段分类为快乐悲伤的情感。Pluto 可以将所有音频文件转换为音频声谱图并保存到本地驱动器。他将使用 Fast.ai 强大的 AI 框架和库来创建图像分类模型。他可以达到 95%以上的准确度。

关键问题是你能否使用在第三章第四章中讨论的图像增强方法来应用于声谱图?

这取决于 AI 模型的安全级别和目标。例如,使用图像增强技术,垂直翻转声谱图意味着将高频率翻转为低频率,反之亦然。Pluto 想知道这会如何影响音乐的情感。它可能是一个不安全的技术。然而,带有低噪声值的图像噪声注入方法可能是声谱图的安全技术。Pluto 认为,保持使用第七章中的音频增强技术更为合适。

类似的深度学习方法也可以应用于人类语音(CREMA-D)数据集,用于分类说话者的年龄、性别或种族。

有趣的挑战

这是一个思维实验。你能否使用语音转文本软件将语音转换为文本,并使用第五章第六章中的文本增强功能?一个提示是思考项目的范围。例如,如果 AI 旨在推断情感分析,它可能有效,但如果目标是识别男性或女性声音,则可能无效。

对于城市声音(US8K)数据集,Pluto 可以使用深度学习多标签分类技术来识别城市声音片段中的不同类型声音,比如电锯声、风声、孩子们玩耍的声音、雨声、狗叫声或枪声。

有趣的挑战

Pluto 挑战你重构 Pluto 类,以使其更加快速和紧凑。你还应该包括之前章节中的所有图像和文本包装器以及辅助函数。Pluto 鼓励你将你的库创建并上传到 GitHub 和 PyPI.org。此外,你不必将类命名为 PacktDataAug,但如果你引用或提到这本书,Pluto 和他的人类伙伴会露出灿烂的笑容。代码目标是易于理解、可重用的模式,并教你使用 Python Notebook。因此,将代码重构为 Python 库将是相对轻松且有趣的。

我们已经涵盖了音频频谱图、梅尔频谱图和色度 STFT 表示与增强的内容,包括将频谱图用作深度学习图像分类模型的图像输入技术。现在是时候做一个总结了。

总结

音频增强在书籍格式中很难解释,但通过附加的可视化技术,如音频频谱图、梅尔频谱图和色度 STFT,我们能更深入地理解音频的幅度、频率和采样率。此外,在 Python Notebook 中,你可以听到音频增强前后的效果。

与上一章相比,波形图显示信号随时间变化的幅度,帮助理解信号的形状和结构。频谱图显示信号随时间变化的频率的可视化表示,提供了对声音谐波内容的更深入了解。

音频频谱图有很多变种,无论是 specgram() 函数。Pluto 在一些频谱图类型上使用了 Python 代码包装器函数。大多数频谱图变种由你来探索,方法是通过额外的包装函数扩展 Pluto 对象。利用 Pluto 的面向对象最佳实践、函数包装器概念和 audiomentations 库,扩展 Pluto 添加额外的包装函数非常容易。

对于谱图增强技术,它们与第七章中的技术相同,如时间*移、时间拉伸、音高缩放、噪声注入、带通滤波器等。直观地看,这些方法应该没有区别,因为在上一章中,你选择将声音波形可视化为波形图,而在这一章中,你将它们绘制为音频谱图、梅尔谱图和色度 STFT 图。因此,底层数据是相同的。

Pluto 只需修改 _audio_transform() 辅助方法,新增一个 is_waveform 参数。此后,Python 代码变得简单而重复,但它隐藏了 audiomentations 库和 Pluto 面向对象最佳实践的强大功能。

在本章中,有许多 有趣的事实有趣的挑战。Pluto 希望你能利用这些优势,并将体验扩展到本章之外的领域。

下一章将超越典型的数据类型,如图像、文本和音频,探讨表格数据增强。

第五部分:表格数据增强

本部分包括以下章节:

  • 第九章表格数据增强

第九章:表格数据增强

表格增强通过向表格数据添加额外信息,使其在预测分析中更具实用性。数据库、电子表格和表格数据是表格数据的例子。它涉及将不足的数据集转化为强大的机器学习输入。表格增强可以帮助将非结构化数据转化为结构化数据,还可以协助将多个数据源合并为一个数据集。它是数据预处理中的一个关键步骤,有助于提高 AI 预测的准确性。

表格增强的想法是向给定的数据集中添加额外的信息,从而生成有价值的洞察。这些数据集可以来自各种来源,例如客户反馈、社交媒体帖子和物联网设备日志。表格增强可以通过用更多有意义的标签来丰富现有列,从而向数据集中添加新的信息列。它增加了数据集的完整性,并提供了更准确的洞察。

表格增强是在数据预处理和生成洞察时需要考虑的重要方法。它通过组织和丰富数据,以提高准确性和速度,为处理不完整和非结构化的数据集提供了一种方法。通过实施表格增强,你可以更好地挖掘现实世界数据集的价值,并做出更明智的决策。

表格增强是数据科学家们的一个年轻领域。它与使用分析进行报告、总结或预测是相反的。在分析中,改变或添加数据以扭曲结果以达到预设的期望结果是不道德的。而在数据增强中,目的是从现有数据集中衍生出新的数据。这两个目标可能不一致,但它们并不矛盾。深度学习(DL)是与传统分析完全不同的技术。一个是基于神经网络算法,另一个则基于统计分析和数据关系。

重要的一点是,即使你可能会向数据集中引入合成数据,这也是一种可接受的做法。Lei Xu 和 Kalyan Veeramachaneni 在 2018 年 11 月发布的《使用生成对抗网络合成表格数据》论文,在 arXiv 论坛 上支持这一观点。

本章专注于描述概念。它有一些使用 Python Notebook 的实际编码示例。主要原因之一是,目前只有少数几种开放源代码的表格增强库可用。你将花费大部分时间绘制各种图表,以从数据集中激发更多的洞察。

在继续之前,让我们先窥探一下一个真实的表格数据集。接下来,Pluto 会详细解释如何编写 Python 代码来处理以下内容:

# print out the tabular data
pluto.df_bank_data[['fraud_bool',
  'proposed_credit_limit',
  'customer_age',
  'payment_type']].sample(5)

输出如下:

图 9.1 – 银行账户欺诈数据集套件(NeurIPS 2022)

图 9.1 – 银行账户欺诈数据集套件(NeurIPS 2022)

增强表格数据的一个挑战是没有固定的方法可以普遍适用,例如翻转图像、注入拼写错误的单词或时间拉伸音频文件。你将了解到,数据集决定了哪些增强技术是安全的或处于安全范围内。在增强数据集之前,彻底审查表格数据集是非常重要的。

趣味事实

深度神经网络DNNs)在预测未来股市价值和表格数据方面表现出色,基于学术论文Deep learning networks for stock market analysis and prediction: Methodology, data representations, and case studies,由 Eunsuk Chong, Chulwoo Han 和 Frank C. Park 撰写。该论文由 Elsevier 出版,刊登于Expert Systems with Applications,第 83 卷,于 2017 年 10 月 15 日发布。

表格增强是一种通过合成数据增强表格数据集的方法。它包括通过衍生计算中的特征向表格数据集添加新列。你将花费大部分时间在 Python 代码中可视化现实世界的表格数据集,并用奇异的图表进行展示。在本章中,我们将涵盖以下主题:

  • 表格增强库

  • 增强类别

  • 现实世界的表格数据集

  • 探索和可视化表格数据

  • 转换增强

  • 提取增强

让我们从增强库开始。

表格增强库

表格数据增强不像图像、文本或音频增强那样被广泛建立。通常,数据科学家会根据项目开发特定的表格增强技术。GitHub 网站上有一些开源项目,但深度学习和生成式 AI 将继续推进时间序列和表格数据预测的预测能力,表格数据增强也将随之发展。以下开源库可以在 GitHub 网站上找到:

  • DeltaPy是一个针对生成和合成数据的表格增强工具,专注于金融应用,如时间序列股市预测。它基本上适用于广泛的数据集。GitHub 网站链接是github.com/firmai/deltapy。已发布的学术论文名为DeltaPy: A Framework for Tabular Data Augmentation in Python,由 Derek Snow, Alan Turing Institute 于 2020 年发表。

  • Synthetic Data VaultSDV)用于通过从单个表、多个表和时间序列数据生成合成数据来增强表格数据。2020 年,Kalyan Veeramachaneni、Neha Patki 和 Saman Amarsinghe 开发了一个名为Datacebo的商业版本。GitHub 链接是github.com/sdv-dev/SDV

  • 表格生成对抗网络GAN)采用成功生成真实图像的算法,并将其应用于表格增强。相关的学术论文是Tabular GANs for uneven distribution,由 Insaf Ashrapov 撰写,2020 年由康奈尔大学出版,发布于Arxiv。GitHub 网站链接是github.com/Diyago/GAN-for-tabular-data

Pluto 选择了DeltaPy库作为其表格增强包装函数背后的引擎,但首先,我们来看一下增强类别。

增强类别

将表格增强分组为不同的类别是有优势的。以下概念是 DeltaPy 库的新特性。增强函数被分为以下几个类别:

  • 变换技术可以应用于横截面数据和时间序列数据。表格增强中的变换技术用于修改现有的行或列,以创建新的、合成的数据,这些数据代表了原始数据。这些方法可以包括以下内容:

    • 缩放:增加或减少列值,以扩展数据集中值的多样性

    • 分箱:将两列或多列合并为一个单一的桶,以创建新特征

    • 类别编码:使用数值表示分类数据

    • *滑:补偿数据集中的异常高值或低值

    • 异常值检测与移除:检测并移除偏离正常值的数据点

    • 基于相关性的增强:根据现有特征之间的相关性添加新特征

  • 交互功能是一个横截面或时间序列的表格增强,包括归一化、离散化和自回归模型。在表格增强中,这些功能用于指定两个或更多变量之间的交互,并帮助生成表示原始变量组合的新特征。当建模多个输入特征和目标变量之间的关系时,这种类型的增强非常有益,因为它允许模型考虑不同组件之间的交互。

  • 映射方法使用特征分解进行表格增强,是一种无监督学习方法,利用数据分解通过特征向量和特征值将数据转化为低维空间。这种特征转换对于聚类、异常值检测和降维非常有用。通过将数据投影到特征向量上,数据可以在降低维度的同时,保持数据的结构。

  • 提取方法是一种表格数据增强技术,利用自然语言处理NLP)从表格数据集中的文本引用中生成附加信息。它使用TSflesh库——一组规则和启发式方法——从文本中提取附加数据,如姓名、日期和地点。这种方法有助于增强结构化数据集,其中句子分割分词词性标注的输出可以用来创建特征,供进一步处理使用。

  • 时间序列合成TSS)是一种表格数据增强方法,其中将来自多个来源或不同时间点的数据行进行合成。你可以使用它来增加数据集的大小,并创建一个更一致的特征集。

  • 横截面合成CSS)是一种表格数据增强方法,其中将来自多个来源的数据列进行合并。你可以使用它来增加数据集的特征,并创建更完整、更全面的数据视图。

  • 组合技术采用现有方法中的混合搭配过程。

在 DeltaPy 库中,每个类别都有相关的函数。然而,Pluto 必须构建一个神经网络模型,比如卷积神经网络CNN)或递归神经网络RNN),以评估这些方法的有效性。这是一个复杂的过程,而 Pluto 在本章中不会实现 CNN。不过,Pluto 会展示如何在 Python Notebook 中使用 DeltaPy 库的机制,但他不会解释这些方法是如何工作的。

现在是从Kaggle网站下载真实世界数据集的时候了。

真实世界的表格数据集

Kaggle网站上有成千上万的真实世界表格数据集。Pluto 选择了两个表格数据集来进行这一过程。

银行账户欺诈数据集套件(NeurIPS 2022)包含六个合成的银行账户欺诈表格数据集。每个数据集包含 100 万个记录。它们基于真实世界的欺诈检测数据,每个数据集侧重于不同类型的偏差。Sergio Jesus、Jose Pombal 和 Pedro Saleiro 在 2022 年以署名-非商业性使用-相同方式共享 4.0 国际(CC BY-NC-SA 4.0)许可证发布了该数据集。Kaggle链接为www.kaggle.com/datasets/sgpjesus/bank-account-fraud-dataset-neurips-2022

世界大联盟棒球电视收视率是一个数据集,记录了 1969 到 2022 年间收看棒球世界大联盟赛的电视观众数据。Matt OP 在 2022 年以CC0 1.0 通用(CC0 1.0)公共领域献身许可证发布了该数据集。Kaggle链接为www.kaggle.com/datasets/mattop/world-series-baseball-television-ratings

实例化 Pluto 并从 Kaggle 网站下载真实世界数据集的步骤是相同的。首先,加载 data_augmentation_with_python_chapter_9.ipynb 文件到 Google Colab 或你选择的 Jupyter Notebook 或 JupyterLab 环境。从这一点开始,代码片段来自于 Python Notebook,包含了完整的功能。

你将使用来自 第二章 的代码,因为你需要用于下载 Kaggle 数据集的包装函数,而不是用于图像、文本和音频增强的包装函数。如果步骤不熟悉,应该复习 第二章第三章

# Clone GitHub repo.
url = 'https://github.com/PacktPublishing/Data-Augmentation-with-Python'
!git clone {url}
# Initialize Pluto from Chapter 2
pluto_file = 'Data-Augmentation-with-Python/pluto/pluto_chapter_2.py'
%run {pluto_file}
# Verify Pluto
pluto.say_sys_info()
# Fetch Bank Fraud dataset
url = 'https://www.kaggle.com/datasets/sgpjesus/bank-account-fraud-dataset-neurips-2022'
pluto.fetch_kaggle_dataset(url)
# Import to Pandas
f = 'kaggle/bank-account-fraud-dataset-neurips-2022/Base.csv'
pluto.df_bank_data = pluto.fetch_df(f)
# Fetch World Series Baseball dataset
url = 'https://www.kaggle.com/datasets/mattop/world-series-baseball-television-ratings'
pluto.fetch_kaggle_dataset(url)
# Import to Pandas
f = 'kaggle/world-series-baseball-television-ratings/world-series-ratings.csv'
pluto.df_world_data = pluto.make_dir_dataframe(f)

趣味挑战

第八章 结束时,Pluto 挑战你对 Pluto 代码进行重构以提高速度和紧凑性。目标是将 Pluto 上传到 Pypi.org。这个挑战扩展了这一概念,要求你将设置代码合并成一个超级包装函数,例如 pluto.just_do_it()。Pluto 不使用超级方法,因为本书的目的是让概念和函数更容易学习,并揭开过程的神秘面纱。

收集 Pluto 系统信息的输出如下:

---------------------------- : ----------------------------
                                 System time : 2023/01/31 07:03
                                        Platform : linux
         Pluto Version (Chapter) : 2.0
                         Python (3.7.10) : actual: 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0]
                        PyTorch (1.11.0) : actual: 1.13.1+cu116
                            Pandas (1.3.5) : actual: 1.3.5
                                 PIL (9.0.0) : actual: 7.1.2
                    Matplotlib (3.2.2) : actual: 3.2.2
                                     CPU count : 2
                                    CPU speed : NOT available
---------------------------- : ----------------------------

趣味挑战

Pluto 挑战你从 Kaggle 网站或你的项目中搜索、下载并导入两个额外的表格数据集到 pandas。

至此,你已经选择了一个表格数据增强库,克隆了 GitHub 仓库,实例化了 Pluto,并从 Kaggle 网站下载了两个真实世界的表格数据集。现在,是时候让 Pluto 探索和可视化数据了。

探索和可视化表格数据

表格数据增强比图像、文本和音频增强更具挑战性。主要原因是你需要构建一个 CNN 或 RNN 模型,以查看合成数据的效果。

Pluto 将花更多时间解释他调查真实世界银行欺诈和世界大赛数据集的历程,而不是使用 DeltaPy 库实现表格增强函数。一旦你理解了数据可视化过程,你可以将其应用于其他表格数据集。

趣味事实

通常,Pluto 通过在该章节的 Python Notebook 中编写代码来开始一个章节。它包含大约 150 到 250 个代码和文本单元格。它们是未经组织的研究笔记和尝试错误的 Python 代码单元格。一旦 Pluto 通过编码证明概念和技术正确无误,他便开始编写该章节。作为写作过程的一部分,他会清理并重构 Python Notebook,添加包装函数并删除无用的代码。Python Notebook 的干净版本包含原始代码和文本单元格的 20% 到 30%。

尤其是在探索表格数据时,我们将涵盖以下主题:

  • 数据结构

  • 第一个图表视图

  • 校验和

  • 专门的图表

  • 探索世界大赛棒球数据集

让我们从数据结构开始。

数据结构

Pluto 通过使用 pandas 的内置函数检查数据结构。他使用以下命令:

# display tabular data in Pandas
pluto.df_bank_data.info()

结果如下:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000000 entries, 0 to 999999
Data columns (total 32 columns):
#     Column                                                    Non-Null Count        Dtype
---    ------                                                 --------------        ----
0     fraud_bool                                            1000000 non-null    int64
1     income                                                    1000000 non-null    float64
2     name_email_similarity                     1000000 non-null    float64
3     prev_address_months_count             1000000 non-null    int64
4     current_address_months_count        1000000 non-null    int64
5     customer_age                                        1000000 non-null    int64
6     days_since_request                            1000000 non-null    float64
7     intended_balcon_amount                    1000000 non-null    float64
8     payment_type                                        1000000 non-null    object
9     zip_count_4w                                        1000000 non-null    int64
10    velocity_6h                                         1000000 non-null    float64
11    velocity_24h                                        1000000 non-null    float64
12    velocity_4w                                         1000000 non-null    float64
13    bank_branch_count_8w                        1000000 non-null    int64
14    date_of_birth_distinct_emails_4 1000000 non-null    int64
15    employment_status                             1000000 non-null    object
16    credit_risk_score                             1000000 non-null    int64
17    email_is_free                                     1000000 non-null    int64
18    housing_status                                    1000000 non-null    object
19    phone_home_valid                                1000000 non-null     int64
20    phone_mobile_valid                            1000000 non-null    int64
21    bank_months_count                             1000000 non-null    int64
22    has_other_cards                                 1000000 non-null     int64
23    proposed_credit_limit                     1000000 non-null    float64
24    foreign_request                                 1000000 non-null     int64
25    source                                                    1000000 non-null    object
26    session_length_in_minutes             1000000 non-null    float64
27    device_os                                             1000000 non-null    object
28    keep_alive_session                            1000000 non-null    int64
29    device_distinct_emails_8w             1000000 non-null    int64
30    device_fraud_count                            1000000 non-null    int64
31    month                                                     1000000 non-null    int64
dtypes: float64(9), int64(18), object(5)
memory usage: 244.1+ MB

银行欺诈数据集由 32 列、100 万条记录或行、没有空值,以及五列非数值型数据组成。Pluto 想要找出哪些列是连续的分类的。他通过计算每列的唯一值来实现这一点。他使用以下 pandas 函数:

# count uniqueness
pluto.df_bank_data.nunique()

部分输出如下:

fraud_bool                                                             2
income                                                                     9
name_email_similarity                             998861
prev_address_months_count                            374
current_address_months_count                     423
customer_age                                                         9

Python Notebook 包含了完整的结果。共有 7 个连续列和 25 个分类列。通常,连续列有很多独特的值,如总记录数,而分类列的唯一值通常介于 2 到几百之间。

在使用图表展示数据之前,Pluto 将使用以下命令查看银行欺诈数据集的样本数据:

# display the tabular data using Pandas
pluto.df_bank_data[['fraud_bool',
    'proposed_credit_limit',
    'customer_age',
    'payment_type']].sample(5)

输出如下:

图 9.2 – 示例银行欺诈数据

图 9.2 – 示例银行欺诈数据

在反复运行命令和变体后,Pluto 发现数据中没有什么意外。数据是干净的。Python Notebook 还包含额外的检查函数,如 pandas 的describe()方法。

趣味事实

对于表格数据集,你将编写自定义代码来检查、可视化和扩展数据。换句话说,更多的可重用概念和过程将被带到下一个项目,而不是可重用的代码。

银行欺诈数据集包含 3200 万个元素,这也是数据科学家处理的典型数据量。然而,如果你尝试使用默认设置通过 pandas 和 Matplotlib 绘制 3200 万个点,Python Notebook 会崩溃。Pluto 创建了一个简单的图表pluto.df_bank_data.plot(),但他的 Google Colab Pro 版本 Python Notebook 崩溃了,原因是需要更多的内存。

第一个图形视图

各种图表并没有直接帮助表格扩展过程。主要目标是帮助你想象一个大型表格数据集。阅读数百万个数据点比将它们绘制在图表上更不有效。你可以跳过关于绘图的部分,直接进入使用 DeltaPy 库的表格扩展技术。

对于大型数据集,解决方案是选择计算或汇总值的图表。因此,将绘制更少的点。例如,直方图图表是一个可行的选择,因为它将频率范围分组。Pluto 使用一个包装函数来绘制直方图:

# display histogram plot
pluto.draw_tabular_histogram(pluto.df_bank_data,
    title='Bank Fraud data with 32 million points')

包装函数的关键代码行如下:

# code snippet, use Pandas histogram function
df.plot.hist()

输出如下:

图 9.3 – 银行欺诈直方图

图 9.3 – 银行欺诈直方图

图 9.3没有提供任何有益的见解。因此,Pluto 继续通过校验和概念来总结数据。

校验和

Pluto 花了几周的时间与不同类型的图表和绘图库进行尝试,如MatplotlibSeabornJoypiPyWaffle。他玩得很开心,但大多数并没有提升银行欺诈和世界系列数据集的可视化效果。

此时,Pluto 将继续进行更多的绘图操作。在表格数据中,显示字符串类型的非数字数据具有挑战性。一种简洁的解决方案是将分类字符串数据转换为整数令牌索引。Pluto 编写了 _fetch_token_index() 辅助函数,用于从列表中索引值。关键代码片段如下:

# code snippet for token index
for i, x in enumerate(xarr):
  if (val == x):
    return i

add_token_index() 包装函数使用了辅助函数和 pandas 的 apply() 函数。核心代码片段如下:

# code snippet for tokenize
arrname = numpy.array(df[cname].unique())
df[tname] = df[cname].apply(
  self._fetch_token_index,
  args=(arrname,))

综合起来,Pluto 使用以下命令来复制并创建数据欺诈数据集的令牌化列:

# tokenize the data
pluto.df_bank_tokenize_data = pluto.df_bank_data.copy()
pluto.add_token_index(
  pluto.df_bank_tokenize_data,
  ['payment_type', 'employment_status',
  'housing_status', 'source', 'device_os'])

Pluto 通过查看以下命令中的示例值,双重检查了令牌化过程:

# print out first 6 row of the tabular data
pluto.df_bank_tokenize_data[['payment_type',
  'payment_type_tokenize']].head(6)

输出结果如下:

图 9.4 – 银行欺诈样本令牌化数据

图 9.4 – 银行欺诈样本令牌化数据

Pluto 对其他列进行了双重检查,确保它们是正确的。你可以通过阅读 Python Notebook 查看代码和结果。

对于数据分析来说,具有一个使用 pandas apply() 方法和 lambda_fetch_checksum() 辅助函数是很实用的。代码片段如下:

# code snippet for calculate the checksum
df['checksum'] = df.apply(
  lambda x: numpy.mean(tuple(x)), axis=1)

Pluto 使用以下命令计算银行欺诈数据集的校验和:

# compute the checksum
pluto._fetch_checksum(pluto.df_bank_tokenize_data)

计算 3200 万个数据点的校验和花费了 27 秒。现在,让我们探索一些与校验和概念相关的专业绘图。

专业绘图

Pluto 想提醒你,以下图表和练习与表格增强并不直接相关。目标是提高你在理解和可视化大型真实世界数据集方面的技能——例如,银行欺诈数据集包含 100 万条记录,旨在为数据增强做准备。如果你愿意,可以跳过绘图练习,直接进入表格增强的课程。

Pluto 创建了一个包含有限列的 self.df_bank_half_data,以便于展示。他使用 heatmap() 函数绘制了相关图。命令如下:

# plot correlogram
pluto.draw_tabular_correlogram(pluto.df_bank_half_data,
  title='Bank Fraud half Correlogram')

输出结果如下:

图 9.5 – 银行欺诈半相关图

图 9.5 – 银行欺诈半相关图

图 9.5 显示了 credit_risk_scoreproposed_credit_limit 之间的高相关性,达到了 61%。fraud_bool 与其他所有参数的相关性较低。

当 Pluto 使用整个数据集绘制相关图时,揭示了校验和velocity_6hvelocity_24hvelocity_4w之间的高相关性。代码和输出结果可以在 Python Notebook 中找到。

draw_tabular_heatmap() 包装函数看起来像是热图。命令如下:

# plotting heatmap
pluto.draw_tabular_heatmap(
  pluto.df_bank_tokenize_data,
  x='checksum',
  y='month')

输出结果如下:

图 9.6 – 银行欺诈校验和与月份热图

图 9.6 – 银行欺诈 校验和与月份热力图

图 9.6 显示了一个模式,但 校验和月份 之间的关系并不明确。

趣味小知识

Pluto 并不是银行欺诈数据的专家,而你也不可能在每个领域都是专家。Pluto 向银行和消费者保护机构的朋友咨询,进行背景研究。以下是他在工作中使用的一些图表。

欺诈数据 fraud_bool == 1 占总数据的 1%。因此,Pluto 可能希望增强更多欺诈数据。他使用以下命令创建了一个 pandas DataFrame:

# tokenize the text or categorical columns
pluto.df_bank_fraud_data = pluto.df_bank_tokenize_data[
  pluto.df_bank_tokenize_data.fraud_bool == 1]
pluto.df_bank_fraud_data.reset_index(
  drop=True,
  inplace=True)

Pluto 的银行专家朋友建议的以下两个图形非常有趣,但可能对银行欺诈数据增强没有益处。完整代码在 Python Notebook 中。尽管如此,它们仍然是超越标准线性或条形图的发人深省的概念:

图 9.7 – 银行欺诈 Seaborn 带掩码的热力图

图 9.7 – 银行欺诈 Seaborn 带掩码的热力图

下一个图形是群集图(Swarmplot)。

图 9.8 – 银行欺诈 Seaborn 群集图

图 9.8 – 银行欺诈 Seaborn 群集图

趣味挑战

你能否利用 tripcolor() 3D 图,展示在 图 9.9 中的内容,使用银行欺诈数据集?tripcolor() 的代码在 Python Notebook 中:

图 9.9 – 趣味挑战 – 随机值的 tripcolor 图

图 9.9 – 趣味挑战 – 随机值的 tripcolor 图

探索 World Series 数据

在这一部分,Pluto 将花费大量时间绘制各种图形,以便理解和可视化 World Series 数据。他并没有执行表格数据增强。尽管理解数据在决定应用哪些增强功能之前至关重要,但你可以跳过这一练习,直接进入表格数据增强的封装函数。

趣味小知识

据说,Pluto,一只虚构的西伯利亚哈士奇,喜欢冲到前面,开始编写增强代码,而不花时间嗅探数据集的内容。因此,他的 AI 模型有 9 次中的 10 次会出现偏差,导致高水*的假阴性和假阳性。因此,花费 40% 到 70% 的时间研究数据集似乎效率不高,但事实并非如此。这在处理实际数据集时是一个可以接受的现实。

Pluto 对 World Series 数据集执行类似的处理。他首先运行 info() 方法,然后是 nunique(), describe(),接着运行 sample()。World Series 数据集包含 14 列和 54 行,代表 756 个数据点。数据集中有 11 列数字型数据和 3 列标签类别。其他因素包括以下的 pluto.df_world_data.info() 命令:

# describe the tabular dataset
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 54 entries, 0 to 53
Data columns (total 14 columns):
#   Column              Non-Null Count  Dtype
---  ------              --------------  -----
0   year                54 non-null     int64
1   network             54 non-null     object
2   average_audience    54 non-null     int64
3   game_1_audience     53 non-null     float64
4   game_2_audience     52 non-null     float64
5   game_3_audience     53 non-null     float64
6   game_4_audience     53 non-null     float64
7   game_5_audience     44 non-null     float64
8   game_6_audience     31 non-null     float64
9   game_7_audience     18 non-null     float64
10  total_games_played  54 non-null     int64
11  winning_team        54 non-null     object
12  losing_team         54 non-null     object
13  losing_team_wins    54 non-null     int64
dtypes: float64(7), int64(4), object(3)
memory usage: 6.0+ KB

其他结果可以在 Python Notebook 中找到。直方图绘图是 World Series 数据集的首要数据可视化技术。命令如下:

# plot histogram graph
pluto.draw_tabular_histogram(pluto.df_world_data,
  title='World Series Baseball',
  maxcolors=14)

输出结果如下:

图 9.10 – World Series 直方图

图 9.10 – World Series 直方图

图 9.10中的直方图没有突出显示七场比赛观众之间的比较。Pluto 使用来自joypy库的joyplot()方法显示观众与电视网络之间的关系。命令如下:

# plot joyplot graph
pluto.draw_tabular_joyplot(pluto.df_world_data,
  x=['game_1_audience', 'game_2_audience', 'game_3_audience',
     'game_4_audience', 'game_5_audience', 'game_6_audience',
     'game_7_audience'],
  y='network',
  t='World series baseball audience')

输出如下:

图 9.11 – 世界大赛观众与电视网络

图 9.11 – 世界大赛观众与电视网络

图 9.11是一个美丽且富有洞察力的可视化图。NBC 电视网络在第七场比赛中拥有最多的观众,但在第五场比赛中拥有最少的观众。Fox 电视台的观众最少,而 ABC 电视台的总观众数最多,仅略高于 NBC 电视台。第三场比赛的观众最少,而第七场比赛的观众最多。

Pluto 通过将标签类别转换为整数令牌索引并计算校验和,为世界大赛数据集的增强做准备。命令如下:

# copy tokenize data
pluto.df_world_tokenize_data = pluto.df_world_data.copy()
# eliminate the null value
pluto.df_world_tokenize_data=pluto.df_world_tokenize_data.fillna(0)
# tokenize the data
pluto.add_token_index(pluto.df_world_tokenize_data,
  ['network', 'winning_team', 'losing_team'])
pluto.df_world_tokenize_data =
  pluto.df_world_tokenize_data.drop(
  ['network', 'winning_team', 'losing_team'],
  axis=1)
# calculate the checksum
pluto._fetch_checksum(pluto.df_world_tokenize_data)

用于双重检查并打印分词和校验和结果的代码可以在 Python Notebook 中找到。Pluto 使用以下命令快速绘制了相关图:

# draw the correlogram graph
pluto.draw_tabular_correlogram(pluto.df_world_tokenize_data,
  title='World Series Baseball Correlogram')

结果如下:

图 9.12 – 世界大赛相关图

图 9.12 – 世界大赛相关图

图 9.12揭示了数据之间许多有趣的关系。例如,losing_team_winstotal_game_played之间有 100%的相关性,average_audience、game_1_audiencegame_2_audiencegame_3_audiencegame_4_audience之间也存在强烈的关系。

Pluto 使用joyplot()方法将校验和与按电视网络分组的*均观众进行比较。命令如下:

# draw the joyplot graph
pluto.draw_tabular_joyplot(pluto.df_world_tokenize_data,
  x=['checksum', 'average_audience'],
  y='network_tokenize',
  t='World series baseball, checksum and average auidence',
  legloc='upper right')

输出如下:

图 9.13 – 世界大赛校验和,按电视网络分组的*均观众

图 9.13 – 世界大赛校验和,按电视网络分组的*均观众

图 9.13中,Pluto 使用mean()函数计算校验和值。因此,与*均观众数的比较呈现出相似的形状。与图 9.11相比,*均观众人数与每场比赛的总观众人数之间的关系并不显而易见,因为 CBS 电视台的*均观众数最高,但似乎每场比赛的观众较少。

此时,Pluto 在想,绘制更多图表是否有助于他更好地理解数据集。你很可能也在想同样的问题。

探索更多图表的理由有两点。首先,现实世界中的表格数据非常多样化。因此,了解各种图表能让你更好地为下一个项目做好准备。其次,没有任何标准或算法可以告诉你,数据集是否已经学得足够深入。因此,如果你已经了解数据,可以跳过数据增强函数部分,或者像 Pluto 一样继续学习新的图表。

Pluto 使用 draw_tabular_waffle() 方法调用 pywaffle 库中的 Waffle 类。显示世界大赛冠军队的命令如下:

# plot the waffle graph
pluto.draw_tabular_waffle(pluto.df_world_data,
  col='winning_team',
  title='World Series Baseball Winning Team')

输出结果如下:

图 9.14 – 世界大赛冠军队

图 9.14 – 世界大赛冠军队

Pluto 对显示失败队伍做了相同的处理。命令如下:

# draw the waffle graph
pluto.draw_tabular_waffle(pluto.df_world_data,
  col='losing_team',
  title='World Series Baseball Losing Team')

输出结果如下:

图 9.15 – 世界大赛失败队

图 9.15 – 世界大赛失败队

图 9.149.15 是色彩鲜艳的华夫图。没有明显的强队或弱队。Pluto 对电视网络做了相同的处理。命令如下:

# draw the waffle graph
pluto.draw_tabular_waffle(pluto.df_world_data,
  col='network',
  title='World Series Baseball Network',
  anchor=(0.5, -0.2))

输出结果如下:

图 9.16 – 世界大赛电视网络

图 9.16 – 世界大赛电视网络

图 9.16 显示了数据中一个令人惊讶的隐藏事实:Fox TV 播出了最多的比赛,但从 图 9.11图 9.12 中来看,它似乎不是观众最多的电视网络。

趣味挑战

这是一个思想实验:你能想象一个 四维4D)图表吗?提示:一个二维图显示两个度量标准,例如每场比赛的电视观众人数,或者一个带有时间序列隐含的 X 轴的向量,例如银行成员的收入,X 轴表示日期或月份。三维图通常显示山上的积雪深度。时间可以作为第四维。

Pluto 探索并解释了现实世界中的银行欺诈和世界大赛数据集。他使用 pandas 函数来展示统计信息,并提供了许多图表来进行可视化。在对表格数据进行增强之前,理解和可视化数据是第一步,也是最重要的一步。

趣味事实

数据增强是深度学习(DL)和生成式人工智能(AI)实现前所未有的准确性和成功的秘密。许多学术论文加强了数据增强的重要性,例如 Cherry Khosla 和 Baljit Singh Saini 撰写的Enhancing Performance of Deep Learning Models with Different Data Augmentation Techniques: A Survey,该论文发表于IEEE 2020 Intelligent Engineering and Management (ICIEM)国际会议

数据增强的转变

在深入探讨表格数据增强方法之前,Pluto 重申他不会建立神经网络模型来验证增强对特定数据集的效果。此外,编写包装函数的模式遵循以前的做法:使用选定的库来执行关键的增强步骤。

正如 Python Notebook 中所述,DeltaPy 库的依赖是 fbprophetpystan 库。这三个库都处于测试版,可能不稳定。Pluto 已反复测试过 Python 代码。一旦这些库加载完成,代码就能完美运行。

表格变换是一种技术集合,它通过变换方法基于一个变量生成新的数据集。它适用于横截面数据和时间序列数据。DeltaPy 库定义了 14 个变换函数。

这些变换技术包括用于当前信息的操作函数、用于历史数据的*滑方法,以及用于滞后和领先值的选择过滤器过程。

在图像增强中,Pluto 可以运行这些函数并查看照片中发生了什么变化。这里的效果非常明显,例如裁剪放大改变色调值。表格增强需要对深度学习和时间序列数据有一定的了解。换句话说,输出效果不那么明显,因此选择适合特定数据集的增强函数可能会令人望而却步。Pluto 将演示如何为表格增强编写 Python 代码,但他不会详细解释何时使用这些函数。

时间序列预测是人工智能中一个成熟且高度研究的分支。理解时间序列及其如何预测或预示未来结果可能需要数门大学课程。时间序列的简洁定义是一个依赖于时间的数据序列。典型的时间序列数据是市场股票价值。例如,Pluto 使用过去 10 年的微软股票数据来预测明天、下周或下个月的收盘价。天气预报是时间序列算法的另一个广泛应用。

时间序列数据中的两个关键概念是滞后时间窗口。滞后时间是从观察者到某一特定点的时间,而窗口是分段的元素范围。时间序列算法中还有几十个其他关键概念,从最早的长短期记忆LSTM)神经网络到ARIMASARIMAHWESResNetInceptionTimeMiniRocket等。

大多数表格数据可以转换为时间序列数据。世界系列数据是基于年份的时间序列数据。银行诈骗数据没有直接的时间向量。然而,通过添加时间数据,Pluto 可以预测一天中的哪个时段——无论是清晨还是深夜——大多数在线银行诈骗发生的时刻,或者他可以预测季节性银行诈骗的发生时间,例如圣诞节或大学春假期间。

共有 14 种变换方法,特别地,Pluto 将介绍以下三种函数:

  • 鲁棒缩放器

  • 标准缩放器

  • 上限限制

让我们从鲁棒缩放器开始。

鲁棒缩放器

K-means主成分分析PCA)时间序列算法使用欧几里得距离。因此,缩放适用于世界系列数据集。当你不确定数据分布时,鲁棒缩放器,也称为归一化,是一种可行的技术。该算法用于预测未来结果。

Pluto 的 augment_tabular_robust_scaler() 封装函数使用了 DeltaPy 库函数和喜悦图与华夫图。核心代码片段如下:

# define robust scaler
def augment_tabular_robust_scaler(self, df):
  return deltapy.transform.robust_scaler(df.copy(),
    drop=["checksum"])

完整的函数代码可以在 Python 笔记本中找到。世界大赛数据的命令如下:

# augment using robust scaler
df_out = pluto.augment_tabular_robust_scaler(
  pluto.df_world_tokenize_data)
# plot joy plot
pluto.draw_tabular_joyplot(df_out,
  x=['game_1_audience', 'game_2_audience', 'game_3_audience',
     'game_4_audience', 'game_5_audience', 'game_6_audience',
     'game_7_audience'],
  y='network_tokenize',
  t='World series baseball audience')

输出如下:

图 9.17 – 世界大赛和稳健缩放器喜悦图

图 9.17 – 世界大赛和稳健缩放器喜悦图

图 9**.17 确认了 Pluto 成功实现了稳健缩放器增强技术。它在预测中的实际效果则是另一个问题,这取决于预测目标和所使用的基础深度学习模型或算法。

标准缩放器与稳健缩放器类似。

标准缩放器

依赖于高斯分布或线性回归和逻辑回归的深度学习模型将从标准化缩放器增强方法中受益。Pluto 的 augment_tabular_standard_scaler() 封装函数使用了 DeltaPy 库函数和喜悦图与华夫图。核心代码片段如下:

# define standard scaler
def augment_tabular_standard_scaler(self, df):
  return deltapy.transform.standard_scaler(df.copy(),
    drop=["checksum"])

完整的函数代码可以在 Python 笔记本中找到。命令如下:

# augment using standard scaler
df_out = pluto.augment_tabular_standard_scaler(
  pluto.df_world_tokenize_data)
# draw using joy plot
pluto.draw_tabular_joyplot(df_out,
  x=['game_1_audience', 'game_2_audience', 'game_3_audience',
     'game_4_audience', 'game_5_audience', 'game_6_audience',
     'game_7_audience'],
  y='network_tokenize',
  t='World series baseball audience',
  legloc='upper right')

输出如下:

图 9.18 – 世界大赛和标准缩放器喜悦图

图 9.18 – 世界大赛和标准缩放器喜悦图

图 9**.18 演示了 Pluto 正确进行了数据增强。他并未使用增强后的数据构建并训练深度学习模型,以确认它是否提高了预测准确性。许多表格数据增强方法需要定义深度学习项目的目标,以验证增强是否有效。例如,Pluto 可以构建一个深度学习模型来预测下一次世界大赛的观众人数。

我们将要查看的下一个表格数据转换技术是 封顶

封顶

封顶技术限制了分布值,例如*均值、最大值、最小值或任意值。特别地,它通过统计分析来限制数值,并用特定的百分位数值替换异常值。

Pluto 的 augment_tabular_capping() 封装函数使用了 DeltaPy 库函数和相关图。核心代码片段如下:

# define capping
def augment_tabular_capping(self, df):
  x, y = deltapy.transform.outlier_detect(df, "checksum")
  return deltapy.transform.windsorization(df.copy(),
    "checksum",
    y,
    strategy='both')

银行欺诈数据的命令如下:

# augment using capping
df_out = pluto.augment_tabular_capping(
  pluto.df_bank_tokenize_data)
# draw correlogram plot
pluto.draw_tabular_correlogram(df_out,
  title='Bank Fraud Capping Transformation')

输出如下:

图 9.19 – 银行欺诈封顶相关图,半数据

图 9.19 – 银行欺诈封顶相关图,半数据

图 9**.19 表示 Pluto 正确实施了封顶技术。与 图 9**.4(原始数据)相比,数值相似,符合预期。

表格数据转换封装函数的 Python 实现变得重复。因此,Pluto 会简要介绍 DeltaPy 库中的其他九种方法。它们如下:

  • 操作是一种使用幂函数、对数函数或*方根函数替换数据集元素的技术。

  • *滑是一种使用三重指数*滑或 Holt-Winters 指数*滑函数的技术。

  • 分解是一种使用朴素分解函数处理时间序列数据中的季节性向量的技术。

  • 过滤是一种使用 Baxter-King 带通滤波器对时间序列数据进行*滑的技术。

  • 谱分析是一种使用周期图函数估计谱密度的技术。

  • 波形是一种使用连续谐波波形雷达函数来增强波形数据的技术。

  • 滚动是一种使用均值或标准差计算固定窗口大小下的滚动*均值的技术,适用于时间序列数据。

  • 滞后是一种计算时间序列数据中滞后值的技术。

  • 预测模型是一种使用 Prophet 算法来预测时间序列数据中季节性趋势(如每周或每年)的技术。

有趣的挑战

Pluto 挑战你在 Python Notebook 中实现九种表格转换技术中的三个包装函数。

现在我们已经回顾了各种表格转换技术,让我们来看看交互技术。

交互增强

交互技术在机器学习和统计建模中用于捕捉数据集中两个或更多特征之间的关系,以进行增强。其目标是创建新的增强数据,捕捉现有组件之间的交互关系,这有助于提高模型的性能,并为数据提供更多的见解。你可以将这些技术应用于横截面数据或特定时间数据,包括归一化、离散化和自回归模型。

Pluto 从七种方法中选择了两种进行 Python 编程演示。与转换增强方法一样,编码是重复性的。因此,Pluto 将为其他五种交互增强技术提供有趣的挑战。

Pluto 将从回归方法开始,然后是操作符方法。

回归增强

回归方法使用lowess *滑器函数,通过局部加权给定点附*的观测值来*滑数据曲线。这是一种有用的表格增强技术,适用于探索散点图中因变量和自变量之间的关系,这种关系需要通过线性函数来很好地描述。该方法可能会受到前瞻性偏差的影响。因此,Pluto 建议在用于预测建模时要谨慎使用。

Pluto 的augment_tabular_regression()包装函数使用 DeltaPy 库函数、愉悦图和自相关图。核心代码片段如下:

# define regression
def augment_tabular_regression(self, df):
  return deltapy.interact.lowess(
    df.copy(),
    ["winning_team_tokenize","losing_team_tokenize"],
    pluto.df_world_tokenize_data["checksum"],
    f=0.25, iter=3)

世界系列数据的命令如下:

# augment using tabular regression
df_out = pluto.augment_tabular_regression(
  pluto.df_world_tokenize_data)
# draw joy plot
pluto.draw_tabular_joyplot(df_out,
  x=['game_1_audience', 'game_2_audience', 'game_3_audience',
     'game_4_audience', 'game_5_audience', 'game_6_audience',
     'game_7_audience'],
  y='network_tokenize',
  t='World series baseball audience: Regression',
  legloc='upper right')

输出如下:

图 9.20 – 世界系列回归增强,愉悦图

图 9.20 – 世界系列回归增强,愉悦图

图 9.20确认 Pluto 正确地实现了回归表格增强。DeltaPy 库执行实际计算。因此,如果 Pluto 出错,结果将是一个错误,或者数据集将包含随机数并无法正确显示。Pluto 只能声明回归技术对世界系列数据的有效性。接下来我们将讨论的表格增强技术是运算符增强方法。

运算符增强

运算符方法是一个简单的乘法或除法函数,作用于表格数据中的两个变量。

Pluto 的augment_tabular_operator()包装函数使用 DeltaPy 库函数和相关图。其核心代码片段如下:

# define tabular operator
def augment_tabular_operator(self, df):
  return deltapy.interact.muldiv(
    df.copy(),
    ["credit_risk_score","proposed_credit_limit"])

Pluto 运行了用于银行欺诈数据的命令,结果如下:

# augment using tabular operator
df_out = pluto.augment_tabular_operator(
  pluto.df_bank_tokenize_data)
# draw the correlogram plot
pluto.draw_tabular_correlogram(df_out,
  title='Bank Fraud Operator Interaction')

输出结果如下:

图 9.21 – 银行欺诈运算符增强,相关图

图 9.21 – 银行欺诈运算符增强,相关图

图 9.21显示了三个新向量之间的强关系:credit_risk_score_X_proposed_credit_limit(乘法)、proposed_credit_limit/credit_risk_score(除法)和proposed_credit_limit_X_credit_risk_score(乘法)。Pluto 正确地实现了运算符功能,但仍需确定深度学习预测准确度的收益。

其他五种交互表格增强技术如下:

  • 离散化是一种使用决策树等宽分箱等频分箱K 均值聚类来增强表格数据的方法。离散化方法取决于 AI 模型和表格数据的特性。Pluto 建议尝试多种方法并评估其性能。

  • 分位数归一化方法通过转换数据集,使它们具有相同的累计分布值,从而使数据集的分布具有可比性。

  • 哈弗辛距离计算两个角度点之间的最短距离,例如地球表面的距离。表格增强还使用欧几里得马哈拉诺比斯闵可夫斯基距离算法。

  • 技术指标是表格增强中的专业方法之一。它利用技术分析来帮助预测证券或金融工具的未来价格走势。这些指标基于价格、交易量和未*仓合约的数学计算。

  • 遗传方法,或遗传表格增强,是一种使用进化算法来优化 AI 模型的机器学习技术。其概念是为一个问题创建一群候选解,即染色体,然后通过应用交叉、变异和选择等遗传操作,随着时间的推移进化这些解的群体。目标是通过自然选择找到问题的最佳解决方案。

趣味挑战

Pluto 挑战你在 Python Notebook 中实现更多的交互增强。

下一个表格增强类别是映射增强。Pluto 会描述映射函数,但不会在 Python Notebook 中实现它们。

映射增强

映射方法使用机器学习(ML)和数据分析来总结和减少数据的维度,以进行增强。可以通过无监督学习或监督学习来完成。一些映射方法的例子包括特征分解和 PCA。PCA 是一种统计程序,它将一组相关变量转换为称为主成分的无关变量。

在 DeltaPy 库中,有七种映射方法用于表格增强。Pluto 在 Python Notebook 中做了一些实现,但他不会在这里解释代码。Python 包装函数是重复的,可以很容易地应用于任何映射方法。函数如下:

  • 特征分解ED)是用于表格增强的PCA的一种形式。在特征分解中,特征向量是数据的协方差矩阵,而相应的特征值表示每个组件的方差量。特征分解包括线性判别分析LDA)、奇异值分解SVD)和马尔可夫链

  • 交叉分解方法,包括典型相关分析CCA),用于揭示两块多变量表格数据之间的线性关系。各种应用,如降维、特征提取和特征选择,都使用交叉分解方法。目标是找到表格数据变量之间的线性组合。

  • 核*似方法用于支持向量机(SVM)等机器学习算法,将表格数据转换到一个更高维的空间,在该空间中可以找到一个线性边界来分离不同的类别。加性 Chi2 核是一种特定的核*似方法,用于衡量两个变量集之间的独立性。

  • 自编码器在多个领域中都有应用,例如图像压缩、异常检测,以及为表格增强生成新数据。我们在监督学习任务的预训练步骤中使用自编码器,以提高后续模型的性能。

  • 流形学习是一类用于非线性降维的技术,旨在保持表格数据的基本非线性结构。局部线性嵌入LLE)是一种方法,其思想是*似高维空间中数据点之间的局部线性关系。目标是找到一个低维的高维数据表示,同时仍然捕捉到表格数据中的基本模式和关系。

  • 聚类是一种流行的无监督机器学习技术,用于将相似的表格数据点分组到聚类中。聚类方法有助于识别表格数据中的模式和结构。

  • 邻*是用于分类和回归问题的监督式机器学习算法的最*邻方法,也用于表格增强。你还可以将最*邻方法扩展为更复杂的版本,称为k-最*邻k-NN)分类。

接下来我们要看的表格增强分类是提取增强。

提取增强

提取方法是时间序列分析中的一种过程,其中多个构建的元素作为输入,每个时间序列从中提取一个单一的值,进而创建新的增强数据。此方法使用名为TSfresh的包,包含默认和自定义特征。提取方法的输出与转换和交互方法的输出不同,后者输出的是完全新的时间序列数据。当需要从时间序列数据中提取特定值时,可以使用此方法。

DeltaPy 库包含 34 种提取方法。编写提取的包装函数与包装转换函数相似。难点在于如何区分预测的有效性与表格增强之间的差异。此外,这些方法是组件,而不是完整的表格增强函数。

Pluto 不会解释每个函数,但以下是 DeltaPy 库中提取函数的列表:AmplitudeAveragesAutocorrelationCountCrossingsDensityDifferencingDerivativeDistanceDistributionEnergyEntropyExponentFixed PointsFluctuationFractalsInformationLinearityLocationModel CoefficientsNon-linearityOccurrencePeaksPercentileProbabilityQuantileRangeShapeSizeSpectral AnalysisStochasticityStreaksStructuralVolatility

提取方法是最后一个表格增强类别。因此,现在是时候做一个总结了。

总结

表格增强是一种通过增加使用的数据量来提高机器学习模型准确性的技术。它通过现有特征或来自其他来源的数据,向数据集添加列或行。它增加了可用的输入数据,使得模型能够做出更准确的预测。表格增强增加了当前数据集中未包含的新信息,增强了模型的实用性。当与其他机器学习技术(如深度学习)结合使用时,表格增强有助于提高预测模型的准确性和性能。

Pluto 从Kaggle网站下载了真实世界的银行欺诈和世界系列数据集。他在 Python Notebook 中编写了大部分代码,用于通过各种图表(如直方图、热图、相关图、华夫图和快乐图)可视化大型数据集。他之所以这样做,是因为在进行数据增强之前,理解数据集至关重要。然而,他并没有编写 CNN 或 RNN 模型来验证增强方法,因为构建 CNN 模型是一个复杂的过程,值得写成一本独立的书籍。

DeltaPy 开源库包含了数十种表格数据增强方法,但它是一个测试版,加载时可能不稳定。不过,Pluto 演示了一些表格数据增强技术,比如鲁棒缩放器、标准缩放器、截断、回归和操作符方法。

在本章中,有有趣的事实有趣的挑战。Pluto 希望你能够利用这些内容,将你的经验扩展到本书的范围之外。

这是本书的最后一章。你和 Pluto 已经涵盖了图像、文本、音频和表格数据的增强技术。随着人工智能和生成式人工智能继续扩展并融入我们的生活,数据将扮演着至关重要的角色。数据增强方法是扩展数据集的最佳实用选择,而不需要高成本地收集或购买额外的数据。此外,生成式人工智能正在改变我们的工作和娱乐方式,例如 OpenAI 的 GPT3、GPT4、Google Bard 和 Stability.ai 的 Stable Diffusion。你上个月在会议室或课堂上讨论的关于人工智能的内容可能会过时,但数据增强的概念和技术依然不变。

你和 Pluto 已经学会了使用包装函数编码数据增强技术,并从 Kaggle 网站下载真实世界的数据集。随着新的、更好、更快的增强库的出现,你可以将它们添加到你的工具集,或者更换背后的库。你实现的内容可能会略有变化,但你对数据增强的理解将保持不变。

我希望你和我一样,享受了阅读本书和操作 Python Notebook 的过程。谢谢你。

posted @ 2025-07-19 15:46  绝不原创的飞龙  阅读(7)  评论(0)    收藏  举报