logo

从零开始:Python语音识别实战(附完整代码)

作者:狼烟四起2025.10.12 07:51浏览量:26

简介:本文通过Python实现语音识别系统,详细讲解音频处理、特征提取、模型训练全流程,提供可复用的代码与优化方案。

Python语音识别实战:从理论到代码实现

语音识别技术作为人机交互的核心环节,已广泛应用于智能客服、语音助手、实时翻译等领域。本文将通过Python实现一个完整的语音识别系统,涵盖音频采集、预处理、特征提取、模型训练与解码的全流程,并提供可复用的代码框架。

一、语音识别技术基础

1.1 语音识别原理

语音识别系统主要由前端处理和后端解码两部分构成:

  • 前端处理:包括音频采集、预加重、分帧、加窗、特征提取(MFCC/FBANK)
  • 后端解码:基于声学模型、语言模型和发音词典的联合解码

现代语音识别系统多采用端到端架构(如Transformer),但传统混合系统(DNN-HMM)仍是理解技术原理的重要基础。

1.2 Python生态工具链

Python在语音处理领域拥有完善的工具链:

二、实战环境搭建

2.1 基础环境配置

  1. # 创建虚拟环境
  2. python -m venv asr_env
  3. source asr_env/bin/activate # Linux/Mac
  4. asr_env\Scripts\activate # Windows
  5. # 安装基础依赖
  6. pip install numpy scipy matplotlib librosa python_speech_features

2.2 深度学习框架选择

推荐使用PyTorch实现端到端模型:

  1. import torch
  2. print(torch.__version__) # 验证安装

三、音频处理实战

3.1 音频采集与存储

使用sounddevice库实现实时录音:

  1. import sounddevice as sd
  2. import numpy as np
  3. def record_audio(duration=5, fs=16000):
  4. print("开始录音...")
  5. recording = sd.rec(int(duration * fs), samplerate=fs, channels=1, dtype='float32')
  6. sd.wait() # 等待录音完成
  7. return recording.flatten()
  8. # 保存为WAV文件
  9. from scipy.io.wavfile import write
  10. def save_wav(data, fs, filename):
  11. scaled = np.int16(data * 32767)
  12. write(filename, fs, scaled)
  13. # 使用示例
  14. audio_data = record_audio()
  15. save_wav(audio_data, 16000, "test.wav")

3.2 预处理关键步骤

  1. import librosa
  2. def preprocess_audio(file_path):
  3. # 加载音频
  4. y, sr = librosa.load(file_path, sr=16000)
  5. # 预加重(提升高频)
  6. y = librosa.effects.preemphasis(y)
  7. # 分帧加窗(帧长25ms,步长10ms)
  8. frame_length = int(0.025 * sr)
  9. hop_length = int(0.01 * sr)
  10. frames = librosa.util.frame(y, frame_length=frame_length, hop_length=hop_length)
  11. # 汉明窗
  12. window = np.hamming(frame_length)
  13. windowed_frames = frames * window
  14. return windowed_frames, sr

四、特征提取实现

4.1 MFCC特征提取

  1. import python_speech_features as psf
  2. def extract_mfcc(audio_path, nfft=512, winlen=0.025, winstep=0.01):
  3. (rate, sig) = librosa.load(audio_path, sr=16000)
  4. mfcc = psf.mfcc(
  5. sig,
  6. samplerate=rate,
  7. winlen=winlen,
  8. winstep=winstep,
  9. numcep=13,
  10. nfilt=26,
  11. nfft=nfft,
  12. preemph=0.97,
  13. ceplifter=22,
  14. appendEnergy=False
  15. )
  16. # 添加动态特征(一阶二阶差分)
  17. mfcc_delta = psf.delta(mfcc, 2)
  18. mfcc_delta2 = psf.delta(mfcc_delta, 2)
  19. features = np.concatenate([mfcc, mfcc_delta, mfcc_delta2], axis=1)
  20. return features
  21. # 使用示例
  22. features = extract_mfcc("test.wav")
  23. print(f"提取特征维度:{features.shape}")

4.2 FBANK特征提取

  1. def extract_fbank(audio_path):
  2. y, sr = librosa.load(audio_path, sr=16000)
  3. # 计算功率谱
  4. stft = librosa.stft(y, n_fft=512, hop_length=160)
  5. power_spec = np.abs(stft) ** 2
  6. # 梅尔滤波器组
  7. n_mels = 40
  8. mel_basis = librosa.filters.mel(sr=sr, n_fft=512, n_mels=n_mels)
  9. fbank = np.dot(mel_basis, power_spec)
  10. # 对数变换
  11. fbank = np.log1p(fbank)
  12. return fbank.T # 转置为(时间帧, 特征维)

五、端到端模型实现

