transformers音频实战02-基于 Speech Commands 数据集的语音识别实战项目全流程

一、项目背景与目标

(一)背景

Speech Commands 数据集是语音识别领域经典的开源数据集,包含 35 个类别(如数字、指令词等)的短语音片段,适合用于基础语音识别模型的开发与验证。本项目基于该数据集,聚焦数字 0-9 的识别任务,搭建并训练语音识别模型,学习从数据准备到模型部署的完整流程。

(二)目标

  1. 实现 Speech Commands 数据集的自动下载与预处理,筛选出数字 0-9 的语音数据。
  2. 构建基于 CNN + LSTM 的混合语音识别模型,完成模型训练与评估。
  3. 借助 Gradio 搭建简单交互界面,实现语音识别功能的快速演示。

二、环境准备

(一)依赖库安装

torch安装

datasets默认使用torchcodec加载音频,请确保torch和python和torchcodec版本匹配。

我这里使用kaggle跑,默认kaggle使用torch2.6版本太低导致加载音频各种不兼容,为了兼容升级torch到2.8并且安装torchcodec=0.7

在终端执行以下命令,安装项目所需 Python 依赖库:

bash 复制代码
#这是cpu的版本
!pip uninstall -y torch torchvision torchaudio torchcodec
!pip install torch==2.8.0 torchvision torchaudio torchcodec==0.7  datasets matplotlib gradio 

如果是gpu可以到pytorch官网 首先查看gpu cuda版本:nvidia-smi,然后官网找到版本后的运行命令安装

我这里

复制代码
!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126

依赖说明:

  • torch:深度学习框架,用于模型构建与训练。
  • torchaudio:处理音频数据,提供特征提取等功能。
  • datasets:加载与处理 Hugging Face 数据集。
  • matplotlib:可视化数据分布、训练曲线等。
  • gradio:快速构建交互演示界面。

查看torchcodec下加载ffpmeg的so

复制代码
!ls /usr/local/lib/python3.11/dist-packages/torchcodec
_core			       libtorchcodec_custom_ops5.so
decoders		       libtorchcodec_custom_ops6.so
encoders		       libtorchcodec_custom_ops7.so
_frame.py		       libtorchcodec_pybind_ops4.so
__init__.py		       libtorchcodec_pybind_ops5.so
_internally_replaced_utils.py  libtorchcodec_pybind_ops6.so
libtorchcodec_core4.so	       libtorchcodec_pybind_ops7.so
libtorchcodec_core5.so	       __pycache__
libtorchcodec_core6.so	       _samplers
libtorchcodec_core7.so	       samplers
libtorchcodec_custom_ops4.so   version.py
安装ffmpeg

注意ffmpeg只支持4-7版本

使用conda安装

复制代码
 !curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba
!./bin/micromamba shell init -s bash --root-prefix ./micromamba
!./bin/micromamba install "ffmpeg<8" -c conda-forge -y
查看版本
! ffmpeg --version

使用apt安装

复制代码
 !apt update
!apt install ffmpeg -y
查看版本
! ffmpeg --version

诊断环境是否正常

复制代码
import os
import sys
import platform
import torch
import torch
print(torch.__config__.show())
print("=== PyTorch GPU 支持检查 ===")
print(f"PyTorch 版本: {torch.__version__}")
print(f"CUDA 可用: {torch.cuda.is_available()}")
print(f"CUDA 版本: {torch.version.cuda}")

if torch.cuda.is_available():
    print(f"GPU 设备数量: {torch.cuda.device_count()}")
    for i in range(torch.cuda.device_count()):
        print(f"GPU {i}: {torch.cuda.get_device_name(i)}")
else:
    print("✗ 没有可用的 CUDA GPU")
