4、数据采集与预处理:传感器数据采集方法、采样率选择、数据清洗、滑动窗口分割、特征提取(均值、方差、FFT等)

TinyML运动检测项目的成败,往往不取决于模型结构有多精巧,而取决于喂给模型的数据质量与形态。传感器数据从物理世界到模型输入,需要经历采集、清洗、分割、特征提取四个关键阶段。本章将系统讲解IMU(惯性测量单元)数据的采集方法、采样率选择依据、清洗策略、滑动窗口分割逻辑以及特征工程的具体实现,帮助你在资源受限的MCU上构建可靠的运动识别流水线。

TinyML运动检测数据流水线 ① 数据采集 IMU传感器 加速度计 ±2~16g 陀螺仪 ±250~2000dps 采样率 25~100Hz ② 数据清洗 异常值剔除 缺失值插补 低通滤波 截止频率 = 采样率/2 ③ 滑动窗口 窗口长度 2~4s 重叠率 50% 步长 = 窗口×(1-重叠) 每窗口 1个样本 ④ 特征提取 时域:均值/方差 频域:FFT峰值 统计:RMS/峰峰值 维度控制 < 50 关键设计参数与约束 • 采样率:25Hz(静态动作)~ 100Hz(快速运动),受MCU Flash/内存限制 • 窗口长度:2s(站立/行走)~ 4s(复杂手势),需覆盖完整动作周期 • 特征维度:每轴3~5个特征,3轴IMU共9~15维,避免维度灾难 • 内存预算:50Hz×6轴×2字节×4s = 2400B,MCU RAM需预留 • 实时性:特征计算耗时 < 50ms,FFT需用定点数优化 数据质量决定模型上限,预处理流水线需在PC端验证后移植到MCU

4.1 传感器数据采集方法

核心原理:运动检测通常使用IMU(惯性测量单元),包含三轴加速度计和三轴陀螺仪。加速度计测量物体在X/Y/Z轴上的线性加速度(单位g或m/s²),陀螺仪测量角速度(单位dps或rad/s)。在TinyML场景中,常见的传感器包括MPU6050(6轴)、MPU9250(9轴)、LSM6DS3等。采集过程涉及I2C或SPI总线通信、FIFO缓冲管理以及中断触发机制。

采集方法选择:

  • 轮询模式:MCU主循环中定时读取传感器寄存器,适合低采样率(≤50Hz)和简单任务,代码实现简单但占用CPU。
  • 中断模式:传感器数据就绪时触发外部中断,MCU进入ISR读取数据,适合中等采样率(50~200Hz),能有效降低功耗。
  • FIFO批量读取:传感器内置FIFO缓存多组数据,MCU定期批量读取,适合高采样率(>200Hz)或需要深度睡眠的场景,可显著减少唤醒次数。
经验提醒:在电池供电的TinyML设备中,推荐使用FIFO模式。例如,MPU6050内置1024字节FIFO,在50Hz采样率下可缓存约4秒数据,MCU每2秒唤醒一次批量读取,比轮询模式节省约70%的功耗。

4.2 采样率选择策略

核心原理:采样率决定了时间分辨率和数据量。根据奈奎斯特采样定理,采样率必须大于信号最高频率的2倍。人体运动信号的频率范围通常在0.5~20Hz之间,日常活动(走路、跑步、站立)的主要能量集中在0.5~5Hz,手势识别可能需要10~20Hz。

应用场景 推荐采样率 频率范围 数据量(6轴,2字节) 适用MCU
静态姿态检测 10~25Hz 0~5Hz 120~300 B/s 8位MCU(如STM8)
日常活动识别 25~50Hz 0~10Hz 300~600 B/s Cortex-M0+
手势/快速动作 50~100Hz 0~20Hz 600~1200 B/s Cortex-M4F
振动/高频分析 200Hz以上 0~100Hz 2400 B/s以上 Cortex-M7或外置DSP

选择方法:首先确定目标动作的最短持续时间。例如,一次快速挥手约0.5秒,需要至少10个采样点才能捕捉波形特征,因此最低采样率为20Hz。然后考虑MCU的Flash和RAM限制——采样率越高,存储和计算开销越大。最后通过实验验证:在PC端用不同采样率重采样数据,训练模型对比准确率,选择准确率不再显著提升的最低采样率。