5.1 简单CTC模型架构

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class SimpleASR(nn.Module):
  4. def __init__(self, input_dim, num_classes):
  5. super().__init__()
  6. self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)
  7. self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
  8. self.rnn = nn.LSTM(64*40, 256, bidirectional=True, batch_first=True)
  9. self.fc = nn.Linear(512, num_classes)
  10. def forward(self, x):
  11. # x: (batch, 1, n_frames, n_mels)
  12. x = F.relu(self.conv1(x))
  13. x = F.relu(self.conv2(x))
  14. # 调整维度 (batch, n_frames, 64*40)
  15. x = x.permute(0, 2, 1, 3).contiguous()
  16. x = x.view(x.size(0), x.size(1), -1)
  17. # RNN处理
  18. x, _ = self.rnn(x)
  19. # 输出层
  20. x = self.fc(x)
  21. return x
  22. # 模型参数
  23. input_dim = 40 # FBANK特征维数
  24. num_classes = 28 + 1 # 26字母+空格+CTC空白符
  25. model = SimpleASR(input_dim, num_classes)
  26. print(model)

5.2 数据准备与训练

  1. from torch.utils.data import Dataset, DataLoader
  2. class AudioDataset(Dataset):
  3. def __init__(self, features, labels):
  4. self.features = features
  5. self.labels = labels
  6. def __len__(self):
  7. return len(self.features)
  8. def __getitem__(self, idx):
  9. # 添加通道维度 (1, n_frames, n_mels)
  10. feature = self.features[idx].T[np.newaxis, :, :]
  11. label = self.labels[idx]
  12. return torch.FloatTensor(feature), torch.LongTensor(label)
  13. # 假设已有features和labels
  14. # dataset = AudioDataset(features, labels)
  15. # dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
  16. # 简单训练循环示例
  17. def train_model(model, dataloader, epochs=10):
  18. criterion = nn.CTCLoss()
  19. optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
  20. for epoch in range(epochs):
  21. for inputs, targets in dataloader:
  22. optimizer.zero_grad()
  23. # 前向传播
  24. outputs = model(inputs) # (batch, seq_len, num_classes)
  25. # 准备CTC输入
  26. input_lengths = torch.full((inputs.size(0),), outputs.size(1), dtype=torch.long)
  27. target_lengths = torch.tensor([len(t) for t in targets], dtype=torch.long)
  28. # 计算损失
  29. loss = criterion(outputs.log_softmax(2), targets, input_lengths, target_lengths)
  30. # 反向传播
  31. loss.backward()
  32. optimizer.step()
  33. print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")

六、解码与评估

6.1 贪心解码实现

  1. def greedy_decode(logits):
  2. # logits: (n_frames, num_classes)
  3. max_indices = np.argmax(logits, axis=1)
  4. # 移除重复和空白符
  5. decoded = []
  6. prev = None
  7. for idx in max_indices:
  8. if idx != 0 and idx != prev: # 0是CTC空白符
  9. decoded.append(idx)
  10. prev = idx
  11. return decoded
  12. # 示例使用
  13. # logits = model(input_tensor).detach().numpy()
  14. # decoded = greedy_decode(logits[-1]) # 取最后一个时间步

6.2 词错误率计算

  1. def calculate_wer(ref, hyp):
  2. # 使用动态规划计算编辑距离
  3. d = np.zeros((len(ref)+1, len(hyp)+1), dtype=np.int32)
  4. for i in range(len(ref)+1):
  5. d[i, 0] = i
  6. for j in range(len(hyp)+1):
  7. d[0, j] = j
  8. for i in range(1, len(ref)+1):
  9. for j in range(1, len(hyp)+1):
  10. if ref[i-1] == hyp[j-1]:
  11. d[i,j] = d[i-1,j-1]
  12. else:
  13. substitution = d[i-1,j-1] + 1
  14. insertion = d[i,j-1] + 1
  15. deletion = d[i-1,j] + 1
  16. d[i,j] = min(substitution, insertion, deletion)
  17. wer = d[len(ref), len(hyp)] / len(ref)
  18. return wer

七、实战优化建议

  1. 数据增强

    • 添加背景噪声
    • 速度扰动(±20%)
    • 音量调整(±6dB)
  2. 模型优化

    • 使用更深的CNN架构(如ResNet)
    • 添加注意力机制
    • 采用Transformer架构
  3. 解码优化

    • 实现束搜索(Beam Search)
    • 集成语言模型(N-gram或神经语言模型)
    • 使用WFST进行图解码

八、完整项目结构建议

  1. asr_project/
  2. ├── data/ # 音频数据
  3. ├── train/
  4. └── test/
  5. ├── features/ # 提取的特征
  6. ├── models/ # 训练好的模型
  7. ├── utils/
  8. ├── audio_processing.py
  9. ├── features.py
  10. └── decoder.py
  11. ├── train.py # 训练脚本
  12. ├── decode.py # 解码脚本
  13. └── requirements.txt # 依赖文件

九、总结与展望

本文实现了从音频采集到语音识别的完整流程,涵盖了传统特征提取方法和端到端建模技术。实际项目中,建议:

  1. 使用专业语音数据集(如LibriSpeech)
  2. 采用更先进的模型架构(如Conformer)
  3. 实现分布式训练和模型压缩
  4. 部署为Web服务或移动端应用

后续文章将深入讲解:

  • 语音识别中的语言模型集成
  • 基于Transformer的端到端模型实现
  • 模型压缩与加速技术
  • 实时语音识别系统实现

通过系统学习和实践,读者可以逐步掌握工业级语音识别系统的开发能力。

相关文章推荐

发表评论

活动