云计算百科
云计算领域专业知识百科平台

深入浅出TinyML 13:原始波形和人工特征应该如何选择?

原始波形把特征学习交给模型,能够保留完整局部形状;人工特征先压缩数据,常能用更小模型完成任务。两种方案的优劣取决于数据规模、任务复杂度和MCU预算。

选择输入形式时,应把预处理计算也计入系统成本。一个很小的特征模型,如果每个窗口需要昂贵FFT和大量浮点统计,整体资源未必更低。

输入方案的成本 = MCU预处理 + 模型推理 + 缓冲区;评价时不能只看神经网络本身。
完成本篇后,你应该能够

  • 比较原始波形、时域特征和频域特征保留的信息与带来的资源成本。
  • 建立三条输入基线,在相同数据划分下判断哪种表示更适合任务。
  • 从同一段信号提取可解释特征,并计算一个简单的类别分离度。
  • 特征是从一段波形计算出的摘要,例如均值、RMS或某个频带的能量。模型可以接收波形,也可以接收这些摘要。

    一、先把核心关系连起来

    原始波形保留最多信息

    1D CNN可以从局部波形中学习边缘、周期和跨通道组合。它减少了人工特征假设,适合事件形状复杂且数据量足够的任务。代价是输入维度和中间激活通常更大。

    原始输入对采样一致性要求更高。采样率、窗口长度、通道顺序或相位关系变化,都可能直接改变模型看到的局部模式。

    图1:原始波形、统计特征和频谱特征的定性取舍

    人工特征把领域知识写进输入

    RMS、峰峰值、峭度和频带能量能够把一个窗口压缩成少量数字。类别差异恰好由这些属性表达时,全连接网络或传统分类器即可完成任务。

    特征也可能删除关键信息。两个波形具有相同RMS和方差时,时序结构仍可能完全不同。特征选择必须通过分布图和消融实验验证。

    表1:三类输入方案的工程差异

    输入优势主要成本
    原始波形 信息完整、可学习局部结构 输入和激活较大、数据需求高
    时域特征 输入小、解释直接 依赖特征假设、可能丢失时序
    频域特征 周期与频带差异清晰 FFT、窗函数和缓冲成本

    二、预处理成本应在目标MCU上测量

    均值和RMS计算简单,FFT、MFCC和高阶统计需要额外缓冲与运算。使用CMSIS-DSP可以提高效率,但仍要记录预处理时间、RAM和常量表Flash。

    PC端特征脚本与MCU实现可能在窗函数、归一化、浮点精度和边界处理上产生差异。黄金样本逐项对比是部署前的必要测试。

    Python:为同一窗口同时生成简单时域特征

    import numpy as np   def time_features(window):     # window形状: [time, channels]     return np.concatenate([         window.mean(axis=0),         window.std(axis=0),         np.sqrt(np.mean(window ** 2, axis=0)),         np.ptp(window, axis=0),     ]).astype(np.float32)   # 与原始波形模型使用同一数据划分进行对照。

    三、用三条平行基线做选择

    可以对同一数据分别训练统计特征+Dense、频谱特征+Dense、原始波形+1D CNN。每条路线统一记录模型指标、预处理时间、推理时间、Flash和RAM。

    最终方案应处于资源与效果的合理前沿。若简单特征已经达到验收要求,增加复杂模型只会扩大维护成本。

    输入表示决定模型需要自己学习多少工作

    原始波形保留时间顺序,卷积网络可以学习局部形状、相位关系和跨通道组合。代价是输入元素多、中间激活大、需要更多训练数据。若任务证据只体现在一个稳定统计量上,直接使用波形会增加不必要的自由度。

    人工特征把领域知识提前写进输入。RMS描述能量,峰峰值描述幅值范围,过零率描述变化快慢,频带能量描述特定频段。24维特征送入小型Dense网络,通常比600点原始窗口节省RAM和计算,但窗口内部细节被压缩后无法恢复。

    特征不是免费计算。平方根、除法、FFT和滤波都消耗时间与工作区。比较方案时要把特征提取和模型推理合并计时;只比较模型Invoke会错误地认为复杂特征方案更快。

    三类输入表示的工程差异

    表示保留信息常见代价
    原始波形 时间顺序与局部形状 输入和激活较大
    时域特征 幅值、能量、分布 丢失细节与相位
    频域特征 周期、谐波和频带 FFT工作区与窗口参数
    混合输入 兼顾领域知识和细节 接口与模型更复杂

    用相同划分建立可归因的对照实验

    先冻结原始记录和按设备划分的训练、验证、测试清单,再从同一窗口生成三种表示。若每条路线重新随机划分,结果差异可能来自测试样本不同。每条路线还要使用相近的训练预算和一致的指标。

    第一条基线可以是少量时域特征加线性分类器,用于判断任务是否简单;第二条是频带能量加小型Dense;第三条是原始窗口加轻量1D CNN。只要简单基线达到业务目标,就没有必要为了结构复杂而增加部署风险。

    错误分析要寻找表示缺失。若两个类别RMS相近但频率不同,时域能量特征难以区分;若故障是短促冲击,整窗平均频谱可能稀释事件。此时更换表示比盲目增加神经元更有针对性。

    特征分离度的直观指标: score = |mean_class_A – mean_class_B| / (std_A + std_B) 它只用于初筛单个特征,不能替代独立测试。

    四、落地检查

  • 三种输入路线使用同一原始数据和同一分组划分。
  • 把特征计算时间、临时缓冲和常量表计入资源。
  • 通过分布图和消融实验确认每个特征的贡献。
  • 训练端与MCU端使用黄金窗口逐项比较。
  • 选择达到验收指标且总系统成本最低的输入方案。
  • 动手:比较原始波形与四个时域特征

    脚本生成两类信号:一类低幅平稳振动,一类包含更高幅值和偶发冲击。它提取均值、RMS、峰峰值和过零率,再计算每个特征的简单分离度。所有数据由固定种子生成。

    实验环境与输入

    • Python 3标准库。
    • 保存为 `compare_representations.py` 并运行。
    • 模拟信号用于学习方法,不作为真实设备性能证据。

    按顺序完成实验

  • 运行脚本,观察每类原始窗口有100个元素,而特征向量只有4个元素。
  • 比较四个特征的分离度,找出对当前模拟任务最有效的特征。
  • 删除故障类冲击,只保留频率差异,再运行并观察哪些时域特征变弱。
  • 增加一个频率相关特征或频带能量,验证表示应随任务证据变化。
  • 可直接运行:从模拟窗口提取特征并计算分离度

    import math import random import statistics   random.seed(13) FS, N = 100, 100   def make_window(label, index):     values = []     for n in range(N):         t = n / FS         amp = 0.20 if label == 0 else 0.42         value = amp * math.sin(2*math.pi*(5+label*2)*t)         value += random.gauss(0, 0.025)         if label == 1 and n == 20 + index % 50:             value += 1.1         values.append(value)     return values   def features(x):     mean = sum(x) / len(x)     rms = math.sqrt(sum(v*v for v in x) / len(x))     p2p = max(x) – min(x)     zcr = sum((a >= 0) != (b >= 0) for a, b in zip(x, x[1:]))/(len(x)-1)     return [mean, rms, p2p, zcr]   groups = {0: [], 1: []} for label in groups:     groups[label] = [features(make_window(label, i)) for i in range(30)]   names = ["mean", "rms", "peak_to_peak", "zero_cross_rate"] print("raw elements/window:", N, "feature elements/window:", len(names)) for j, name in enumerate(names):     a = [row[j] for row in groups[0]]     b = [row[j] for row in groups[1]]     score = abs(statistics.mean(a)-statistics.mean(b)) / (statistics.pstdev(a)+statistics.pstdev(b)+1e-12)     print(f"{name:16s} mean0={statistics.mean(a):.4f} "           f"mean1={statistics.mean(b):.4f} separation={score:.3f}")

    先读懂代码中的关键路径

  • 模拟类差异同时包含幅值、频率和冲击,便于观察不同特征捕获不同证据。
  • features只用当前窗口计算,不读取标签,防止把答案泄漏进输入。
  • 分离度把类间均值差除以类内波动,只做单特征初筛,不代表非线性模型效果。
  • 所有路线必须复用同一窗口ID,否则表示比较会混入数据划分差异。
  • 你应该观察到什么

    • 特征向量从100个元素压缩到4个元素,直接减少后续Dense层输入。
    • RMS或峰峰值对当前幅值与冲击差异通常具有较高分离度。
    • 删除冲击或修改类别差异后,最有效特征会变化,证明特征选择依赖任务。

    成功标准

  • 三条表示路线使用完全相同的原始样本ID和集合划分。
  • 预处理耗时、模型耗时和RAM一起进入比较。
  • 最终选择由独立测试、资源和错误类型共同支持。
  • 失败时从哪里查起

    输入表示对照实验常见问题

    现象原因处理
    训练很好、换设备很差 特征包含设备偏置 按设备隔离并检查均值类特征
    特征模型完全分不开 摘要丢失关键时序 加入频域或原始波形路线
    特征路线板端更慢 漏算FFT或除法成本 端到端测预处理加推理

    特征工程的目标是用更低资源保留任务证据。每次添加特征都应说明它描述什么物理属性。

    把实验迁移到真实MCU项目

    把特征函数先用常量、正弦、单脉冲做单元测试,再移植C。计算耗时必须包含滤波、平方根、除法和跨通道操作。

    若选择原始波形,仍需做单位换算和最小质量检查;“端到端学习”不意味着固件可以忽略采样率、通道和饱和。

    把结果再向前推进一步

  • 为你的任务写出三个可能有区分力的物理属性,再映射到特征。
  • 计算600维原始输入与24维特征输入连接16个神经元时的参数量差异。
  • 列出原始、时域、频域三条基线的统一评价表字段。
  • 收束:原始波形与人工特征没有固定胜者。用同一数据、同一划分和完整板端资源账单比较,才能选出适合项目的输入方案。

    参考资料: Arm CMSIS-DSP 官方文档 TensorFlow Lite Micro 官方代码仓库

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 深入浅出TinyML 13:原始波形和人工特征应该如何选择?
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!