def deep_diagnosis():
    print("=== 深度诊断 ===")
    print(f"Python 版本: {sys.version}")
    print(f"平台: {platform.system()} {platform.release()}")
    print(f"os 模块文件: {os.__file__}")
    
    # 检查 os 模块的所有属性
    print(f"os 模块属性数量: {len(dir(os))}")
    
    # 检查特定于 Windows 的方法是否存在
    windows_specific = ['add_dll_directory', 'GetLongPathName', 'GetShortPathName']
    for method in windows_specific:
        exists = hasattr(os, method)
        print(f"os.{method}: {'✓' if exists else '✗'}")
    
    # 检查平台标识
    print(f"sys.platform: {sys.platform}")
    print(f"os.name: {os.name}")
    
    # 检查模块加载路径
    print(f"os 模块来自: {os.__spec__ if hasattr(os, '__spec__') else 'N/A'}")

deep_diagnosis()



import os
import sys

def setup_linux_library_path():
    """设置 Linux 库路径"""
    ffmpeg_bin_path = r"/usr/lib/x86_64-linux-gnu"
    # 找到 PyTorch 库路径
    try:
        import torch
        pytorch_lib_path = os.path.join(os.path.dirname(torch.__file__), 'lib')
        print(f"PyTorch 库路径: {pytorch_lib_path}")
        
        # 添加到 LD_LIBRARY_PATH
        current_ld_path = os.environ.get('LD_LIBRARY_PATH', '')
        if pytorch_lib_path not in current_ld_path:
            os.environ['LD_LIBRARY_PATH'] = pytorch_lib_path + os.pathsep + current_ld_path
            print("✓ 已设置 LD_LIBRARY_PATH")
        current_ld_path = os.environ.get('LD_LIBRARY_PATH', '')    
        os.environ['LD_LIBRARY_PATH'] = ffmpeg_bin_path + os.pathsep + current_ld_path    
    except ImportError:
        print("✗ 未找到 PyTorch")

# 应用设置
setup_linux_library_path()
print(os.environ['LD_LIBRARY_PATH'])
# 现在尝试加载你的库
import ctypes
try:
    lib = ctypes.CDLL('/usr/local/lib/python3.11/dist-packages/torchcodec/libtorchcodec_core4.so')
    print("✓ 库加载成功!")
except Exception as e:
    print(f"✗ 库加载失败: {e}")

(二)硬件要求

  • CPU 环境:普通 4 核及以上 CPU(如 i5 系列)可完成训练,训练 10 轮约 1 - 2 小时;若 CPU 性能较低(如 2 核),时间会相应增加。
  • GPU 环境(可选):支持 CUDA 的 NVIDIA GPU(如 GTX 1050 及以上)可加速训练,10 轮训练时间可缩短至 10 - 20 分钟,需额外安装对应 CUDA 版本的 PyTorch。

三、数据集处理

(一)数据集介绍

Speech Commands 数据集包含 train(训练集 )、validation(验证集 )、test(测试集 )三个划分,每个语音片段为 1 秒左右的单词语音,采样率 16000Hz,涵盖 35 个类别,本项目聚焦其中数字 0-9 的识别。

(二)数据集下载与加载

1. 数据集下载函数
python 复制代码
import os
import tarfile
import urllib.request
from datasets import load_dataset

# Speech Commands 官方下载 URL 模板
DL_URL = "https://s3.amazonaws.com/datasets.huggingface.co/SpeechCommands/{version}/{version}_{split}.tar.gz"
# 支持的版本
VERSIONS = ["v0.01", "v0.02"]

def download_and_extract(version="v0.02", data_dir="./speech_commands"):
    """自动下载并解压 Speech Commands 数据集"""
    os.makedirs(data_dir, exist_ok=True)
    splits = ["train", "validation", "test"]
    extracted_dirs = {}

    for split in splits:
        url = DL_URL.format(version=version, split=split)
        filename = os.path.join(data_dir, f"{version}_{split}.tar.gz")
        extract_dir = os.path.join(data_dir, f"{version}_{split}")

        if not os.path.exists(extract_dir):
            print(f"⬇️  Downloading {url} ...")
            urllib.request.urlretrieve(url, filename)

            print(f"📦 Extracting {filename} ...")
            with tarfile.open(filename, "r:gz") as tar:
                tar.extractall(extract_dir)

        extracted_dirs[split] = extract_dir

    return extracted_dirs