风险提示:采样率过低会导致动作细节丢失,例如走路时脚跟着地的冲击信号持续约100ms,若采样率低于20Hz则可能完全错过该特征。采样率过高则会造成数据冗余,增加MCU负担和功耗,且对模型准确率提升有限。

4.3 数据清洗与预处理

核心原理:原始传感器数据包含噪声、异常值和缺失值。噪声来源包括:传感器自身的热噪声、电源纹波、机械振动耦合;异常值可能由突然的冲击、通信错误或传感器饱和引起;缺失值则可能发生在FIFO溢出或I2C通信失败时。数据清洗的目标是去除无效信息,保留真实运动信号。

清洗流程:

  1. 异常值检测:计算每个轴数据的均值和标准差,若某采样点超出均值±3σ范围,标记为异常值。对于加速度计,若|a| > 4g(正常运动通常<2g),判定为冲击噪声。
  2. 缺失值处理:若缺失数据点较少(<5%),采用线性插值;若连续缺失超过10个点,建议丢弃该段数据,因为插值会引入虚假波形。
  3. 滤波去噪:使用一阶低通滤波器(RC滤波)或移动平均滤波。截止频率设为采样率的1/4~1/2。例如,50Hz采样率下,截止频率设为12.5Hz,可有效滤除高频振动噪声。
// 一阶低通滤波实现(C语言,适用于MCU)
float alpha = 0.2f;  // 滤波系数 = 1/(1+2π*fc*dt)
float filtered = 0.0f;

float lowpass_filter(float raw) {
    filtered = alpha * raw + (1.0f - alpha) * filtered;
    return filtered;
}

// 移动平均滤波(窗口大小=5)
#define WINDOW_SIZE 5
float buffer[WINDOW_SIZE] = {0};
int idx = 0;

float moving_average(float raw) {
    buffer[idx] = raw;
    idx = (idx + 1) % WINDOW_SIZE;
    float sum = 0.0f;
    for (int i = 0; i < WINDOW_SIZE; i++) sum += buffer[i];
    return sum / WINDOW_SIZE;
}
实战要点:在MCU上实现滤波时,优先使用整数运算替代浮点运算。例如,将alpha量化为Q15格式(乘以32768),滤波结果右移15位。这样可将计算耗时从约50μs降至5μs,且不损失精度。

4.4 滑动窗口分割

核心原理:运动数据是连续的时间序列,无法直接输入模型。滑动窗口将连续数据切分为固定长度的片段,每个窗口作为一个独立样本。窗口长度需覆盖一个完整动作周期,重叠率则用于增加样本数量和平滑预测结果。

参数选择方法:

  • 窗口长度:设为动作平均持续时间的1.5~2倍。例如,走路一步约1秒,窗口设为2秒;站立检测可设为1秒。窗口过短会截断动作,过长则包含多余信息,降低时间分辨率。
  • 重叠率:通常设为50%~75%。50%重叠可增加样本数量而不显著增加计算量;75%重叠用于需要高时间精度的场景(如实时跌倒检测),但计算量增加3倍。
  • 步长计算:步长 = 窗口长度 × (1 - 重叠率)。例如,窗口2秒、重叠50%,则步长1秒,即每1秒产生一个新窗口。

案例拆解:假设我们要在STM32F411(Cortex-M4F,100MHz)上实现跌倒检测。跌倒动作从开始到倒地约1.5秒,因此设置窗口长度2秒(100Hz采样率下共200个采样点),重叠率50%(步长1秒)。每个窗口包含6轴数据,共200×6=1200个原始值。若直接输入模型,特征维度为1200,远超MCU的处理能力。因此需要特征提取将维度降至20~30。

4.5 特征提取:从原始数据到有效特征

核心原理:特征提取将窗口内的原始采样点压缩为少量统计量,保留运动的关键信息,同时降低模型输入维度。在TinyML中,特征提取需在MCU上实时计算,因此必须选择计算量小、物理意义明确的特征。

