音频分类
音频分类——与文本分类类似——根据输入数据输出一个类别标签。唯一的区别在于,输入不再是文本,而是原始音频波形。音频分类的一些实际应用包括识别说话者意图、语言分类,甚至通过声音识别动物物种。
本指南将向您展示如何:
要查看与此任务兼容的所有架构和检查点,我们建议查阅 任务页面
在开始之前,请确保已安装所有必要的库:
pip install transformers datasets evaluate soundfile librosa torchcodec
我们建议您登录 Hugging Face 账户,以便上传模型并与社区共享。当系统提示时,请输入您的令牌以完成登录:
>>> from huggingface_hub import notebook_login
>>> notebook_login()加载 MInDS-14 数据集
首先,从 🤗 Datasets 库中加载 MInDS-14 数据集:
>>> from datasets import load_dataset, Audio
>>> minds = load_dataset("PolyAI/minds14", name="en-US", split="train")使用 train_test_split 方法将数据集的 train 子集拆分为较小的训练集和测试集。这样可以在投入更多时间处理完整数据集之前,先进行实验并确认一切运行正常。
>>> minds = minds.train_test_split(test_size=0.2)然后查看数据集:
>>> minds
DatasetDict({
train: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 450
})
test: Dataset({
features: ['path', 'audio', 'transcription', 'english_transcription', 'intent_class', 'lang_id'],
num_rows: 113
})
})虽然数据集包含许多有用的信息,例如 lang_id 和 english_transcription,但本指南将重点关注 audio 和 intent_class。使用 remove_columns 方法删除其他列:
>>> minds = minds.remove_columns(["path", "transcription", "english_transcription", "lang_id"])以下是一个示例:
>>> minds["train"][0]
{'audio': {'array': array([ 0. , 0. , 0. , ..., -0.00048828,
-0.00024414, -0.00024414], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602b9a5fbb1e6d0fbce91f52.wav',
'sampling_rate': 8000},
'intent_class': 2}有两个字段:
audio:一维array,表示语音信号,必须调用以加载并重采样音频文件。intent_class:表示说话人意图的类别 ID。
为了让模型更容易根据标签 ID 获取标签名称,请创建一个字典,将标签名称映射为整数,反之亦然:
>>> labels = minds["train"].features["intent_class"].names
>>> label2id, id2label = dict(), dict()
>>> for i, label in enumerate(labels):
... label2id[label] = str(i)
... id2label[str(i)] = label现在,您可以将标签 ID 转换为标签名称:
>>> id2label[str(2)]
'app_error'预处理
下一步是加载 Wav2Vec2 特征提取器来处理音频信号:
>>> from transformers import AutoFeatureExtractor
>>> feature_extractor = AutoFeatureExtractor.from_pretrained("facebook/wav2vec2-base")MInDS-14 数据集的采样率为 8kHz(您可以在其 数据集卡片 中找到此信息),这意味着您需要将数据集重采样为 16kHz,才能使用预训练的 Wav2Vec2 模型:
>>> minds = minds.cast_column("audio", Audio(sampling_rate=16_000))
>>> minds["train"][0]
{'audio': {'array': array([ 2.2098757e-05, 4.6582241e-05, -2.2803260e-05, ...,
-2.8419291e-04, -2.3305941e-04, -1.1425107e-04], dtype=float32),
'path': '/root/.cache/huggingface/datasets/downloads/extracted/f14948e0e84be638dd7943ac36518a4cf3324e8b7aa331c5ab11541518e9368c/en-US~APP_ERROR/602b9a5fbb1e6d0fbce91f52.wav',
'sampling_rate': 16000},
'intent_class': 2}现在创建一个预处理函数,该函数:
- 调用
audio列进行加载,并在必要时对音频文件进行重采样。 - 检查音频文件的采样率是否与模型预训练所使用的音频数据的采样率一致。您可以在 Wav2Vec2 的 model card 中找到此信息。
- 设置最大输入长度,以便在不截断的情况下对较长的输入进行批处理。
>>> def preprocess_function(examples):
... audio_arrays = [x["array"] for x in examples["audio"]]
... inputs = feature_extractor(
... audio_arrays, sampling_rate=feature_extractor.sampling_rate, max_length=16000, truncation=True
... )
... return inputs要对整个数据集应用预处理函数,请使用 🤗 Datasets 的 map 函数。通过设置 batched=True 来一次处理数据集中的多个元素,可以加速 map。删除不必要的列,并将 intent_class 重命名为 label,以符合模型的要求:
>>> encoded_minds = minds.map(preprocess_function, remove_columns="audio", batched=True)
>>> encoded_minds = encoded_minds.rename_column("intent_class", "label")评估
在训练过程中加入评估指标通常有助于评估模型的性能。您可以使用 🤗 Evaluate 库快速加载评估方法。对于此任务,请加载 accuracy 指标(请参阅 🤗 Evaluate 的 快速入门 以了解如何加载和计算指标):
>>> import evaluate
>>> accuracy = evaluate.load("accuracy")然后创建一个函数,将你的预测值和标签传递给 compute 以计算准确率:
>>> import numpy as np
>>> def compute_metrics(eval_pred):
... predictions = np.argmax(eval_pred.predictions, axis=1)
... return accuracy.compute(predictions=predictions, references=eval_pred.label_ids)您的 compute_metrics 函数已准备就绪,在配置训练时您将再次用到它。
训练
现在可以开始训练模型了!使用 AutoModelForAudioClassification 加载 Wav2Vec2,并指定预期的标签数量以及标签映射:
>>> from transformers import AutoModelForAudioClassification, TrainingArguments, Trainer
>>> num_labels = len(id2label)
>>> model = AutoModelForAudioClassification.from_pretrained(
... "facebook/wav2vec2-base", num_labels=num_labels, label2id=label2id, id2label=id2label
... )此时,只剩下三个步骤:
- 在 TrainingArguments 中定义训练超参数。唯一必需的参数是
output_dir,用于指定模型的保存位置。通过设置push_to_hub=True,您可以将该模型推送到 Hub(上传模型需要登录 Hugging Face 账户)。在每个 epoch 结束时,Trainer 会评估准确率并保存训练检查点。 - 将训练参数与模型、数据集、分词器、数据整理器以及
compute_metrics函数一起传递给 Trainer。 - 调用 train() 来微调你的模型。
>>> training_args = TrainingArguments(
... output_dir="my_awesome_mind_model",
... eval_strategy="epoch",
... save_strategy="epoch",
... learning_rate=3e-5,
... per_device_train_batch_size=32,
... gradient_accumulation_steps=4,
... per_device_eval_batch_size=32,
... num_train_epochs=10,
... warmup_steps=0.1,
... logging_steps=10,
... load_best_model_at_end=True,
... metric_for_best_model="accuracy",
... push_to_hub=True,
... report_to="trackio",
... )
>>> trainer = Trainer(
... model=model,
... args=training_args,
... train_dataset=encoded_minds["train"],
... eval_dataset=encoded_minds["test"],
... processing_class=feature_extractor,
... compute_metrics=compute_metrics,
... )
>>> trainer.train()训练完成后,使用 push_to_hub() 方法将您的模型共享到 Hub,以便所有人都能使用您的模型:
>>> trainer.push_to_hub()如需了解如何针对音频分类任务微调模型的更详细示例,请参阅对应的 PyTorch notebook。
推理
很好,既然你已经完成了模型微调,现在就可以用它进行推理了!
加载用于推理的音频文件。如有必要,请记得将音频文件的采样率重采样,以匹配模型的采样率。
>>> from datasets import load_dataset, Audio
>>> dataset = load_dataset("PolyAI/minds14", name="en-US", split="train")
>>> dataset = dataset.cast_column("audio", Audio(sampling_rate=16000))
>>> sampling_rate = dataset.features["audio"].sampling_rate
>>> audio_file = dataset[0]["audio"]["path"]尝试使用微调后的模型进行推理的最简单方法是将其用于 pipeline()。使用你的模型实例化一个用于音频分类的 pipeline,并将你的音频文件传入:
>>> from transformers import pipeline
>>> classifier = pipeline("audio-classification", model="stevhliu/my_awesome_minds_model")
>>> classifier(audio_file)
[
{'score': 0.09766869246959686, 'label': 'cash_deposit'},
{'score': 0.07998877018690109, 'label': 'app_error'},
{'score': 0.0781070664525032, 'label': 'joint_account'},
{'score': 0.07667109370231628, 'label': 'pay_bill'},
{'score': 0.0755252093076706, 'label': 'balance'}
]您也可以手动复现 pipeline 的结果:
加载特征提取器以预处理音频文件,并将input作为 PyTorch 张量返回:
>>> from transformers import AutoFeatureExtractor
>>> feature_extractor = AutoFeatureExtractor.from_pretrained("stevhliu/my_awesome_minds_model")
>>> inputs = feature_extractor(dataset[0]["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")将输入传递给模型并返回 logits:
>>> from transformers import AutoModelForAudioClassification
>>> model = AutoModelForAudioClassification.from_pretrained("stevhliu/my_awesome_minds_model")
>>> with torch.no_grad():
... logits = model(**inputs).logits获取概率最高的类别,并使用模型的 id2label 映射将其转换为标签:
>>> import torch
>>> predicted_class_ids = torch.argmax(logits).item()
>>> predicted_label = model.config.id2label[predicted_class_ids]
>>> predicted_label
'cash_deposit'