函数说明:

  • 根据 version(默认 v0.02 )和 data_dir(默认 ./speech_commands ),自动下载 trainvalidationtest 三个划分的数据集压缩包。
  • 检查本地是否已解压,未解压则先下载再用 tarfile 解压,返回各划分的解压目录。
2. 数据集加载函数
python 复制代码
def load_speech_commands(version="v0.02", data_dir="./speech_commands"):
    """返回 HuggingFace DatasetDict(train/validation/test)"""
    extracted_dirs = download_and_extract(version, data_dir)

    dataset = {
        split: load_dataset("audiofolder", data_dir=extracted_dirs[split], split="train")
        for split in extracted_dirs
    }
    return dataset

函数说明:利用 datasets 库的 load_dataset,以 audiofolder 方式加载各划分解压目录的音频数据,返回包含 trainvalidationtest 数据集的字典。

3. 主程序调用与数据集筛选
python 复制代码
if __name__ == "__main__":
    # 加载完整数据集
    dataset = load_speech_commands("v0.02")

    print("完整训练集信息:", dataset["train"])
    print("完整验证集信息:", dataset["validation"])
    print("完整测试集信息:", dataset["test"])

    # 只筛选数字 0-9 的类别
    digits = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
    digits_train = dataset["train"].filter(lambda x: x["label"] in digits)
    digits_validation = dataset["validation"].filter(lambda x: x["label"] in digits)
    digits_test = dataset["test"].filter(lambda x: x["label"] in digits)

    print("数字训练集信息:", digits_train)
    print("数字验证集信息:", digits_validation)
    print("数字测试集信息:", digits_test)

代码说明:

  • 先加载完整数据集,打印各划分基本信息。
  • 通过 filter 方法,依据 label 字段筛选出数字 0-9 对应的语音数据,构建数字识别专用数据集。

(三)数据预处理(特征提取)

1. 定义预处理函数
python 复制代码
import torch
import torchaudio.transforms as T

# 统一采样率
sample_rate = 16000  
# 定义梅尔频谱图转换器
mel_transform = T.MelSpectrogram(
    sample_rate=sample_rate,
    n_fft=1024,        
    n_mels=64,         
    hop_length=256     
)

def preprocess_function(examples):
    """
    预处理函数:将音频转换为梅尔频谱图并标准化
    参数:
        examples: 数据集样本,包含音频数据等字段
    返回:
        处理后的梅尔频谱图(mel)和标签(labels)
    """
    # 提取音频张量,若数据集音频存储格式不同,需调整获取方式
    wavs = [torch.tensor(wav["array"], dtype=torch.float32) for wav in examples["audio"]]  

    # 统一采样率(若原始采样率不同,需更完善处理,这里假设原始为 16000Hz 简单示例)
    resampler = T.Resample(sample_rate, sample_rate)  
    wavs = [resampler(wav) for wav in wavs]

    # 提取梅尔频谱图,增加通道维度
    mels = [mel_transform(wav).unsqueeze(0) for wav in wavs]  

    # 标准化:计算整体均值和标准差
    mel_cat = torch.cat(mels)
    mel_mean = torch.mean(mel_cat)
    mel_std = torch.std(mel_cat)
    mels = [(mel - mel_mean) / mel_std for mel in mels]

    return {"mel": mels, "labels": examples["label"]}

函数说明:

  • 从数据集中提取音频张量,统一采样率(实际需根据原始数据调整,这里简化处理 )。
  • 利用 MelSpectrogram 将音频转换为梅尔频谱图,增加通道维度适配模型输入。
  • 对频谱图进行标准化,提升模型训练稳定性。
2. 应用预处理
python 复制代码
# 对数字数据集应用预处理
digits_train = digits_train.map(
    preprocess_function,
    batched=True,
    batch_size=32,
    remove_columns=digits_train.column_names  
)
digits_validation = digits_validation.map(
    preprocess_function,
    batched=True,
    batch_size=32,
    remove_columns=digits_validation.column_names
)
digits_test = digits_test.map(
    preprocess_function,
    batched=True,
    batch_size=32,
    remove_columns=digits_test.column_names
)

