3、特征提取概述:特征提取在信号处理与机器学习中的意义、常见特征类型(时域、频域、统计特征)及在MCU上的挑战
特征提取是连接原始信号与智能决策的桥梁。在嵌入式信号处理与边缘机器学习场景中,传感器采集到的原始数据往往包含大量冗余信息、噪声和与任务无关的干扰分量。若将原始采样点直接送入分类器或回归模型,不仅会消耗MCU上极其有限的Flash与RAM资源,还会因维度灾难导致模型泛化能力下降。特征提取的核心目标,是在保留任务判别性信息的前提下,将高维原始信号压缩为低维、稳定、物理可解释的特征向量。本章将系统阐述特征提取在信号处理与机器学习中的意义,梳理时域、频域与统计特征的典型类型与适用场景,并深入剖析在MCU上实施特征提取所面临的计算、存储与数值精度挑战。
上图展示了三类特征在信号处理链路中的位置与典型代表。时域特征直接对采样序列进行算术与逻辑运算,计算量小但物理意义直观;频域特征通过变换揭示信号的周期性与频率分布,判别能力强但需要额外的变换开销;统计特征则从概率分布角度刻画信号形态,对噪声鲁棒性较好。在实际MCU工程中,往往需要根据任务需求、传感器类型与算力预算,从三类特征中选取若干组合成特征向量。
3.1 特征提取的核心意义:从数据洪流到决策支点
在嵌入式机器学习系统中,原始传感器数据通常以较高的采样率持续产生。以常见的加速度计为例,三轴以100Hz采样、每样本16位量化,每秒产生600字节数据。若直接将这些原始数据送入模型,一个仅包含1秒窗口的样本就需要600维输入特征。这不仅导致模型参数量急剧膨胀,还会引入大量与任务无关的噪声分量。特征提取的意义在于三个层面:维度压缩、信噪比提升与物理可解释性。
维度压缩并非简单丢弃信息,而是通过领域知识将原始信号映射到更能反映任务本质的低维空间。例如,在电机故障诊断中,原始振动波形包含数千个采样点,但真正区分正常与轴承磨损状态的关键信息往往集中在特定频带的能量分布上。通过提取频域子带能量特征,可以将数千维的原始数据压缩为10~20维的特征向量,同时保持甚至提升分类准确率。信噪比提升则体现在特征提取天然具备滤波效应——均值运算抑制随机噪声,频带能量计算剔除带外干扰,自相关分析突出周期性成分。物理可解释性使工程师能够理解模型决策依据,例如峰值因子增大可能意味着轴承出现点蚀,频谱质心偏移可能指示转速变化,这些都为后续的阈值设定与故障定位提供了依据。
工程视角:在MCU上实施特征提取时,应始终以“最小充分特征集”为设计目标。每增加一个特征维度,不仅增加当前的计算开销,还会导致后续分类器需要更多训练样本与更大的存储空间。建议在PC端使用完整数据集进行特征筛选与重要性排序,确定最优特征组合后,再将其固化到MCU固件中。
3.2 时域特征:低成本高物理意义的首选
时域特征直接对采样序列x[n](n=0,1,...,N-1)进行运算,无需变换域操作,计算复杂度通常为O(N),非常适合在MCU上实时计算。表1列出了常用时域特征的定义、物理含义与典型应用场景。
| 特征名称 | 计算公式 | 物理含义 | 典型应用 |
|---|---|---|---|
| 均值 | μ = (1/N)Σx[n] | 信号直流分量 | 加速度计倾角测量 |
| 均方根(RMS) | RMS = √((1/N)Σx²[n]) | 信号有效能量 | 振动烈度评估 |
| 峰值因子 | Crest = x_peak / RMS | 信号冲击程度 | 轴承点蚀检测 |
| 过零率 | ZCR = (1/N)Σ|sign(x[n])-sign(x[n-1])|/2 | 频率粗略估计 | 语音端点检测 |
| 波形因子 | Form = RMS / (1/N)Σ|x[n]| | 波形平坦程度 | 电流波形畸变分析 |
时域特征的计算流程通常遵循“滑动窗口+增量更新”模式。以RMS为例,若窗口长度为N,每次新采样到来时,只需更新平方和累加器:
// 滑动窗口RMS增量计算(伪代码)
static float sum_sq = 0;
static float buffer[N]; // 环形缓冲区
static uint8_t idx = 0;
// 每次新采样x_new到达时:
sum_sq -= buffer[idx] * buffer[idx]; // 移除最旧样本
buffer[idx] = x_new;
sum_sq += x_new * x_new;
idx = (idx + 1) % N;
float rms = sqrtf(sum_sq / N);
这种增量计算方式将每次采样的计算量降为常数级,非常适合中断服务程序中执行。但需要注意,当N较大时,sum_sq的累加值可能超出float32的精确表示范围,建议定期重置或使用double累加。
3.3 频域特征:揭示隐藏的周期规律
频域特征通过傅里叶变换将信号从时间域映射到频率域,能够揭示时域中难以观察的周期性成分。在MCU上,最常用的频域分析工具是FFT(快速傅里叶变换)。对于N点实数序列,使用基2 FFT算法需要(N/2)log₂N次复数乘法,当N=256时约需1024次乘法,在Cortex-M4内核上仅需数十微秒,完全可满足实时处理需求。
频域特征提取的关键步骤包括:加窗(抑制频谱泄漏)、FFT变换、频谱后处理。加窗是容易被忽视但至关重要的环节。矩形窗虽然主瓣最窄,但旁瓣衰减仅-13dB,会导致严重的频谱泄漏;汉宁窗旁瓣衰减达-31dB,是嵌入式应用中最常用的折中选择。频谱后处理则包括计算功率谱密度、提取子带能量、寻找峰值频率等操作。
以电机振动分析为例,假设采样率fs=2000Hz,FFT点数N=512,频率分辨率Δf=fs/N≈3.9Hz。若电机基频为50Hz,则其频谱峰值出现在第13个频点附近。通过提取基频及其2倍频、3倍频处的幅值比,可以判断转子是否存在不对中或弯曲故障。这种基于频域特征的诊断方法,比单纯观察时域波形更加直观和可靠。
经验提醒:在MCU上执行FFT时,建议使用CMSIS-DSP库提供的实数FFT函数(如arm_rfft_fast_f32),该函数针对Cortex-M内核进行了汇编级优化,比通用C语言实现快3~5倍。同时,注意FFT输入数据需要按特定格式排列(实部/虚部交替),且输出为自然序,需配合位反转操作或使用库提供的位反转函数。
3.4 统计特征:刻画信号的概率分布形态
统计特征从随机过程的角度描述信号,不依赖信号的时序关系,而是关注其幅值分布的形状。这类特征对噪声和幅值缩放具有一定的鲁棒性,常用于故障诊断和异常检测。高阶统计量如偏度(Skewness)和峰度(Kurtosis)能够反映信号分布的非对称性和尖峰程度,对早期微弱故障非常敏感。
偏度定义为三阶中心矩与标准差立方的比值:
Skewness = (1/N)Σ((x[n]-μ)/σ)³
当偏度接近0时,信号分布对称;偏度为正表示右偏(存在较大正脉冲),为负表示左偏。峰度定义为四阶中心矩与标准差的四次方之比再减3(使正态分布峰度为0):
Kurtosis = (1/N)Σ((x[n]-μ)/σ)⁴ - 3
峰度大于0表示信号分布比正态分布更尖峰,即存在更多离群值。在轴承故障诊断中,正常振动信号的峰度约为3(即Kurtosis≈0),当出现点蚀或剥落时,冲击成分使峰度显著增大,可超过10。这一特征在时域中即可计算,无需FFT,非常适合MCU实时监测。
统计特征的计算需要注意数值稳定性。当信号接近直流(σ→0)时,偏度和峰度的计算会产生除零问题。工程上通常先判断标准差是否小于某个阈值(如满量程的0.1%),若小于则直接置偏度和峰度为0。此外,统计特征对异常值敏感,建议在计算前先进行中值滤波或限幅处理。
3.5 MCU上的特征提取挑战与应对策略
在MCU上实施特征提取,面临的核心挑战可归纳为四个方面:计算资源、存储资源、数值精度与实时性。表2总结了这些挑战的具体表现与应对策略。
| 挑战维度 | 具体表现 | 应对策略 |
|---|---|---|
| 计算资源 | FFT、高阶统计量计算量大 | 使用CMSIS-DSP优化库;降低FFT点数;采用递推算法 |
| 存储资源 | 原始数据缓冲、FFT蝶形运算需大量RAM | 使用环形缓冲区;原地FFT;特征值即时计算不缓存原始数据 |
| 数值精度 | float32累加误差、FFT舍入误差 | 使用q15/q31定点格式;定期重置累加器;采用Kahan求和算法 |
| 实时性 | 高采样率下特征计算时间超过采样间隔 | 分时计算;利用DMA搬运数据;在空闲时段批量处理 |
存储资源往往是比计算资源更紧的约束。以三轴加速度计100Hz采样、窗口1秒为例,若需缓存全部原始数据,需要3×100×2字节=600字节RAM。若使用FFT进行频域分析,N=256点的FFT需要额外的2×256×4字节=2KB用于复数缓冲区。对于RAM仅有16KB的入门级MCU,这已经占据了相当比例。因此,工程上常采用“边采样边计算”的策略:在采样中断中更新时域特征(均值、RMS、峰值等),在空闲任务中执行FFT和频域特征提取,避免同时缓存大量原始数据。
风险提示:在低功耗MCU上使用浮点运算单元(FPU)时,虽然计算速度快,但功耗显著高于整数运算。对于电池供电的设备,建议在特征提取阶段使用定点数(如Q15格式),仅在分类器推理阶段启用FPU。此外,注意CMSIS-DSP库的某些函数(如arm_rfft_fast_f32)需要额外的临时缓冲区,需在链接脚本中合理分配内存段。
3.6 案例拆解:基于Cortex-M4的电机振动特征提取
下面通过一个完整的工程案例,展示如何在STM32F407(Cortex-M4,168MHz,带FPU)上实现电机振动信号的实时特征提取。该案例的目标是区分电机正常状态与轴承故障状态,为后续的轻量级分类器提供输入特征。
背景与约束:电机转速1500rpm(基频25Hz),振动传感器为IEPE型加速度计,灵敏度100mV/g,采样率fs=2000Hz,采样窗口T=0.5s(N=1000点)。MCU可用RAM为8KB,Flash为64KB,要求特征提取计算时间不超过5ms,功耗预算为50mA@3.3V。
特征选择:根据领域知识,选择以下6个特征组成特征向量:
- 时域RMS值(反映整体振动烈度)
- 时域峰值因子(反映冲击成分)
- 频域基频25Hz处幅值(反映转子不平衡)
- 频域2倍频50Hz处幅值(反映不对中)
- 频域高频段(500-1000Hz)能量占比(反映轴承早期故障)
- 时域峰度(反映冲击概率分布)
实现方案:采用双缓冲策略,使用DMA将ADC采样数据交替存入两个1KB缓冲区。当一个缓冲区填满时,触发中断,在中断服务程序中计算时域特征(RMS、峰值因子、峰度),同时启动FFT计算频域特征。FFT点数选择512点(实际使用前500个采样点,后12点补零),频率分辨率Δf=2000/512≈3.9Hz,基频25Hz对应第6.4个频点,取第6和第7频点的幅值加权平均作为基频幅值。
// 特征提取核心代码(简化版)
void feature_extract(float32_t* buffer, uint16_t len, float32_t* features) {
// 1. 时域特征
float32_t mean, rms, peak, kurtosis;
arm_mean_f32(buffer, len, &mean);
arm_rms_f32(buffer, len, &rms);
arm_max_f32(buffer, len, &peak, NULL);
features[0] = rms;
features[1] = peak / rms;
// 峰度计算(简化,实际需遍历)
float32_t sum4 = 0;
for (int i = 0; i < len; i++) {
float32_t dev = (buffer[i] - mean) / rms;
sum4 += dev * dev * dev * dev;
}
features[5] = sum4 / len - 3.0f;
// 2. 频域特征(使用CMSIS-DSP)
arm_rfft_fast_instance_f32 fft;
arm_rfft_fast_init_f32(&fft, 512);
float32_t fft_input[1024]; // 实部虚部交替
float32_t fft_output[512];
// 填充输入(加汉宁窗)
for (int i = 0; i < 512; i++) {
float32_t win = 0.5f * (1 - cosf(2*PI*i/511));
fft_input[2*i] = (i < len) ? buffer[i]*win : 0;
fft_input[2*i+1] = 0;
}
arm_rfft_fast_f32(&fft, fft_input, fft_output, 0);
// 提取基频幅值(第6、7频点平均)
features[2] = (fft_output[6] + fft_output[7]) / 2;
features[3] = (fft_output[12] + fft_output[13]) / 2;
// 高频段能量占比
float32_t total_energy = 0, high_energy = 0;
for (int i = 128; i < 256; i++) { // 500-1000Hz
high_energy += fft_output[i] * fft_output[i];
total_energy += fft_output[i] * fft_output[i];
}
for (int i = 0; i < 256; i++) total_energy += fft_output[i] * fft_output[i];
features[4] = high_energy / total_energy;
}
结果与复盘:实测该方案在168MHz主频下,时域特征计算耗时约0.2ms,FFT及频域特征提取耗时约2.8ms,总耗时3.0ms,满足5ms的实时性要求。RAM占用包括双缓冲2KB、FFT临时缓冲区4KB、特征向量存储0.1KB,总计约6.1KB,在8KB预算内。功耗方面,FPU开启时平均电流约45mA,符合预算。