音频课程文档

音频数据集预处理

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

音频数据集预处理

使用 🤗 Datasets 加载数据集只是乐趣的一半。如果您计划将其用于训练模型或运行推理,您首先需要预处理数据。一般来说,这将涉及以下步骤

  • 重采样音频数据
  • 过滤数据集
  • 将音频数据转换为模型期望的输入

重采样音频数据

load_dataset 函数下载音频示例时,使用的是它们发布的采样率。但这并不总是您计划训练或用于推理的模型的预期采样率。如果采样率之间存在差异,您可以将音频重采样到模型的预期采样率。

大多数可用的预训练模型都是在采样率为 16 kHz 的音频数据集上预训练的。当我们探索 MINDS-14 数据集时,您可能已经注意到它的采样率为 8 kHz,这意味着我们可能需要对其进行上采样。

要做到这一点,请使用 🤗 Datasets 的 cast_column 方法。此操作不会就地更改音频,而是向数据集发出信号,以便在加载音频示例时动态地对其进行重采样。以下代码将采样率设置为 16kHz

from datasets import Audio

minds = minds.cast_column("audio", Audio(sampling_rate=16_000))

重新加载 MINDS-14 数据集中的第一个音频示例,并检查它是否已重采样到所需的 sampling rate

minds[0]

输出

{
    "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
    "audio": {
        "path": "/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-AU~PAY_BILL/response_4.wav",
        "array": array(
            [
                2.0634243e-05,
                1.9437837e-04,
                2.2419340e-04,
                ...,
                9.3852862e-04,
                1.1302452e-03,
                7.1531429e-04,
            ],
            dtype=float32,
        ),
        "sampling_rate": 16000,
    },
    "transcription": "I would like to pay my electricity bill using my card can you please assist",
    "intent_class": 13,
}

您可能会注意到,数组值现在也不同了。这是因为我们现在获得的每个振幅值是之前的两倍。

💡 关于重采样的背景知识:如果音频信号以 8 kHz 采样,使其每秒有 8000 个采样读数,我们知道音频不包含任何高于 4 kHz 的频率。这由奈奎斯特采样定理保证。因此,我们可以确定在采样点之间,原始连续信号始终形成平滑曲线。然后,上采样到更高的采样率就是计算额外的采样值,这些值通过逼近该曲线插入到现有值之间。然而,下采样需要我们首先滤除任何高于新奈奎斯特极限的频率,然后再估计新的采样点。换句话说,您不能通过简单地丢弃每隔一个样本来按 2 倍因子进行下采样——这会在信号中产生称为混叠的失真。正确地进行重采样是棘手的,最好留给经过良好测试的库,例如 librosa 或 🤗 Datasets。

过滤数据集

您可能需要根据某些标准过滤数据。一种常见的情况是将音频示例限制在特定持续时间内。例如,我们可能想要过滤掉任何超过 20 秒的示例,以防止在训练模型时出现内存不足错误。

我们可以通过使用 🤗 Datasets 的 filter 方法并向其传递一个带有过滤逻辑的函数来做到这一点。让我们首先编写一个函数,指示要保留哪些示例以及要丢弃哪些示例。此函数 is_audio_length_in_range,如果样本短于 20 秒,则返回 True,如果样本长于 20 秒,则返回 False

MAX_DURATION_IN_SECONDS = 20.0


def is_audio_length_in_range(input_length):
    return input_length < MAX_DURATION_IN_SECONDS

过滤函数可以应用于数据集的列,但我们在此数据集中没有包含音轨持续时间的列。但是,我们可以创建一个列,根据该列中的值进行过滤,然后将其删除。

# use librosa to get example's duration from the audio file
new_column = [librosa.get_duration(path=x) for x in minds["path"]]
minds = minds.add_column("duration", new_column)

# use 🤗 Datasets' `filter` method to apply the filtering function
minds = minds.filter(is_audio_length_in_range, input_columns=["duration"])

# remove the temporary helper column
minds = minds.remove_columns(["duration"])
minds

输出

Dataset({features: ["path", "audio", "transcription", "intent_class"], num_rows: 624})

我们可以验证数据集已从 654 个示例过滤到 624 个。

预处理音频数据