# 转换为 PyTorch 张量格式
digits_train.set_format("torch", columns=["mel", "labels"])
digits_validation.set_format("torch", columns=["mel", "labels"])
digits_test.set_format("torch", columns=["mel", "labels"])

代码说明:

  • 以批次方式(batch_size=32 )对数字数据集各划分应用预处理,移除原始无关字段。
  • 将处理后数据集转换为 PyTorch 张量格式,方便后续模型训练。

四、模型构建

(一)模型架构选择(CNN + LSTM 混合模型)

python 复制代码
import torch.nn as nn

class SpeechRecognitionModel(nn.Module):
    def __init__(self, num_classes=10):
        """
        初始化模型
        参数:
            num_classes: 分类数量,数字 0-9 共 10 类
        """
        super().__init__()
        # 1. 卷积层:提取局部频率特征
        self.cnn = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=(2, 2)),  
            nn.Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=(2, 2))   
        )
        # 2. LSTM 层:处理时间序列特征
        self.lstm = nn.LSTM(
            input_size=64 * 16,  
            hidden_size=128,    
            num_layers=2,       
            batch_first=True    
        )
        # 3. 分类头:输出分类概率
        self.fc = nn.Linear(128, num_classes)
    
    def forward(self, x):
        """
        前向传播
        参数:
            x: 输入的梅尔频谱图,形状 [batch, 1, 64, time]
        返回:
            分类预测结果
        """
        # CNN 处理
        x = self.cnn(x)  
        batch_size, channels, freq, time = x.shape
        # 调整形状适配 LSTM 输入:[batch, time, channels×freq]
        x = x.permute(0, 3, 1, 2).reshape(batch_size, time, channels * freq)
        # LSTM 处理
        x, _ = self.lstm(x)  
        # 取最后一个时间步特征
        x = x[:, -1, :]  
        # 分类输出
        logits = self.fc(x)  
        return logits

# 初始化模型,数字识别共 10 类
model = SpeechRecognitionModel(num_classes=10)

模型说明:

  • CNN 部分:通过两层卷积提取音频频谱的局部特征,池化层压缩维度,减少计算量。
  • LSTM 部分:处理 CNN 输出的时间序列特征,捕捉语音的时序依赖关系。
  • 分类头:将 LSTM 输出映射到 10 个数字类别的预测概率。

这个语音识别模型使用LSTM是非常关键且合理的设计,主要原因如下:

  1. 语音数据的时序特性

    语音是时间序列数据:音频信号本质上是随时间变化的连续信号

  2. 前后依赖关系:一个音素的识别依赖于前面的音素和后面的音素

  3. 上下文信息:数字发音中,各个部分之间存在强关联

五、模型训练与评估

(一)训练参数设置

python 复制代码
# 训练参数
batch_size = 32  
lr = 1e-3  # 学习率
epochs = 10  # 训练轮数

# 数据加载器
train_loader = torch.utils.data.DataLoader(digits_train, batch_size=batch_size, shuffle=True)
validation_loader = torch.utils.data.DataLoader(digits_validation, batch_size=batch_size)
test_loader = torch.utils.data.DataLoader(digits_test, batch_size=batch_size)

# 损失函数(交叉熵,适合分类任务)
criterion = nn.CrossEntropyLoss()
# 优化器(Adam,自适应调整学习率)
optimizer = optim.Adam(model.parameters(), lr=lr)

# 设备设置,自动检测 GPU/CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

(二)训练循环

python 复制代码
import torch.optim as optim