常用特征分类:

特征类别 特征名称 计算公式 物理意义 计算量
时域特征 均值 μ = (1/N)Σxᵢ 静态分量(重力方向) O(N)
方差 σ² = (1/N)Σ(xᵢ-μ)² 运动强度 O(N)
均方根RMS RMS = √(Σxᵢ²/N) 信号能量 O(N)
频域特征 FFT峰值频率 f_max = argmax|X(k)| 动作周期性 O(N log N)
频谱能量 E = Σ|X(k)|² 频带能量分布 O(N log N)
统计特征 峰峰值 max(x) - min(x) 动作幅度 O(N)

FFT实现要点:在MCU上执行FFT需注意:使用定点FFT(如CMSIS-DSP库的arm_rfft_q15),将输入数据转换为Q15格式;FFT点数选择256或512(2的幂),对应2秒窗口在128Hz采样率下的数据量;只取前N/2个频点(奈奎斯特频率以下),丢弃对称部分。

// 使用CMSIS-DSP库进行定点FFT(Cortex-M4F)
#include "arm_math.h"

#define FFT_SIZE 256
q15_t input[FFT_SIZE * 2];  // 实部+虚部交替存储
q15_t output[FFT_SIZE];
arm_rfft_instance_q15 fft_inst;

// 初始化FFT
arm_rfft_init_q15(&fft_inst, FFT_SIZE, 0, 1);

// 执行FFT(输入为加速度X轴数据)
arm_rfft_q15(&fft_inst, input, output, 1);

// 计算频谱能量(取前FFT_SIZE/2个频点)
uint32_t energy = 0;
for (int i = 0; i < FFT_SIZE/2; i++) {
    energy += (uint32_t)(output[i] * output[i]) >> 15;
}

特征选择策略:并非特征越多越好。在TinyML中,每个特征都会增加模型输入维度和计算量。建议采用以下流程:先在PC端用全部候选特征训练模型,通过特征重要性排序(如随机森林的特征重要性)筛选Top 10~20个特征;然后在MCU上实现这些特征的计算,验证实时性;最后在真实硬件上测试模型准确率,确保特征在定点数计算下的精度损失可接受。

案例复盘:某团队开发手腕动作识别项目,初始提取了6轴×8个特征=48维特征,模型准确率92%。但部署到MCU后发现,特征计算耗时120ms,超过50ms的实时性要求。通过分析发现,FFT特征(6轴×2个)占用了60%的计算时间,但对准确率贡献仅3%。于是将FFT特征替换为过零率(计算量O(N)),特征维度降至36维,计算耗时降至35ms,准确率仅下降1.5%至90.5%,满足实时性要求。

4.6 常见误区与总结

常见误区:

  • 误区一:采样率越高越好。高采样率导致数据量激增,MCU存储和计算压力增大,功耗上升,但准确率提升有限。应根据动作频率选择合适采样率。
  • 误区二:忽略传感器校准。IMU存在零偏和尺度因子误差,未校准的数据会导致特征值偏移。建议在采集前进行静态校准(采集静止数据计算零偏)和六面校准(计算尺度因子)。
  • 误区三:窗口重叠率过高。75%重叠率下,相邻窗口高度相关,导致训练集样本冗余,模型过拟合风险增加,且推理计算量增大。
  • 误区四:特征提取在PC端完成,MCU端直接使用模型。这会导致训练与推理环境不一致。必须在MCU上实现相同的特征提取代码,并验证输出一致性。

总结复盘:数据采集与预处理是TinyML运动检测项目的基石。合理的采样率(25~50Hz)、有效的清洗策略(异常值剔除+低通滤波)、恰当的窗口参数(2秒窗口+50%重叠)以及精选的特征组合(5~10个/轴),能够在MCU资源受限的条件下实现高准确率运动识别。建议在项目初期就建立完整的PC端数据流水线,用于验证算法和参数;待方案成熟后,再移植到MCU并进行定点数优化。最终,数据质量决定了模型性能的上限,预处理流水线的设计应始终围绕“在MCU上可实时运行”这一核心约束展开。