处理音频数据集最具挑战性的方面之一是以正确的格式准备数据以进行模型训练。正如您所看到的,原始音频数据以采样值数组的形式出现。但是,预训练模型,无论您是使用它们进行推理,还是想针对您的任务对其进行微调,都希望原始数据被转换为输入特征。输入特征的要求可能因模型而异——它们取决于模型的架构以及预训练所用的数据。好消息是,对于每个受支持的音频模型,🤗 Transformers 都提供了一个特征提取器类,可以将原始音频数据转换为模型期望的输入特征。

那么,特征提取器对原始音频数据做了什么呢?让我们看一下 Whisper 的特征提取器,以了解一些常见的特征提取转换。Whisper 是由 OpenAI 的 Alec Radford 等人在 2022 年 9 月发布的用于自动语音识别 (ASR) 的预训练模型。

首先,Whisper 特征提取器会填充/截断一批音频示例,以使所有示例的输入长度为 30 秒。短于此长度的示例会填充到 30 秒,方法是在序列末尾附加零(音频信号中的零对应于无信号或静音)。长于 30 秒的示例会被截断为 30 秒。由于批次中的所有元素都在输入空间中填充/截断为最大长度,因此不需要注意力掩码。Whisper 在这方面是独一无二的,大多数其他音频模型都需要注意力掩码,详细说明序列在何处被填充,以及在自注意力机制中应忽略的位置。Whisper 经过训练,无需注意力掩码即可运行,并直接从语音信号中推断出应忽略输入的位置。

Whisper 特征提取器执行的第二个操作是将填充的音频数组转换为对数梅尔频谱图。正如您所回忆的那样,这些频谱图描述了信号的频率如何随时间变化,以梅尔刻度表示,并以分贝(对数部分)测量,以使频率和幅度更能代表人类听觉。

所有这些转换都可以通过几行代码应用于您的原始音频数据。让我们继续从预训练的 Whisper 检查点加载特征提取器,以便为我们的音频数据做好准备

from transformers import WhisperFeatureExtractor

feature_extractor = WhisperFeatureExtractor.from_pretrained("openai/whisper-small")

接下来,您可以编写一个函数,通过将单个音频示例传递给 feature_extractor 来预处理它。

def prepare_dataset(example):
    audio = example["audio"]
    features = feature_extractor(
        audio["array"], sampling_rate=audio["sampling_rate"], padding=True
    )
    return features

我们可以使用 🤗 Datasets 的 map 方法将数据准备函数应用于我们所有的训练示例

minds = minds.map(prepare_dataset)
minds

输出

Dataset(
    {
        features: ["path", "audio", "transcription", "intent_class", "input_features"],
        num_rows: 624,
    }
)

就这么简单,我们现在在数据集中有了作为 input_features 的对数梅尔频谱图。

让我们为 minds 数据集中的一个示例可视化它

import numpy as np

example = minds[0]
input_features = example["input_features"]

plt.figure().set_figwidth(12)
librosa.display.specshow(
    np.asarray(input_features[0]),
    x_axis="time",
    y_axis="mel",
    sr=feature_extractor.sampling_rate,
    hop_length=feature_extractor.hop_length,
)
plt.colorbar()
Log mel spectrogram plot

现在您可以看到预处理后 Whisper 模型的音频输入是什么样子。

模型的特征提取器类负责将原始音频数据转换为模型期望的格式。但是,许多涉及音频的任务是多模态的,例如语音识别。在这种情况下,🤗 Transformers 还提供特定于模型的 tokenizer 来处理文本输入。有关 tokenizer 的深入了解,请参阅我们的 NLP 课程

您可以分别加载 Whisper 和其他多模态模型的特征提取器和 tokenizer,也可以通过所谓的 processor 加载两者。为了使事情更简单,请使用 AutoProcessor 从检查点加载模型的特征提取器和 processor,就像这样

from transformers import AutoProcessor

processor = AutoProcessor.from_pretrained("openai/whisper-small")

在这里,我们说明了基本的数据准备步骤。当然,自定义数据可能需要更复杂的预处理。在这种情况下,您可以扩展函数 prepare_dataset 以执行任何类型的自定义数据转换。使用 🤗 Datasets,如果您可以将其编写为 Python 函数,则可以 将其应用 于您的数据集!

< > 更新 在 GitHub 上