for epoch in range(epochs):
    # 训练模式:启用 dropout、批量归一化等训练专属行为
    model.train()  
    train_loss = 0.0
    for batch in train_loader:
        # 加载数据到设备(GPU/CPU)
        mels = batch["mel"].to(device)  
        labels = batch["labels"].to(device)
        
        # 梯度清零
        optimizer.zero_grad()  
        # 前向传播
        outputs = model(mels)  
        # 计算损失
        loss = criterion(outputs, labels)  
        # 反向传播计算梯度
        loss.backward()  
        # 更新模型参数
        optimizer.step()  

        train_loss += loss.item() * mels.size(0)

    # 计算训练集平均损失
    train_loss /= len(train_loader.dataset)

    # 验证集评估:切换为评估模式,关闭 dropout 等
    model.eval()  
    validation_loss = 0.0
    correct = 0
    with torch.no_grad():  
        for batch in validation_loader:
            mels = batch["mel"].to(device)
            labels = batch["labels"].to(device)
            outputs = model(mels)
            loss = criterion(outputs, labels)
            validation_loss += loss.item() * mels.size(0)
            
            # 取预测类别
            _, preds = torch.max(outputs, 1)  
            correct += torch.sum(preds == labels.data)

    validation_loss /= len(validation_loader.dataset)
    validation_acc = correct.double() / len(validation_loader.dataset)

    # 打印训练轮次日志
    print(f"Epoch {epoch+1}/{epochs}")
    print(f"Train Loss: {train_loss:.4f} | Validation Loss: {validation_loss:.4f} | Validation Acc: {validation_acc:.4f}")

流程说明:

  • 训练阶段:迭代训练集,计算损失、反向传播更新模型参数,累计训练损失。
  • 验证阶段:切换模型为评估模式,关闭梯度计算,计算验证集损失与准确率,评估模型泛化能力。

(三)测试集评估

python 复制代码
# 测试集评估
model.eval()
test_loss = 0.0
correct = 0
with torch.no_grad():
    for batch in test_loader:
        mels = batch["mel"].to(device)
        labels = batch["labels"].to(device)
        outputs = model(mels)
        loss = criterion(outputs, labels)
        test_loss += loss.item() * mels.size(0)
        
        _, preds = torch.max(outputs, 1)
        correct += torch.sum(preds == labels.data)

test_loss /= len(test_loader.dataset)
test_acc = correct.double() / len(test_loader.dataset)
print(f"测试集结果:Loss={test_loss:.4f}, Acc={test_acc:.4f}")

说明:在测试集上执行与验证集类似的评估流程,得到模型最终的泛化性能指标(损失与准确率 )。

六、模型部署与演示(Gradio 交互界面)

(一)保存模型(可选)

python 复制代码
# 保存训练好的模型
torch.save(model.state_dict(), "speech_recognition_model.pth")

(二)构建交互界面

python 复制代码
import gradio as gr

# 加载模型(若之前保存过,可直接加载;也可使用训练好的模型实例)
# model.load_state_dict(torch.load("speech_recognition_model.pth", map_location=device))
model.eval()

def recognize_speech(audio):
    """
    语音识别函数,对接 Gradio 界面
    参数:
        audio: Gradio 传入的音频数据,格式为 (采样率, 波形数组)
    返回:
        识别结果文本
    """
    if audio is None:
        return "请录制或上传语音"
    sr, wav = audio
    wav = torch.tensor(wav, dtype=torch.float32)

    # 预处理(与训练时一致)
    resampler = T.Resample(sr, sample_rate)
    wav = resampler(wav)
    mel = mel_transform(wav).unsqueeze(0).unsqueeze(0)  # 增加批次和通道维度
    # 注意:需使用训练时的均值和标准差,这里需提前保存并加载,示例简化处理
    mel_mean = torch.mean(torch.cat([batch["mel"] for batch in train_loader]))  
    mel_std = torch.std(torch.cat([batch["mel"] for batch in train_loader]))    
    mel

七、数据集大小、训练时长、GPU 需求

(一)、数据集大小(以 Speech Commands v0.02 为例)

1. 原始数据规模
  • 总样本量 :约 10 万条语音(v0.02 版本含 35 个类别,每个类别约几千条)

  • 单条语音 :1 秒时长,采样率 16000Hz → 单条音频大小约 16000 * 2 bytes = 32KB(PCM 16 位编码)

  • 总容量:plaintext

    10万条 * 32KB ≈ 3.2GB(未压缩)
    实际下载为 tar.gz 压缩包,解压后约 2GB 左右

