Python-数据扩充-三-

102 阅读50分钟

Python 数据扩充(三)

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

译者:飞龙

协议:CC BY-NC-SA 4.0

第七章:音频数据增强

与图像和文本增强类似,音频数据增强的目标是扩展数据集,从而在生成 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 的过程。谢谢你。