2. 时序数据基础
在TinyML时序项目交付中,数据是一切模型性能的根基。与图像或文本数据不同,时间序列数据具有天然的先后顺序、时间依赖性和非平稳特性。若对时序数据的基本概念缺乏系统理解,后续的预处理、特征工程、模型训练与板端部署都将建立在不可靠的基础之上。本章将围绕时间序列数据的核心特性、采样率与时间戳的工程含义、缺失值与异常值的判定与处理策略展开,为后续章节的模型指标设计与板端验证打下坚实的数据认知基础。
上图展示了时间序列数据的核心特性与工程链路之间的关系。时间顺序性、时间依赖性、非平稳性和多尺度性共同定义了时序数据的本质,而采样率、时间戳、缺失值和异常值则是数据质量的具体维度。从数据采集到板端部署,每一个环节都受这些基础概念制约。下面逐一展开。
2.1 时间序列数据的核心特性
核心原理:时间序列数据是按时间顺序排列的观测值集合,其本质特征在于“顺序即信息”。与独立同分布假设下的普通样本不同,时序数据中相邻观测值之间往往存在强关联,且统计特性可能随时间变化。理解这些特性是选择模型架构、设计验证方案的前提。
- 时间顺序性:观测值的排列顺序不可打乱。例如,传感器在第1秒采集的温度与第10秒采集的温度交换位置后,数据便失去物理意义。在TinyML场景中,滑动窗口的构造必须严格保持时间顺序。
- 时间依赖性:当前时刻的观测值往往与过去若干时刻的值相关。例如,惯性测量单元(IMU)的加速度数据中,当前帧的姿态变化与前一帧密切相关。这种依赖关系可以用自相关函数(ACF)或偏自相关函数(PACF)量化。
- 非平稳性:时序数据的均值、方差或自相关结构可能随时间变化。例如,工业设备振动信号在启动阶段与稳定运行阶段的统计特性明显不同。TinyML模型若在平稳假设下训练,部署到非平稳环境时性能会显著退化。
- 多尺度性:数据中同时存在短时波动(如高频噪声)和长期趋势(如缓慢漂移)。例如,环境温度监测数据中,秒级波动反映瞬时扰动,小时级变化反映昼夜节律,天级变化反映天气系统。
| 特性 | 定义 | TinyML中的典型影响 | 应对策略 |
|---|---|---|---|
| 时间顺序性 | 观测值按时间先后排列 | 窗口切片必须保持顺序 | 使用固定步长滑动窗口 |
| 时间依赖性 | 当前值与历史值相关 | 模型需捕捉短期记忆 | 采用1D-CNN或LSTM/GRU |
| 非平稳性 | 统计特性随时间变化 | 训练集与测试集分布偏移 | 差分、归一化、分段建模 |
| 多尺度性 | 不同时间尺度上的模式 | 单一窗口难以覆盖全尺度 | 多分辨率特征融合 |
实战判断方法:在项目启动时,先用Python的statsmodels库绘制ACF/PACF图,观察自相关衰减速度;再用滚动统计量(如滚动均值、滚动标准差)检查平稳性。若滚动均值明显漂移,则需考虑差分或分段处理。
2.2 采样率与时间戳:数据的时间基准
核心原理:采样率(单位Hz)决定了时间序列的时间分辨率,即相邻两个采样点之间的时间间隔。时间戳则是每个采样点对应的或相对时间标记。两者共同定义了数据的“时间坐标系”,任何时序分析都建立在这个坐标系之上。
采样率的选择:根据奈奎斯特采样定理,采样率必须至少为信号最高频率成分的2倍,才能无失真地重建原始信号。但在TinyML场景中,采样率并非越高越好:高采样率意味着更大的数据量、更高的功耗和更多的存储开销。例如,一个3轴加速度计以100Hz采样,每秒钟产生300个浮点数,若每个浮点占4字节,则每分钟产生72KB数据,对MCU的RAM和Flash都是沉重负担。
时间戳的工程含义:时间戳不仅是记录时刻,更是数据对齐与同步的基准。在多传感器融合场景中,不同传感器可能具有不同的采样率(如加速度计100Hz、陀螺仪200Hz、麦克风16kHz),必须通过时间戳进行插值或重采样对齐。此外,时间戳的精度直接影响特征提取的准确性——例如计算振动信号的峰值频率时,时间戳抖动会导致频谱泄漏。
// 伪代码示例:基于时间戳的重采样对齐
// 输入:accel_ts[] (100Hz), gyro_ts[] (200Hz)
// 输出:对齐后的统一时间轴 (100Hz)
for each target_time in uniform_100Hz_axis:
find nearest accel sample by timestamp
interpolate gyro samples around target_time
append aligned sample to output buffer
常见误区:许多开发者直接使用“采样序号”代替时间戳,这在采样率恒定时可行,但一旦出现采样间隔抖动(如RTOS调度延迟、中断抢占),序号与真实时间之间就会产生偏差。务必在数据采集时记录硬件时钟或系统滴答计数器的值作为时间戳。
| 采样率场景 | 推荐范围 | 时间戳精度要求 | 典型应用 |
|---|---|---|---|
| 人体活动识别(IMU) | 25-100 Hz | ±1 ms | 步数检测、跌倒检测 |
| 语音关键词唤醒 | 8-16 kHz | ±0.1 ms | 唤醒词检测 |
| 工业振动监测 | 1-10 kHz | ±0.01 ms | 轴承故障诊断 |
| 环境温湿度 | 0.1-1 Hz | ±100 ms | 农业大棚监控 |
2.3 缺失值:成因、检测与处理
核心原理:缺失值是指时间序列中某些时间点没有观测记录。在TinyML项目中,缺失值的成因多种多样:传感器临时掉线、无线传输丢包、存储缓冲区溢出、设备重启等。缺失值不仅减少了有效数据量,更严重的是破坏了时间序列的连续性,可能导致特征提取错误或模型推理偏差。
缺失模式分类:
- 完全随机缺失(MCAR):缺失与否与观测值本身无关,如随机丢包。处理相对简单,可直接删除或插补。
- 随机缺失(MAR):缺失与否与其他观测变量相关,如温度过高导致传感器保护性关机。需要结合其他变量进行插补。
- 非随机缺失(MNAR):缺失与否与缺失值本身相关,如传感器量程饱和导致数据截断。这类缺失最难处理,需谨慎建模。
检测方法:在板端或PC端,通过检查时间戳间隔是否大于理论采样间隔来判断缺失。例如,100Hz采样理论间隔为10ms,若相邻时间戳间隔为20ms,则中间缺失1个点。
# Python示例:检测缺失时间戳
import numpy as np
expected_interval_ms = 10 # 100Hz
timestamps_ms = np.array([...]) # 实际时间戳
diffs = np.diff(timestamps_ms)
missing_indices = np.where(diffs > expected_interval_ms * 1.5)[0]
print(f"检测到 {len(missing_indices)} 处缺失,最大间隔 {diffs.max()} ms")
处理策略:
- 前向填充(Forward Fill):用前一个有效值填充缺失点,适用于缓慢变化的信号(如温度)。
- 线性插值:用缺失点前后两个有效值进行线性插值,适用于近似线性的信号段。
- 样条插值:对非线性信号更平滑,但计算量较大,不适合板端实时处理。
- 模型预测插补:使用ARIMA或简单RNN预测缺失值,精度高但复杂度高,通常离线完成。
经验提醒:在TinyML板端推理阶段,若实时数据流中出现缺失,通常采用“保持上一有效值”的策略,因为MCU上运行复杂的插值算法会引入不可接受的延迟。离线训练时则可以使用更精细的插补方法。
2.4 异常值:识别与处理
核心原理:异常值(Outlier)是显著偏离正常模式的数据点。在时序数据中,异常值分为两类:全局异常(数值超出正常范围)和上下文异常(数值在全局范围内正常,但在特定时间上下文中异常)。例如,室温在25°C正常,但若在1秒内从25°C跳变到40°C,则属于上下文异常。
识别方法:
- 统计方法:基于均值±k倍标准差(k通常取3),或使用四分位距(IQR)方法。适用于近似正态分布的数据。
- 滑动窗口方法:计算窗口内的局部均值与标准差,若当前点偏离局部均值超过阈值,则标记为异常。适用于非平稳数据。
- 基于模型的方法:训练一个自编码器或One-Class SVM,计算重建误差或决策函数值。精度高但计算量大,通常离线使用。
# 滑动窗口异常检测伪代码
window_size = 50
threshold = 3.0
for i in range(window_size, len(data)):
window = data[i-window_size:i]
mean = np.mean(window)
std = np.std(window)
if abs(data[i] - mean) > threshold * std:
mark_as_outlier(i)
处理策略:
- 删除:适用于明显由传感器故障或传输错误导致的异常点,但删除过多会破坏时间连续性。
- 替换:用中位数、前后均值或插值结果替换异常值,保留时间点位置。
- 标记:在特征中增加“是否为异常”的布尔标志,让模型自行学习异常模式。这在异常检测任务中尤其有效。
风险提示:在TinyML异常检测项目中,异常值往往正是我们想要检测的目标(如设备故障初期的振动突变)。因此,在训练阶段不要盲目删除所有异常值,而应区分“数据质量异常”和“目标事件异常”。前者需要清洗,后者需要保留并标注。
2.5 案例拆解:IMU跌倒检测数据规范
场景背景:某团队开发基于MCU的老年人跌倒检测系统,使用3轴加速度计+3轴陀螺仪,采样率50Hz,数据通过BLE传输到手机端标注,再离线训练TinyML模型部署到Cortex-M4芯片。
初始现象与问题:采集的原始数据中,约5%的时间戳间隔异常(大于20ms或小于15ms),部分时间段出现连续缺失(最长缺失2秒),且存在大量因BLE丢包导致的瞬时跳变值(加速度突增到±16g)。若直接使用这些数据训练,模型在板端测试时误报率高达30%。
关键数据与参数:
- 采样率:50Hz,理论间隔20ms
- 加速度量程:±8g,16位ADC
- BLE传输:每10ms发送一个数据包,每包包含6轴数据
- 标注类别:跌倒(正样本)、日常活动(负样本)
分析判断过程:
- 首先统计时间戳间隔分布,发现约3%的间隔为40ms(丢1个点),1%为60ms(丢2个点),0.5%为100ms以上(连续丢包)。
- 检查加速度幅值,发现约2%的样本幅值超过10g,其中一半是真实跌倒瞬间的高冲击,另一半是BLE传输错误导致的随机跳变。
- 通过可视化对比,发现真实跌倒的冲击波形持续约200-300ms,而传输错误表现为单点或双点孤立尖峰。
实际操作步骤:
- 时间戳校正:对间隔大于25ms的缺口,使用线性插值填充缺失点,并标记为“插值数据”。
- 异常值分类:计算每个点的滑动窗口均值(窗口50点)和标准差,若当前点偏离超过5倍标准差,且前后两点均正常,则判定为传输错误,用前后均值替换;若连续3点以上偏离,则保留为候选跌倒事件。
- 数据对齐:将加速度计和陀螺仪数据按时间戳对齐到统一的50Hz时间轴。
- 窗口切片:使用2秒窗口(100点),步长0.5秒,生成训练样本。
结果对比:清洗前模型在验证集上的F1-score为0.72,误报率30%;清洗后F1-score提升至0.89,误报率降至8%。板端实测中,跌倒检测延迟从平均350ms降至280ms,且未出现因数据缺失导致的系统卡死。
风险与代价:插值操作引入了约3%的合成数据,可能轻微影响模型对真实数据分布的拟合;替换异常值时若阈值设置过严,可能误删真实跌倒样本。团队最终保留了“插值标记”作为附加特征,让模型自行学习插值数据与真实数据的差异。
复盘经验:数据清洗不是简单的“删掉坏的”,而是需要结合业务语义区分“数据质量异常”与“目标事件异常”。在TinyML项目中,建议在数据采集阶段就记录时间戳、信号质量指示(如RSSI)等元数据,为后续清洗提供依据。
2.6 常见误区与总结复盘
| 误区 | 后果 | 正确做法 |
|---|---|---|
| 忽略时间戳,仅用序号 | 采样抖动导致特征失真 | 始终记录硬件时间戳 |
| 采样率越高越好 | 存储/功耗超限,模型过拟合噪声 | 根据信号带宽和任务需求选择 |
| 所有缺失值都线性插值 | 在突变段引入虚假平滑 | 根据缺失长度和信号特性选择策略 |
| 所有异常值都删除 | 丢失真实事件样本 | 区分数据质量异常与目标事件异常 |
| 训练集和测试集随机划分 | 时间泄漏导致指标虚高 | 按时间顺序划分,前80%训练,后20%测试 |