2. 数字子集(0-9)规模
  • 样本量 :每个数字约 4000-5000 条 → 总约 4-5 万条
  • 容量 :约 4万 * 32KB ≈ 1.28GB(解压后)

(二)、训练时长估算

训练时长受 模型复杂度batch sizeGPU 性能 影响极大,以下分场景对比:

1. 模型复杂度(以你的 CNN+LSTM 为例)
  • 参数量 :约 100 万参数(轻量级模型,适合入门)
  • 计算量:每轮训练需处理约 5 万条样本(数字子集),属于低计算量任务
2. 不同 GPU 训练时长(数字子集,10 轮)
GPU 型号 典型场景 单轮时长 10 轮总时长 显存需求
无 GPU(纯 CPU) 4 核笔记本 CPU 30-60 分钟 5-10 小时 ---
NVIDIA GTX 1060 入门游戏显卡 3-5 分钟 30-50 分钟 2-3GB
NVIDIA RTX 3060 中端显卡 1-2 分钟 10-20 分钟 3-4GB
NVIDIA A100 数据中心显卡 10-20 秒 2-3 分钟 5-6GB
关键影响因素
  • batch size :越大越快,但受显存限制(你的代码用 batch_size=32,很保守)
  • 数据增强:若添加音频加噪、变速等,时长会增加 20%-50%
  • 模型深度:若换成 Wav2Vec 等大模型,时长会飙升 10 倍以上

(三)、GPU 需求与选型建议

1. 最低需求:无需 GPU
  • 纯 CPU 可跑:你的轻量级模型 + 小 batch size(32),4 核 CPU 能跑通(只是慢)
  • 适合场景:仅想验证流程、样本量极小(<1 万条)
2. 推荐 GPU:千元级显卡足够
  • 性价比之选 :GTX 1060 / RTX 3050(2000 元以内二手卡)
    • 显存 6GB,能轻松容纳 batch_size=128(比 32 快 3 倍)
    • 10 轮训练仅需 30 分钟,适合个人学习
3. 企业级需求:按需扩容
  • 大模型 / 大数据:A100(40GB 显存)或多卡集群
  • 但你的场景不需要:数字识别任务简单,千元卡足够

(四)、完整训练成本总结

需求类型 硬件建议 训练时长(10 轮) 成本(硬件 / 云 GPU)
纯体验(能跑通) 4 核 CPU 5-10 小时 0(已有电脑)
快速验证 GTX 1060(二手) 30-50 分钟 1500 元(显卡)
极致效率 RTX 3060 10-20 分钟 3000 元(显卡)/ 10 元(云 GPU 按次)
相关推荐
爱思德学术5 小时前
中国计算机学会(CCF)推荐学术会议-B(计算机网络):SenSys 2026
人工智能·计算机网络·嵌入式·传感系统
a1111111111ss5 小时前
添加最新的LSKNet遥感目标检测网络主干
人工智能·目标检测·计算机视觉
relis5 小时前
llama.cpp Flash Attention 论文与实现深度对比分析
人工智能·深度学习
盼小辉丶5 小时前
Transformer实战(21)——文本表示(Text Representation)
人工智能·深度学习·自然语言处理·transformer
艾醒(AiXing-w)5 小时前
大模型面试题剖析:模型微调中冷启动与热启动的概念、阶段与实例解析
人工智能·深度学习·算法·语言模型·自然语言处理
_张一凡6 小时前
OpenAI Sora 2提示词指南:打造精准视频生成指令
aigc·音视频
科技小E6 小时前
流媒体视频技术在明厨亮灶场景中的深度应用
人工智能
geneculture6 小时前
融智学院十大学部知识架构示范样板
人工智能·数据挖掘·信息科学·哲学与科学统一性·信息融智学
无风听海6 小时前
神经网络之交叉熵与 Softmax 的梯度计算
人工智能·深度学习·神经网络