传统语音识别系统流程:从声波到文本的全链路技术
一、信号预处理:构建语音识别的数据基石
语音识别系统的输入是原始声波信号,其质量直接影响后续模块的性能。预处理阶段的核心目标是消除噪声干扰、标准化信号格式,为特征提取提供可靠数据源。
1.1 采样与量化
原始语音信号为连续模拟信号,需通过ADC(模数转换器)进行采样和量化。典型采样率为8kHz(电话语音)或16kHz(通用语音识别),量化精度通常为16位(65536级幅度)。例如,在Linux环境下使用sox工具进行采样:
sox input.wav -r 16000 -b 16 output.wav
此操作将输入文件转换为16kHz采样率、16位量化的WAV格式,符合大多数传统系统的输入要求。
1.2 预加重与分帧
高频信号在传输中衰减更快,预加重通过一阶高通滤波器(如系数0.95)提升高频分量:
import numpy as npdef pre_emphasis(signal, coeff=0.95):return np.append(signal[0], signal[1:] - coeff * signal[:-1])
分帧将连续信号切割为20-30ms的短时帧(典型帧长25ms,帧移10ms),每帧约400个采样点(16kHz采样率下)。分帧后需加窗(如汉明窗)减少频谱泄漏:
def hamming_window(frame_length):return 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(frame_length) / (frame_length - 1))
1.3 端点检测(VAD)
通过能量和过零率判断语音起止点。双门限法示例:
def vad_double_threshold(frame_energy, zcr, energy_low=0.3, energy_high=0.6, zcr_thresh=0.1):speech_flag = Falsesegments = []for e, z in zip(frame_energy, zcr):if e > energy_high and z < zcr_thresh:if not speech_flag:segments.append(('start', len(segments)))speech_flag = Trueelif e < energy_low or z > zcr_thresh:if speech_flag:segments.append(('end', len(segments)-1))speech_flag = Falsereturn segments
此算法可有效剔除静音段,减少计算量。
二、特征提取:从时域到频域的降维映射
特征提取将原始信号转换为机器学习模型可处理的向量序列。梅尔频率倒谱系数(MFCC)是传统系统的主流选择。
2.1 傅里叶变换
对每帧信号进行FFT(快速傅里叶变换),获取频域表示:
def compute_fft(frame):return np.abs(np.fft.rfft(frame, n=512))[:257] # 取前257点(0-Nyquist频率)
2.2 梅尔滤波器组
人类听觉对频率的感知呈对数关系,梅尔滤波器组模拟此特性。典型实现使用26个三角形滤波器:
def mel_filterbank(nfft=512, sr=16000, n_filters=26):low_mel = 0high_mel = 2595 * np.log10(1 + (sr/2)/700)mel_points = np.linspace(low_mel, high_mel, n_filters + 2)hz_points = 700 * (10**(mel_points/2595) - 1)bin = np.floor((nfft + 1) * hz_points / sr).astype(int)fbank = np.zeros((n_filters, nfft//2 + 1))for m in range(1, n_filters + 1):for k in range(bin[m-1], bin[m+1]):if k < bin[m]:fbank[m-1, k] = (k - bin[m-1]) / (bin[m] - bin[m-1])else:fbank[m-1, k] = (bin[m+1] - k) / (bin[m+1] - bin[m])return fbank
2.3 MFCC计算流程
- 对每帧FFT结果应用梅尔滤波器组
- 取对数能量
- 进行DCT(离散余弦变换)得到倒谱系数
- 保留前13维系数(MFCC_0~MFCC_12)
def compute_mfcc(frame, sr=16000, n_mfcc=13):fft = compute_fft(frame)fbank = mel_filterbank(sr=sr)mel_energy = np.dot(fft, fbank.T)log_mel = np.log(mel_energy + 1e-6) # 避免log(0)mfcc = np.dot(np.diag(np.power(np.arange(1, n_mfcc+1), -0.5)),np.fft.dct(log_mel, norm='ortho')[:n_mfcc])return mfcc
动态特征(ΔMFCC、ΔΔMFCC)通过一阶/二阶差分计算,增强时序信息。
三、声学模型:从特征到音素的映射
声学模型建立特征向量与音素(Phoneme)之间的概率关系,传统系统多采用HMM-GMM框架。
3.1 音素集设计
根据语言特性选择音素集,如英语常用CMU词典的39个音素(含静音模型<sil>)。中文需考虑声调,可扩展为带调音素(如a1, a2, a3, a4)。
3.2 HMM拓扑结构
每个音素建模为3状态左-右HMM(开始、中间、结束状态):
[开始] -> [中间] -> [结束]
状态转移矩阵示例:
trans_matrix = np.array([[0.6, 0.4, 0.0], # 开始状态[0.0, 0.7, 0.3], # 中间状态[0.0, 0.0, 1.0] # 结束状态])
3.3 GMM参数训练
每个HMM状态输出概率由GMM建模,典型混合数为16-32个高斯分量。EM算法迭代优化:
def gmm_em_step(data, weights, means, covars):# E步:计算责任值n_components = len(weights)n_samples = data.shape[0]responsibilities = np.zeros((n_samples, n_components))for k in range(n_components):diff = data - means[k]exponent = -0.5 * np.sum(diff * np.linalg.solve(covars[k], diff.T).T, axis=1)log_prob = np.log(weights[k]) - 0.5 * np.log(np.linalg.det(covars[k])) + exponentresponsibilities[:, k] = np.exp(log_prob - np.max(log_prob)) # 数值稳定responsibilities /= responsibilities.sum(axis=1, keepdims=True)# M步:更新参数n_k = responsibilities.sum(axis=0)weights = n_k / n_samplesmeans = np.dot(responsibilities.T, data) / n_k[:, np.newaxis]for k in range(n_components):diff = data - means[k]covars[k] = np.dot(responsibilities[:, k] * diff.T, diff) / n_k[k]return weights, means, covars
四、语言模型:语法与语义的约束
语言模型提供词序列的概率分布,传统系统采用N-gram模型。
4.1 N-gram统计
基于语料库统计词共现概率。以3-gram为例:
from collections import defaultdictdef train_ngram(corpus, n=3):ngram_counts = defaultdict(int)for sentence in corpus:tokens = ['<s>'] + sentence.split() + ['</s>'] # 添加句子边界for i in range(len(tokens)-n+1):ngram = tuple(tokens[i:i+n])ngram_counts[ngram] += 1return ngram_counts
4.2 平滑技术
解决零概率问题,常用Kneser-Ney平滑:
def kneser_ney_smooth(ngram_counts, discount=0.75):# 实现简化版Kneser-Ney平滑# 实际工程中需处理不同阶数的计数和连续折扣pass
4.3 决策树语言模型
通过词类(如名词、动词)构建决策树,减少参数数量。例如:
IS_NOUN(w1)/ \YES NO| |v(w2|w1) v'(w2|w1)
五、解码器:搜索最优路径
解码器整合声学模型和语言模型,在词图中搜索最优词序列。
5.1 WFST框架
加权有限状态转换器(WFST)统一声学模型(H)、发音词典(L)、语言模型(G):
HCLG = H ◦ C ◦ L ◦ G
其中◦表示组合操作,C为上下文依赖转换器。
5.2 Viterbi算法
动态规划搜索最优路径,核心步骤:
def viterbi_decode(obs, states, start_p, trans_p, emit_p):V = [{}]path = {}# 初始化for st in states:V[0][st] = start_p[st] * emit_p[st][obs[0]]path[st] = [st]# 递推for t in range(1, len(obs)):V.append({})new_path = {}for curr_st in states:(prob, state) = max((V[t-1][prev_st] * trans_p[prev_st][curr_st] * emit_p[curr_st][obs[t]], prev_st)for prev_st in states)V[t][curr_st] = probnew_path[curr_st] = path[state] + [curr_st]path = new_path# 终止(prob, state) = max((V[len(obs)-1][st], st) for st in states)return prob, path[state]
5.3 令牌传递算法
实际系统采用令牌传递(Token Passing)实现并行搜索,每个令牌记录路径和概率,在WFST状态间传递。
六、工程实践建议
- 特征工程优化:尝试PLP(感知线性预测)特征替代MFCC,在噪声环境下可提升5%-10%准确率。
- 模型压缩:对GMM模型进行SVD分解,减少30%-50%参数同时保持性能。
- 解码加速:使用GPU加速WFST组合操作,典型实现可达到10倍加速。
- 自适应技术:应用MAP(最大后验概率)自适应,10分钟用户数据即可提升15%-20%准确率。
传统语音识别系统流程构建了语音技术的基础框架,其模块化设计为后续深度学习革命提供了重要参考。理解这些经典技术,有助于开发者在资源受限场景下构建高效、可靠的语音识别系统。