资讯详情

资讯详情

mlpack 信号处理完全指南:EMD/EEMD 信号分解与 MFE/MFCC 音频特征提取

人工智能机器学习深度学习【免费下载链接】mlpackmlpack: a fast, header-only C machine learning library项目地址https://gitcode.com/gh_mirrors/ml/mlpack点击查看免费下载mlpack 在src/mlpack/core/transforms/下提供了一组面向信号处理与音频特征提取的 C 工具函数EMD()与EEMD()用于对一维信号做自适应分解MFE()与MFCC()用于从原始 PCM 音频中提取梅尔频谱特征。本文以 信号处理官方文档 为主线结合 emd.hpp、eemd.hpp、mfe.hpp、mfcc.hpp 等源码实现与src/mlpack/tests/下的测试用例系统讲解每个函数的参数、算法原理、调用方式与工程注意事项。读完本文你将掌握在 mlpack 中构建信号监测管线、语音识别/说话人识别等特征工程管线的完整方法。一、mlpack 信号处理模块总览mlpack 提供两大类信号处理技术用于从平稳与非平稳信号中提取特征类别函数用途分解DecompositionEMD()经验模态分解将一维信号自适应分解为一组本征模态函数IMF加残差分解DecompositionEEMD()集成经验模态分解用集成ensemble方式包装EMD()输出更稳健的 IMF特征提取Feature ExtractionMFE()梅尔频率能量从梅尔尺度的三角滤波器组中提取对数刻度能量特征提取Feature ExtractionMFCC()梅尔频率倒谱系数对 MFE 输出施加离散余弦变换DCT得到的紧凑表示所有实现均位于 src/mlpack/core/transforms/ 目录含spline_envelope.hpp等内部支撑文件均为头文件实现header-only可直接被 C 程序包含使用。二、EMD经验模态分解2.1 函数签名与参数EMD()用于从均匀采样的周期信号中提取本征模态函数Intrinsic Mode Functions, IMFs适用于非线性、非平稳问题的信号监测管线。EMD(signal, imfs, residue, maxImfs 10, maxSiftIter 50, tol 1e-3)各参数含义如下实现见 emd.hpp参数类型默认值说明signal列向量如arma::vec—一维信号数据必须均匀采样仅支持单列多列会抛出std::runtime_errorimfs矩阵—输出参数存放提取的 IMF形状为N x KN为信号长度K为提取到的 IMF 个数residue列向量长度N—输出参数提取完 IMF 后的最终残差信号maxImfssize_t10最大提取 IMF 数量maxSiftItersize_t50每个 IMF 的最大筛选sifting迭代次数toldouble1e-3筛选迭代的停止容差2.2 算法原理与内部实现EMD()的核心流程见 emd.hpp 中的NextImf()、SiftingStep()、FindExtrema()、CountZeroCrossings()如下找极值FindExtrema()通过相邻三点的比较识别严格局部极大值/极小值并始终把端点包含进去以保证残差单调时也能构造包络emd.hpp。样条包络BuildSplineEnvelope()通过自然三次样条端点二阶导为零穿过极值点构造上包络与下包络spline_envelope.hpp。筛选siftingSiftingStep()计算上下包络均值meanEnv (upper lower)/2更新h - meanEnv反复迭代直到满足停止条件emd.hpp。IMF 判定停止准则基于归一化平均包络幅值——当包络均值范数与信号范数之比小于tol时停止同时满足IMF 形状判据极值点个数与过零点个数相等或至多相差 1对应 S-number 取 S1emd.hpp。关键注意事项文档明确说明原信号可精确重建sum(imfs) residue等于原始信号。测试 EMDSingleTone 在 50000 点含噪信号上验证了相对重建误差小于1e-3。更小的tol意味着更严格的停止准则算法在达到maxSiftIter或满足tol时终止以先发生者为准。若残差单调极值不足EMD()返回 0 个 IMF 且residue等于输入信号——测试 EMDMonotone 验证了该边界行为。提取的 IMF 若相对原信号范数过小imfNorm 1e-8 * signalNorm也会提前终止emd.hpp。下图展示了 EMD 的分解过程(a) 原始信号(b) 带局部极大/极小包络的原始信号(c) 通过筛选从原始信号中提取出的第一个 IMF。2.3 完整示例对时变信号做 EMD 并检查主频const arma::uword N 400; const double tMin 0.0; const double tMax arma::datum::pi; arma::vec time arma::linspace(tMin, tMax, N); // signal sin(20*T*(1 0.2*T)) T**2 sin(13*T) // 见上图 arma::vec signal arma::sin( 20.0 * time % (1.0 0.2 * time) ) arma::square(time) arma::sin(13.0 * time); arma::mat imfs; arma::vec residue; // 最多 5 个 IMF每个 IMF 最多 50 次筛选tol 1e-6 mlpack::EMD(signal, imfs, residue, 5, 50, 5e-6); // 打印前 3 个 IMF 的主导频率验证 EMD 是否正确提取了 IMF const size_t numToShow std::minsize_t(3, imfs.n_cols); const double dt time(1) - time(0); const double fs 1.0 / dt; for (size_t k 0; k numToShow; k) { arma::cx_vec spectrum arma::fft(imfs.col(k)); // 只用频谱的前半部分 arma::vec mag arma::abs(spectrum.rows(0, spectrum.n_elem / 2)); arma::uword idx mag.index_max(); const double peakHz (double) idx * fs / spectrum.n_elem; std::cout IMF k peak freq: peakHz Hz std::endl; }其中N400等参数可根据信号长度自由调整signal也可以使用arma::fvec等浮点列向量类型——EMD()通过 SFINAE 支持任何元素类型匹配的 Armadillo 列/矩阵类型见 emd.hpp测试 EMDTemplateReconstruction 同时验证了float与double两种模板实例的重建精度。三、EEMD集成经验模态分解3.1 函数签名与参数EEMD()包装EMD()对信号多次运行 EMD每次注入独立的白噪声最后对结果取平均。注入的噪声会抑制模式混叠mode mixing并在平均过程中相互抵消从而得到更稳健的 IMF。EEMD(signal, imfs, residue, ensSize 100, noiseStrength 0.2, maxImfs 10, maxSiftIter 50, tol 1e-3)参数类型默认值说明ensSizesize_t100集成成员数即参与平均的EMD()运行次数必须大于 0否则抛出std::runtime_erroreemd.hppnoiseStrengthdouble0.1注入白噪声的标准差占信号标准差的比例如0.1表示信号标准差的 10%源码实现默认值为0.1见 eemd.hppsignal、imfs、residue、maxImfs、maxSiftIter、tol——与经典EMD()定义一致3.2 实现细节与注意事项源码实现eemd.hpp要点每次运行构造noisySignal signal noiseScale * randnColType(N)其中noiseScale noiseStrength * stddev(signal)再调用EMD()。各次运行之间使用 OpenMP 并行在MLPACK_USE_OPENMP宏开启时按线程数分配局部累加缓冲避免数据竞争。返回的 IMF 数量是所有ensSize次运行中EMD()实际提取 IMF 数的最小值 maxImfs保证每个 IMF 列都有完整的平均结果。imfs accumulatedImfs / ensSizeresidue signal - sum(imfs, 1)。与EMD()不同EEMD()的 IMF 是“信号 噪声”多次分解后的集成平均结果不能像EMD()那样把 IMF 与残差之和解释为对原始信号的自然分解。文档同时提醒由于注入噪声与集成平均EEMD 可能产生低能量的前导 IMF应用时可在后处理中通过能量占比阈值丢弃可忽略的 IMF。此外返回的 IMF 数量被限制在0到maxImfs之间——算法只返回从输入信号中实际能提取出的 IMF 数量。测试 EEMDOutput 用文档中的经典 chirp 信号sin(20t(10.2t)) t² sin(13t)验证了重建误差小于1e-2并确认了第一个 IMF 对应随时间线性升频的 chirp 分量、后续 IMF 对应约 2 Hz 的固定频率分量测试 EEMDvsEMD 则验证了当ensSize1、噪声强度极小时 EEMD 退化为近似 EMD。3.3 完整示例const arma::uword N 3000; const double tMin 0.0; const double tMax arma::datum::pi; arma::vec time arma::linspace(tMin, tMax, N); // signal sin(20*T*(1 0.2*T)) T**2 sin(13*T) arma::vec signal arma::sin( 20.0 * time % (1.0 0.2 * time) ) arma::square(time) arma::sin(13.0 * time); arma::mat imfs; arma::vec residue; // 100 个集成成员0.15 噪声强度最多 10 个 IMF每个 IMF 50 次筛选tol 1e-2 mlpack::EEMD(signal, imfs, residue, 100, 0.15, 10, 50, 1e-2);四、MFE梅尔频率能量4.1 函数签名与参数MFE()用于从Load()加载的原始 PCM 音频数据中提取标准音频特征可作为语音识别、说话人识别、关键词检测等机器学习模型的输入。MFE(signals, mfe, sampleRate, numMelFilters 40, windowLength 25, windowStep 10, nFFT 0, lowFreq 0.0, highFreq 0.0)参数表文档与 mfe.hpp 一致参数类型默认值说明signalsarma::mat或其他浮点矩阵—原始 PCM 音频样本形状numSamples x numSignals每列一个信号mfearma::mat或其他浮点矩阵—输出矩阵形状numMelFilters x (numWindows * numSignals)sampleRatesize_t—音频采样率Hz如16000、44100numMelFilterssize_t40梅尔尺度三角滤波器数量典型范围20~100windowLengthfloat25.0窗长毫秒典型范围20~40windowStepfloat10.0窗移/步长毫秒典型范围5~20nFFTsize_t0FFT 点数0表示取不小于窗长的下一个 2 的幂2 的幂更高效典型范围256~4096lowFreqfloat0.0梅尔滤波器组低频边界Hz典型范围0~300highFreqfloat0.0高频边界Hz0表示sampleRate / 2典型范围4000~sampleRate / 2使用前提signals必须为浮点元素类型float/double。若原始音频是整数矩阵需先用arma::conv_to转换为浮点矩阵对整数类型MFE()的重载会在编译期通过static_assert报错mfe_impl.hpp。sampleRate可通过Load()时填充的AudioOptions获得如opts.SampleRate()。多声道音频必须在调用前去交织de-interleave每个声道一列以保留空间信息如左右声道若不需要空间信息可先混音为单声道如mono (left right) / 2再处理。4.2 计算步骤MFE 的完整计算流程如下实现见 mfe_impl.hpp(a)每个输入信号的幅值应在[-1.0, 1.0]范围内Load()加载为浮点矩阵时自动保证见 音频数据文档。(b)用滑动窗口把信号切成重叠的帧乘以Hamming 窗w[n] 0.54 - 0.46·cos(2πn/(N-1))抑制频谱泄漏HammingWindow。(c)对每个数据窗施加短时傅里叶变换STFT得到短时频谱PowerSpectrum()通过arma::fft()计算并保留前nFFT/2 1个 bin 的功率谱幅度平方PowerSpectrum。(d)将每个 STFT 帧与梅尔滤波器组相乘——滤波器组由梅尔尺度上对数分布的三角滤波器构成。MelFilterbank()在lowFreq与highFreq之间按梅尔刻度均匀放置numFilters 2个点映射到 FFT bin 索引并构造相邻重叠的三角滤波器保证整个频段无缝隙覆盖MelFilterbank。(e)对滤波 bin 取对数得到梅尔滤波器能量。实现中在乘法结果上加上1e-10以避免对 0 取对数mfe_impl.hpp。补充的工程细节来自源码windowLength/windowStep会先换算为样本数lengthInSamples windowLength * sampleRate / 1000。nFFT 0时由NextPowerOf2()计算不小于窗长的下一个 2 的幂若显式传入的nFFT小于窗长样本数会通过Log::Fatal报错mfe_impl.hpp。每列的窗数由numWindows (signal.n_elem - windowLength) / windowStep 1确定信号短于一窗时会零填充SlidingWindow。4.3 示例一默认参数// 见 https://datasets.mlpack.org/sine.wav arma::mat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); arma::mat mfe; mlpack::MFE(signal, mfe, opts.SampleRate()); std::cout MFE shape: mfe.n_rows x mfe.n_cols std::endl;4.4 示例二自定义滤波器数与频段// 见 https://datasets.mlpack.org/sine.wav arma::fmat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); arma::fmat mfe; // 80 个梅尔滤波器默认窗参数频段 300–8000 Hz mlpack::MFE(signal, mfe, opts.SampleRate(), 80, 25.0, 10.0, 0, 300.0, 8000.0); std::cout MFE shape: mfe.n_rows x mfe.n_cols (filters x windows) std::endl;4.5 示例三分析每个频带的平均能量并定位峰值滤波器该示例同时演示了HzToMel()/MelToHz()两个公开辅助函数的用法二者实现见 mfe_impl.hpp对应公式mel 2595·log10(1 hz/700)及其逆变换arma::mat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); std::cout Loaded: signal.n_rows samples, opts.SampleRate() Hz, opts.Channels() channel(s). std::endl; arma::mat mfe; mlpack::MFE(signal, mfe, opts.SampleRate()); std::cout MFE shape: mfe.n_rows x mfe.n_cols (filters x windows). std::endl; arma::vec meanMFE arma::mean(mfe, 1); size_t peakFilter meanMFE.index_max(); float peakVal meanMFE.max(); size_t nFFT 512; float highFreq opts.SampleRate() / 2.0f; float melLow mlpack::HzToMel(0.0f); float melHigh mlpack::HzToMel(highFreq); arma::vec melPoints arma::linspacearma::vec(melLow, melHigh, 42); arma::vec hzPoints(42); for (size_t i 0; i 42; i) hzPoints(i) mlpack::MelToHz(melPoints(i)); std::cout std::endl; std::cout Filter Freq range (Hz) Avg energy std::endl; std::cout ------ ------------------- ---------- std::endl; for (size_t i 0; i 40; i) { std::cout std::setw(2) i std::setw(5) std::fixed std::setprecision(0) hzPoints(i) – std::setw(5) hzPoints(i 2) std::setw(8) std::setprecision(2) meanMFE(i); if (i peakFilter) std::cout peak; else if (i peakFilter - 1 || i peakFilter 1) std::cout adjacent; std::cout std::endl; }测试 MFEPureSine440 与 MFEDC 分别验证了对 440 Hz 纯正弦输入峰值梅尔 bin 出现在低频段滤波器 0–10 内对直流信号滤波器 00 Hz能量最高其余 bin 显著低于峰值。五、MFCC梅尔频率倒谱系数5.1 函数签名与参数MFCC()与 MFE 类似从Load()加载的原始 PCM 数据中提取标准音频特征。由于 MFCC 系数已去相关decorrelated它们可以用于基于距离的机器学习算法如 KNN、KMeans或概率算法如 GMM、HMM。MFCC(signals, mfcc, sampleRate, numCoeffs, numMelFilters 40, windowLength 25, windowStep 10, nFFT 0, lowFreq 0.0, highFreq 0.0)参数表文档与 mfcc.hpp 一致参数类型默认值说明signalsarma::mat或其他浮点矩阵—原始 PCM 音频样本形状numSamples x numSignalsmfccarma::mat或其他浮点矩阵—输出矩阵形状numCoeffs x (numWindows * numSignals)sampleRatesize_t—音频采样率Hz如16000、44100numCoeffssize_t13倒谱系数个数必填参数之一numMelFilterssize_t40梅尔三角滤波器数量典型范围20~100windowLengthfloat25.0窗长毫秒典型范围20~40windowStepfloat10.0窗移毫秒典型范围5~20nFFTsize_t0FFT 点数0取不小于窗长的下一个 2 的幂典型范围256~4096lowFreqfloat0.0低频边界Hz典型范围0~300highFreqfloat0.0高频边界Hz0表示sampleRate / 2典型范围4000~sampleRate / 25.2 计算步骤与实现要点MFCC 在 MFE 的基础上多出最后一步(a)每个输入信号幅值应在[-1.0, 1.0]内(b)用 Hamming 窗将信号切成重叠帧以抑制频谱泄漏(c)对每个数据窗做 STFT 得到短时频谱(d)每个 STFT 帧与梅尔滤波器组梅尔尺度上对数分布的三角滤波器相乘(e)对滤波 bin 取对数得到梅尔滤波器能量即 MFE(f)乘上离散余弦变换DCT矩阵得到 MFCC。实现层面mfcc_impl.hppD[n][k] cos(π · n · (k 0.5) / M) // M numMelFilters mfcc DCTMatrix(numCoeffs, numMelFilters) * mfe;即先调用MFE()得到numMelFilters x numWindows的对数梅尔能量再左乘numCoeffs x numMelFilters的 DCT-II 矩阵压缩出numCoeffs个倒谱系数。关键约束numCoeffs必须小于等于numMelFiltersDCT 只能把numMelFilters个对数梅尔能量压缩成numCoeffs个系数不能产出比输入值更多的系数。与 MFE 相同signals必须是浮点矩阵整数矩阵在编译期报错mfcc_impl.hpp多声道需先解交织或混音为单声道。5.3 示例一从 WAV 提取默认 13 个 MFCC// 见 https://datasets.mlpack.org/sine.wav arma::mat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); arma::mat mfcc; mlpack::MFCC(signal, mfcc, opts.SampleRate()); // mfcc 形状为 13 x numWindows std::cout MFCC shape: mfcc.n_rows x mfcc.n_cols . std::endl;5.4 示例二从 MP3 提取 20 个 MFCC80 个梅尔滤波器// 见 https://datasets.mlpack.org/fifths.mp3 arma::fmat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::MP3; mlpack::Load(fifths.mp3, signal, opts); arma::fmat mfcc; mlpack::MFCC(signal, mfcc, opts.SampleRate(), 20, 80);5.5 示例三自定义参数电话语音典型配置// 见 https://datasets.mlpack.org/sine.wav arma::fmat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); arma::fmat mfcc; mlpack::MFCC(signal, mfcc, opts.SampleRate(), 13, 26, 25.0, 10.0, 0, 300.0, 3400.0);5.6 示例四解释 13 个 MFCC 各自捕获的信息arma::mat signal; mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; mlpack::Load(sine.wav, signal, opts); std::cout Loaded: signal.n_rows samples, opts.SampleRate() Hz, opts.Channels() channel(s). std::endl; arma::mat mfcc; mlpack::MFCC(signal, mfcc, opts.SampleRate()); std::cout MFCC shape: mfcc.n_rows x mfcc.n_cols (coefficients x windows). std::endl; arma::vec meanMFCC arma::mean(mfcc, 1); std::cout std::endl; std::cout Coeff Avg value What it captures (roughly) std::endl; std::cout ----- --------- ---------------- std::endl; const char* descriptions[] { Overall energy (loudness), Spectral tilt (low vs high freq balance), Spectral curvature (middle vs edges), Two-bump structure (formant separation), Finer spectral shape, Finer spectral shape, Finer spectral shape, Finer spectral shape, Finer spectral shape, Finer spectral shape, Finer spectral shape, Fine spectral detail, Finest spectral detail }; for (size_t i 0; i mfcc.n_rows; i) { std::cout c[ std::setw(2) i ] std::setw(10) std::fixed std::setprecision(2) meanMFCC(i) descriptions[i] std::endl; }测试方面MFCCSine440 验证了对 440 Hz 正弦输入提取的 MFCC 形状为13 x 98且数值有限MFCCMultiChannel 验证了多声道3 通道输入时输出列数等于nChannels * framesPerChannel且每个声道的帧序列一致。六、与 Load()/AudioOptions 组合的音频特征工程管线MFE()/MFCC()的上游是 mlpack 的音频加载能力。Load()通过内置的dr_libs头文件库解码 WAV/MP3 文件为 PCM 帧并将每个音频文件展平为加载矩阵中的一列立体声文件的帧顺序为[l0, r0, l1, r1, ...]见 音频数据文档。加载为浮点矩阵时样本值保证落在[-1.0, 1.0]——这正是 MFE/MFCC 步骤 (a) 的前提。AudioOptionsaudio_options.hpp在Load()后被填充以下元数据成员详见 AudioOptions 文档成员函数返回类型含义opts.SampleRate()size_t采样率Hz如44100、48000直接作为MFE()/MFCC()的sampleRate参数opts.Channels()size_t声道数1 为单声道、2 为立体声opts.AudioDuration()double音频时长秒opts.BitsPerSample()size_t每样本位深opts.TotalSamples()size_t总样本数totalFrames * Channels()典型管线写法mlpack::AudioOptions opts mlpack::Fatal mlpack::WAV; // Fatal加载失败即抛异常 arma::mat signal; mlpack::Load(sine.wav, signal, opts); arma::mat mfcc; mlpack::MFCC(signal, mfcc, opts.SampleRate()); // mfcc 每列即一个短时帧的特征向量可拼接后作为模型输入七、边界情况与工程建议依据源码与测试综合源码与测试用例以下是使用这四个函数时值得注意的边界情况输入维度EMD()/EEMD()仅接受单列信号多列抛异常且要求均匀采样MFE()/MFCC()的输入矩阵按列解释为独立信号输出按列拼接。类型限制MFE()/MFCC()仅支持浮点元素类型float/doubleEMD()/EEMD()对float与double均支持但输入列类型与输出矩阵元素类型必须一致SFINAE 约束。单调信号EMD()对单调残差返回 0 个 IMFresidue等于输入EMDMonotoneEEMD 的集成数量也只在能实际提取时才返回对应 IMF。噪声与低能量 IMFEEMD 可能因注入噪声与集成平均产生低能量前导 IMF建议后处理时按能量占比过滤EMD()内部则会丢弃范数小于1e-8 × signalNorm的 IMF。参数合法性EEMD()的ensSize必须大于 0MFE()要求highFreq lowFreq且nFFT windowLength × sampleRate否则运行时报错MFCC()要求numCoeffs numMelFilters。性能提示nFFT使用 2 的幂可显著提升 FFT 效率默认自动取不小于窗长的下一个 2 的幂windowStep越大、windowLength越短产生的帧越少特征矩阵越小。以上实现均可直接在 C 程序中通过包含 mlpack/core.hpp 使用全部源码位于 src/mlpack/core/transforms/测试代码位于 src/mlpack/tests/emd_test.cpp 与 src/mlpack/tests/mfcc_test.cpp可作为进一步研究算法行为与精度验证的参考。赞分享人工智能机器学习深度学习【免费下载链接】mlpackmlpack: a fast, header-only C machine learning library项目地址https://gitcode.com/gh_mirrors/ml/mlpack点击查看免费下载相关推荐告别绘图工具用文本思维重构你的图表创作流程告别绘图工具用文本思维重构你的图表创作流程 你是否曾在创建技术文档时因为图表绘制而中断思路是否在与团队协作时因为图表格式不统一而反复沟通是否因为复杂的前端开发者工具数据可视化numpy-ml 数字信号处理DSP模块实战指南从 DFT/DCT 到 MFCC 特征提取numpy ml 数字信号处理DSP模块实战指南从 DFT/DCT 到 MFCC 特征提取 导读 本文以 numpy ml 仓库中的 docs/numpy机器学习人工智能RockGO未来路线图即将发布的5大核心功能预览RockGO未来路线图即将发布的5大核心功能预览 RockGO作为一款基于实体组件系统ECS的游戏服务器框架正处于积极开发阶段。本文将为您独家揭秘Roc上一篇终极指南如何用STIX Two字体彻底解决学术文档排版难题下一篇如何快速提升GitHub访问速度终极加速插件完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →