简介这份资源面向语音信号处理与模式识别方向的学习者聚焦语音障碍分类这一具体问题通过提取短时帧特征构建两类分类器以区分发声麻痹症患者与健康人的语音。内容涵盖LPC、MFCC、PLP等特征提取方法并结合高斯混合模型、支持向量机、神经网络、LSTM及多种降维与聚类技术适合具备一定机器学习基础、希望深入理解语音特征工程与分类器对比实验的读者。压缩包共53个文件约313KB以Python脚本为主体辅以训练好的GMM模型文件、说明文档与数据文本并附有论文PDF便于对照理论复现实验。已有202人学习。资源完整呈现了从特征提取、降维到分类器训练与留一法评估的流程读者可据此理解全极点模型建模思路、比较不同特征与分类器的效果并借鉴其模块化目录组织方式开展自己的语音分类实验。1. 从一帧 25ms 的语音里把病理信息抠出来语音障碍分类这件事很多人第一反应是“上深度学习”但真正跑过一轮就会发现样本量往往只有几百条动辄上 LSTM 只会把验证集曲线画成玄学。这个资源走的是另一条路先把语音切成 2030ms 的短时帧用线性预测系数LPC及其倒谱把声道系统的贡献建模出来再交给 SVM、GMM、LDA 这类经典分类器去区分声带麻痹与健康发声。它解决的不是“识别说了什么”而是“发声器官本身有没有问题”——输入是一段持续元音输出是二分类标签。适合做语音病理辅助分析、医学信号课程设计以及想搞明白 MFCC/LPC 到底怎么算出来的从业者。整套流程从特征提取到分类器对比都有属于能直接照着复现的那类资源。2. 特征工程先立住LPC 与 MFCC 到底在算什么2.1 为什么选 LPC 而不是直接上频谱人发声可以拆成激励源和声道滤波器两级。声道在短时间内近似一个全极点系统传递函数写成 $H(z)1/(1-\sum_{k1}^{p}a_k z^{-k})$那组 $a_k$ 就是 LPC 系数。它把“声道形状”这件事压缩成十几个数比原始频谱干净得多也不容易被基频和谐波结构干扰。资源里对语音障碍分类感兴趣而声带麻痹改变的恰恰是声门激励的周期性和声道共振的稳定性LPC 谱包络能把这个变化反映出来。LPC 倒谱系数LPCC是在 LPC 基础上再取一次倒谱好处是把系统贡献和激励贡献进一步解耦同时维度可控、对谱包络的刻画更平滑。实操里阶数 $p$ 一般取采样率的千分之一附近8kHz 采样取 812 阶16kHz 取 1216 阶。阶数太低包络糊成一团太高会把基频谐波也拟合进去反而引入噪声。2.2 分帧、加窗、预加重这套前置动作不管后面用 LPC 还是 MFCC前置流程是一样的写错一步后面全废。下面这段是可直接抄的分帧与预加重参数按 16kHz、25ms 帧长、10ms 帧移设置import numpy as np def pre_emphasis(signal, coeff0.97): # 提升高频补偿发声时高频衰减 return np.append(signal[0], signal[1:] - coeff * signal[:-1]) def frame_signal(signal, sr16000, frame_ms25, hop_ms10): frame_len int(sr * frame_ms / 1000) # 400 点 hop_len int(sr * hop_ms / 1000) # 160 点 n_frames 1 (len(signal) - frame_len) // hop_len idx np.arange(frame_len)[None, :] hop_len * np.arange(n_frames)[:, None] return signal[idx] # (n_frames, frame_len) def apply_window(frames): # 汉明窗压住帧两端的不连续减少频谱泄漏 return frames * np.hamming(frames.shape[1])pre_emphasis的 0.97 是经验值语音识别里几乎默认frame_ms25保证一帧内声道近似不变hop_ms10让帧之间有重叠、不丢边界信息。加窗必须做否则帧首尾突变会在频谱上拖出一片虚假高频。这里有个容易忽略的点预加重要在分帧之前对整段信号做不是逐帧做否则每帧第一个点会被重复处理。2.3 MFCC 与 LPCC 的取舍MFCC 走的是梅尔刻度滤波器组加 DCT贴近人耳感知LPCC 走的是全极点模型贴近发声系统物理。资源里两类都实现了原因很实际语音障碍分类的判别信息更多在声道共振的精细结构上LPCC 往往更稳但 MFCC 对噪声鲁棒、生态成熟适合做基线对照。我的建议是两个都提拼成特征向量再降维别一上来就赌某一个。import librosa def mfcc_features(signal, sr16000, n_mfcc13): mfcc librosa.feature.mfcc(ysignal, srsr, n_mfccn_mfcc, n_fft512, hop_length160, win_length400) # 对时间轴取均值标准差得到定长向量 return np.hstack([mfcc.mean(axis1), mfcc.std(axis1)])n_mfcc13是常规起点n_fft512对应 32ms 窗和 400 点帧长匹配。取均值和标准差是为了把变长帧序列压成定长向量喂给 SVM——这一步不做后面分类器根本接不上。3. 分类器怎么搭SVM、GMM 与降维的配合3.1 特征标准化与 PCA 的先后顺序拿到特征矩阵后第一件事是标准化第二件事才是降维。顺序反了PCA 会被量纲大的维度主导主成分方向直接跑偏。资源里用了 PCA 和 LDA 两种降维区别在于 PCA 是无监督的方差最大化LDA 是有监督的类间/类内散度比最大化。样本少、类别可分性明确时LDA 往往比 PCA 更省维度。from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.pipeline import Pipeline from sklearn.svm import SVC pipe Pipeline([ (scaler, StandardScaler()), (pca, PCA(n_components0.95)), # 保留 95% 方差 (svm, SVC(kernelrbf, C1.0, gammascale, probabilityTrue)), ])n_components0.95让 PCA 自动选维避免手拍数字gammascale是 sklearn 的默认自适应值样本量小的时候比固定 gamma 稳。注意 LDA 最多只能降到“类别数-1”维二分类就是 1 维别指望它保留太多信息它更适合做可视化或极简模型。3.2 GMM 做生成式对照的价值SVM 是判别式给的是决策边界GMM 是生成式给的是每类特征的分布。资源里两类都做是因为语音障碍数据常有不平衡问题GMM 能通过似然比对看出某一类样本是否“离群”这对排查标注错误很有用。GMM 的组件数不要贪多二分类、几百个样本24 个组件足够组件多了协方差矩阵估不准EM 容易收敛到奇异解。from sklearn.mixture import GaussianMixture gmm_healthy GaussianMixture(n_components3, covariance_typediag, random_state0).fit(X_healthy) gmm_patho GaussianMixture(n_components3, covariance_typediag, random_state0).fit(X_patho) # 用对数似然差做判别 score gmm_patho.score_samples(X_test) - gmm_healthy.score_samples(X_test) pred (score 0).astype(int)covariance_typediag是样本量有限时的保命选择全协方差在维度稍高时参数爆炸。score_samples返回对数似然相减就是对数似然比比直接比概率更数值稳定。3.3 交叉验证与类别不平衡语音病理数据集通常健康样本远多于病理样本直接算准确率会虚高。资源里用分层 K 折加召回率、F1 一起看。分层保证每折里两类比例一致否则某一折可能全是健康样本模型直接学废。from sklearn.model_selection import StratifiedKFold, cross_validate cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) scores cross_validate(pipe, X, y, cvcv, scoring[accuracy, recall, f1]) print(scores[test_recall].mean(), scores[test_f1].mean())shuffleTrue配固定random_state是为了可复现scoring里一定要带 recall病理类漏检的代价远高于误检这个场景下准确率不是第一指标。4. 避坑与排查这几处翻车最频繁4.1 现象训练集准确率 99%测试集掉到 60%原因几乎都是数据泄漏——标准化或 PCA 在全量数据上 fit 之后再切分测试集信息提前进了模型。解决是把 scaler、PCA、分类器全塞进 Pipeline让交叉验证内部自己 fit别在切分前手动fit_transform整个矩阵。4.2 现象LPC 系数算出来全是 NaN 或极大值原因是自相关矩阵接近奇异常见于静音段或阶数设得比帧长还高。解决是先做语音活动检测把能量过低的帧丢掉阶数控制在帧长的 1/4 以内求自相关时加一个极小的对角正则项如1e-8稳住矩阵求逆。4.3 现象MFCC 和 LPCC 拼起来后效果反而变差维度灾难。两类特征各自十几维拼完三十多维样本只有几百条分类器在噪声维度上过拟合。解决是拼接后强制走 PCA 或 LDA 降维或者先各自标准化再按方差贡献加权别直接hstack完就喂模型。4.4 现象GMM 训练报协方差矩阵非正定组件数给多了某个组件只分到一两个样本协方差估不出来。解决是降n_components、改用diag协方差或者给reg_covar设一个非零值如1e-6做正则。样本量小于组件数乘维度时GMM 基本不可信换 SVM 更实在。4.5 现象换一批录音后模型完全失效录音设备、采样率、麦克风距离变了特征分布整体漂移。解决是统一重采样到同一采样率、做峰值归一化并在特征里加入能量和过零率这类对增益不敏感的量做辅助。跨设备场景下单靠 MFCC 均值很难扛住这点要有心理准备。5. 把验证做扎实从单次划分到可复现的评估脚本模型能跑通只是起点真正决定这份资源能不能用的是评估是否站得住。我一般会强制走一遍“固定种子 分层交叉验证 多指标 混淆矩阵”的组合而不是看一眼准确率就收工。下面这段把前面所有环节串成一条可复现的评估链import numpy as np from sklearn.model_selection import StratifiedKFold, cross_val_predict from sklearn.metrics import confusion_matrix, classification_report cv StratifiedKFold(n_splits5, shuffleTrue, random_state42) y_pred cross_val_predict(pipe, X, y, cvcv) print(confusion_matrix(y, y_pred)) print(classification_report(y, y_pred, digits3))cross_val_predict返回的是每个样本在“没被训练过”的那一折上的预测拼起来就是一份近似无泄漏的袋外预测拿它算混淆矩阵比单次划分可信得多。digits3是为了看清 recall 的小数位差异二分类样本少的时候0.02 的差距都可能是真实信号。再往上一层是特征层面的消融对照。别只报“LPCCSVM 准确率多少”要报“只用 MFCC 多少、只用 LPCC 多少、两者拼接降维后多少”这张表才是别人愿意信你的理由特征组合降维方式分类器RecallF1MFCC 均值标准差无SVM-RBF基线基线LPCCPCA 95%SVM-RBF对比对比MFCCLPCC 拼接LDASVM-RBF对比对比MFCCLPCC 拼接PCA 95%GMM对比对比表格里的数值要自己跑出来填别照抄。跑的时候固定random_state把特征提取的参数帧长、帧移、阶数、MFCC 维数写进配置字典一起存盘否则过两周你自己都复现不出当时那组数。血泪经验是特征提取脚本和分类脚本一定要解耦特征存成.npy加一份参数 JSON换分类器时不用重算特征调参效率能差出好几倍。还有一个容易被跳过的验证点——把预测错的样本单独拎出来听。语音障碍分类里错分往往集中在发声极不稳定或录音质量差的片段听一遍比看十张图都快。从那以后我每次做完这类二分类都强制把混淆矩阵四个格子各抽几条出来过一遍耳朵确认模型不是在拟合录音设备而不是病理特征。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?