4. 数据准备与预处理:从原始数据到DSP能吃的“干净饭”
数据准备这步,说白了就是给模型“喂饭”。你想想看,模型再厉害,给它一堆乱七八糟、缺胳膊少腿的数据,它也不可能学出好结果。我在DSP部署项目里踩过最大的坑,十有八九都出在数据上。所以这一章,咱们把数据采集、标注、归一化、增强、划分这些基本功,一个一个捋清楚。
核心观点:数据质量决定了模型性能的上限,算法只是逼近这个上限。DSP部署对数据格式、数值范围、内存对齐尤其敏感,预处理做不好,模型在PC上跑得再好,上板子也是白搭。
4.1 数据采集与标注:源头决定一切
数据采集,听起来简单,但门道不少。我见过有人直接从网上下载公开数据集,也不看传感器型号、采样率、环境条件,直接拿来训练,结果部署到自己的设备上,准确率直接腰斩。
采集时,你得想清楚这几件事:
- 传感器匹配:你的DSP板子上用的是几轴IMU?采样率是多少?麦克风阵列是线阵还是圆阵?采集设备必须跟部署硬件一致,或者至少覆盖目标硬件的特性。
- 场景覆盖:别只在实验室里采。我做过一个语音唤醒项目,实验室采集的数据准确率98%,一放到嘈杂的商场里,直接掉到60%。后来我专门去商场、地铁、路边补采了噪声数据,才把性能拉回来。
- 标注一致性:多人标注时,一定要有标注规范。比如“咳嗽声”和“清嗓子”算不算同一类?我曾经因为标注标准不统一,浪费了两周时间重新清洗数据。
我的习惯:每次采集完数据,我会先随机抽100条,自己盲标一遍,再跟标注团队的标注重合度对比。重合度低于95%,说明标注规范有问题,得重新对齐。
4.2 归一化与标准化:让DSP“看懂”你的数据
原始数据往往量纲不同。比如加速度计输出是±16g,陀螺仪是±2000°/s,麦克风是0~1的浮点数。如果不做处理,模型会天然偏向数值大的特征,这显然不合理。
归一化(Normalization):把数据缩放到[0,1]或[-1,1]区间。适合数据分布有明确边界的情况,比如图像像素值0~255。
标准化(Standardization):把数据变成均值为0、标准差为1的分布。适合数据分布近似高斯分布的情况,比如传感器噪声。
在DSP上部署时,我特别推荐用定点化版本的归一化。因为DSP做浮点运算慢,而且很多低端DSP根本没有浮点单元。你可以把归一化参数提前算好,在预处理阶段直接用整数乘加实现。
// 定点化归一化示例:假设输入范围[-100, 100],映射到[0, 255]
// 缩放因子 = 255 / (100 - (-100)) = 1.275
// 为了定点化,我们乘以2^12 = 4096,得到整数因子 = 1.275 * 4096 ≈ 5222
int16_t normalize_fixed(int16_t raw_value) {
// raw_value 范围 [-100, 100]
int32_t tmp = (int32_t)raw_value + 100; // 平移到 [0, 200]
tmp = tmp * 5222; // 乘以定点化缩放因子
tmp = tmp >> 12; // 右移12位还原
if (tmp > 255) tmp = 255;
if (tmp < 0) tmp = 0;
return (int16_t)tmp;
}
注意:定点化时一定要考虑溢出。DSP的乘法器通常是32位或40位,中间结果用int64_t暂存更安全。我曾经因为没注意乘法溢出,在板子上跑出来的结果全是乱的,排查了整整一天。
4.3 数据增强技术:小数据集也能训练出好模型
数据增强,说白了就是“无中生有”。但这里的“无中生有”不是瞎编,而是基于先验知识做合理变换。
常见的数据增强方法:
| 数据类型 | 增强方法 | 适用场景 |
|---|---|---|
| 图像 | 随机裁剪、旋转、翻转、色彩抖动 | 视觉分类、目标检测 |
| 音频 | 加噪声、时间拉伸、音调偏移、混响 | 语音识别、声学事件检测 |
| IMU/传感器 | 随机缩放、旋转、添加高斯噪声、时间扭曲 | 人体活动识别、姿态估计 |
| 时序信号 | 裁剪、缩放、加噪、时间反转 | 故障诊断、生物电信号分析 |
我个人的经验是:增强不是越多越好。有一次我做振动信号故障诊断,把时间反转、加噪、缩放全用上了,结果模型在测试集上反而变差了。后来分析发现,时间反转破坏了故障信号的因果性,模型学到了错误特征。
避坑指南:增强后的数据一定要人工检查一遍。我曾经用音频加混响增强,结果混响加得太重,语音都糊成一团了,模型学到的全是混响特征,而不是语音内容。
4.4 数据集划分:训练/验证/测试
数据划分看似简单,但很多人在这里翻车。最常见的错误是:先做增强,再划分数据集。这会导致训练集和验证集里出现同一条数据的变体,造成数据泄露,验证结果虚高。
正确的流程是:
- 先把原始数据按比例划分成训练集、验证集、测试集。
- 只在训练集上做数据增强。
- 验证集和测试集保持原始数据,不做任何增强。
划分比例建议:
| 数据集规模 | 训练集 | 验证集 | 测试集 |
|---|---|---|---|
| 小(<1万条) | 70% | 15% | 15% |
| 中(1万~10万条) | 80% | 10% | 10% |
| 大(>10万条) | 90% | 5% | 5% |
还有一个容易被忽略的点:时序数据不能随机划分。比如你采集了连续7天的传感器数据,如果随机打乱划分,模型会学到“未来”的信息,这在部署时根本不可能实现。正确的做法是按时间顺序划分,比如前5天做训练,第6天做验证,第7天做测试。
我曾经犯过的错:做ECG心电信号分类时,我把所有病人的数据混在一起随机划分。结果模型在测试集上准确率99%,但部署到新病人身上直接崩了。后来才发现,同一个病人的数据同时出现在训练集和测试集里,模型只是记住了病人特征,而不是学到了疾病特征。
4.5 本章知识体系总览
下面这张图,把数据准备与预处理的整个流程串起来了。你可以把它当作一个检查清单,每次做项目时对照着走一遍。