4. 数据预处理与标注:数据清洗、时间窗口分割与标签定义
大家好,我是你们的老朋友。今天咱们聊聊数据预处理和标注。说实话,很多做AI的朋友,一上来就急着调模型,结果数据质量不行,后面全白干。我在好几个项目里都吃过这个亏,所以今天把这部分经验掰开揉碎了讲给你听。
核心观点:数据预处理和标注,占整个AI项目工作量的60%以上。别不信,这是真的。
4.1 数据清洗:滤波与去趋势
传感器数据,说白了就是一堆带噪声的原始信号。你想想看,MCU采集到的加速度、温度、电流,哪个不是混着各种干扰?所以第一步,就是清洗。
4.1.1 滤波
滤波的目的很简单——把有用的信号留下,把没用的噪声滤掉。我个人习惯用两种方法:
- 低通滤波:适合去除高频噪声。比如你采集人体运动数据,步频一般不超过5Hz,那50Hz的电源噪声就该滤掉。
- 中值滤波:对付突发性的尖峰噪声特别管用。我在做工业设备振动监测时,经常遇到传感器被碰一下产生的大幅值毛刺,中值滤波一上,干净利落。
这里给个简单的滑动平均滤波代码,在MCU上跑起来很轻量:
// 滑动平均滤波,窗口大小N
#define N 10
float buffer[N];
int index = 0;
float moving_average(float new_sample) {
static float sum = 0;
static int count = 0;
if (count < N) {
sum += new_sample;
buffer[index] = new_sample;
index = (index + 1) % N;
count++;
return sum / count;
} else {
sum -= buffer[index];
sum += new_sample;
buffer[index] = new_sample;
index = (index + 1) % N;
return sum / N;
}
}
小提示:窗口N选多大?经验值是信号主周期的2-5倍。比如你采集的步态信号周期约0.5秒,采样率100Hz,那N取100-250比较合适。
4.1.2 去趋势
去趋势,说白了就是把信号中的缓慢变化成分去掉。比如温度传感器,环境温度从早上到下午慢慢升高,这个趋势会掩盖你真正关心的振动细节。
我曾经在一个可穿戴设备项目里,没做去趋势,结果模型把温度漂移当成了用户活动,闹了大笑话。常用的方法有两种:
- 差分法:简单粗暴,用当前值减去前一个值。适合实时处理。
- 多项式拟合:精度高,但计算量大,适合离线分析。
4.2 时间窗口分割
原始数据是一长串时间序列,你不能直接扔给模型。为什么?因为模型需要看到一段“有意义”的片段。这就涉及到窗口分割。
4.2.1 固定窗口
固定窗口,就是一刀切。比如每256个采样点作为一个样本。优点是简单,缺点是可能把两个不同状态切到一个窗口里。
举个例子:你监测电机运行状态,正常转和异常振动可能就隔了0.1秒。固定窗口一划,两个状态混在一起,模型就懵了。
4.2.2 滑动窗口
滑动窗口更灵活。窗口长度固定,但每次只滑动一小步。比如窗口256点,步长32点。这样相邻窗口有大量重叠,信息冗余度高,模型学得更稳。
我建议你这样做:
- 先确定窗口长度:至少包含2-3个完整的事件周期。
- 再确定步长:一般是窗口长度的1/8到1/4。
- 最后做数据增强:滑动窗口天然就是数据增强,一个长序列能生成几十个样本。
// 滑动窗口分割伪代码
#define WINDOW_SIZE 256
#define STEP_SIZE 32
void sliding_window(float* data, int data_len) {
int start = 0;
int sample_id = 0;
while (start + WINDOW_SIZE <= data_len) {
// 取出 data[start] 到 data[start+WINDOW_SIZE-1] 作为一个样本
extract_sample(data, start, WINDOW_SIZE, sample_id);
start += STEP_SIZE;
sample_id++;
}
}
注意:滑动窗口会产生大量样本,MCU内存可能扛不住。建议在PC上预处理完,再把标注好的数据集烧录到设备上。
4.3 标签定义与标注策略
标签,就是告诉模型“这段数据是什么”。标签定义得好不好,直接决定模型能不能学会。
4.3.1 正常/异常分类
这是最简单的二分类。比如设备正常运转是0,出现故障是1。但这里有个坑——异常样本往往很少。我在做电机故障诊断时,正常数据几万条,异常数据只有几十条。
怎么办?两个思路:
- 数据合成:人为制造一些异常模式,加进去。
- 异常检测:用单分类模型,只学正常模式,偏离太多的就算异常。
4.3.2 多状态分类
现实场景中,设备往往有多个状态。比如:
| 状态 | 标签 | 描述 |
|---|---|---|
| 待机 | 0 | 设备上电但未运行 |
| 正常运行 | 1 | 额定负载下稳定运行 |
| 过载 | 2 | 负载超过额定值20%以上 |
| 故障 | 3 | 轴承磨损、转子不平衡等 |
标注时要注意:状态切换的过渡区,最好别标。比如从待机到正常运行,中间有1-2秒的过渡,这段数据直接扔掉,不然模型会学混乱。
我的经验:标注策略上,宁可少标,不要错标。我曾经为了凑样本量,把过渡区也标上了,结果模型准确率从92%掉到78%。后来花了三天重新清洗数据,才救回来。
4.4 本章知识体系
下面这张图,把本章的核心逻辑串起来了。你可以把它当作一个检查清单,做项目时对着来:
嗯,以上就是数据预处理与标注的核心内容。说实话,这部分看起来琐碎,但做扎实了,后面模型训练会顺很多。我见过太多人在这上面翻车,希望你能少走弯路。
最后一个小建议:每次做数据预处理,都写一个处理日志。哪天模型效果不好,回头查日志,能快速定位问题。这个习惯救过我很多次。