4、特征向量与模型输入:什么是特征向量、模型输入格式要求、常见数据类型(float32、q7、q15、q31)

在嵌入式机器学习与数字信号处理(DSP)系统中,模型推理的起点并非算法本身,而是数据如何被组织、量化并送入模型。CMSIS-DSP 作为 ARM Cortex-M 系列处理器上的官方 DSP 库,其核心任务之一就是高效地完成特征向量的预处理与格式转换。理解特征向量的本质、模型输入的内存布局要求,以及 q7、q15、q31 等定点数据类型的数学含义,是确保模型在资源受限设备上正确、高效运行的前提。本章将系统拆解这三个关键环节,并给出可落地的工程实践指南。

特征向量 → 模型输入适配链路 特征向量 维度:N×1 或 1×N 来源:时域/频域/统计量 语义:物理量的数值映射 数据量化 float32 → q31/q15/q7 缩放因子:2^(n-1) 精度与范围权衡 内存布局 连续数组 / 对齐 通道交错 / 平面存储 CMSIS-DSP 要求 模型推理 NN/ML DSP 算法 CMSIS-DSP 常见数据类型对比 float32 范围:±3.4×10^38 精度:7位有效数字 内存:4字节/样本 速度:FPU 加速 q31 范围:[-1, 1) 精度:2^-31 ≈ 4.66e-10 内存:4字节/样本 适用:高精度 DSP q15 范围:[-1, 1) 精度:2^-15 ≈ 3.05e-5 内存:2字节/样本 适用:音频/控制 q7 范围:[-1, 1) 精度:2^-7 ≈ 7.81e-3 内存:1字节/样本 适用:神经网络/传感器

4.1 特征向量的本质与构建

特征向量是原始信号经过变换、降维或统计提炼后形成的数值序列,它是模型推理的直接输入。在 CMSIS-DSP 语境下,特征向量通常以数组形式存储于内存中,每个元素代表一个维度的特征值。例如,一个 256 点的 FFT 频谱幅值序列、一组 MFCC 倒谱系数、或由加速度计三轴数据计算出的均值、方差、峰值等统计量,都可以构成特征向量。

构建特征向量时,必须遵循以下原则:

  • 维度固定:模型输入维度是编译期常量,特征向量长度必须严格匹配。若使用 CMSIS-DSP 的 arm_mat_* 矩阵函数,还需注意行/列主序。
  • 数值范围可控:浮点特征值应归一化到 [-1, 1] 或 [0, 1] 区间,以便后续定点量化时充分利用动态范围。
  • 物理意义明确:每个维度应具有可解释性,避免冗余或高度相关的特征导致模型训练不稳定。
核心原理:特征向量是“物理世界 → 数学空间”的桥梁。CMSIS-DSP 提供 arm_scale_f32、arm_offset_f32 等函数,可对浮点特征进行线性变换(缩放+偏移),使其分布适配模型输入的期望范围。例如,将加速度计原始读数(±16g)映射到 [-1, 1] 区间,只需计算 scale = 1/16,然后调用 arm_scale_f32。

4.2 模型输入的格式要求

不同推理框架(如 TensorFlow Lite Micro、CMSIS-NN、自研 C 代码)对输入张量的内存布局有严格约定。常见要求包括:

格式项要求说明CMSIS-DSP 对应操作
数据连续性特征数据必须存储在连续内存块中,不能有间隔arm_copy_f32 / arm_fill_q15
字节对齐通常要求 4 字节对齐(q31/float32)或 2 字节对齐(q15)使用 __ALIGNED(4) 或 CMSIS 提供的 ALIGN_STRUCT
通道布局多通道数据需按 CHW(通道-高-宽)或 HWC 排列arm_transpose_q15 进行矩阵转置
量化参数定点模型需提供 scale 和 zero_pointarm_scale_q31 / arm_offset_q7

在 Cortex-M 处理器上,非对齐访问会导致 HardFault 或性能骤降。因此,定义特征向量缓冲区时,应使用 __ALIGNED(4) 或 alignas(4) 属性。CMSIS-DSP 的许多函数(如 arm_cfft_f32)要求输入输出缓冲区 4 字节对齐,否则结果不可预测。

4.3 常见数据类型深入解析

CMSIS-DSP 支持三种定点格式和一种浮点格式,每种格式在精度、内存占用和运算速度上各有取舍。

4.3.1 float32(单精度浮点)

float32 是 Cortex-M4/M7/M33 等带有 FPU(浮点运算单元)器件的首选类型。其动态范围极大,无需担心溢出,但内存占用为 4 字节/样本,且在没有 FPU 的 Cortex-M0/M0+ 上,软件浮点模拟会非常缓慢。使用场景包括:音频处理中的中间计算、模型训练的离线仿真、以及精度要求极高的控制环路。

4.3.2 q31(1.31 定点格式)

q31 将 32 位有符号整数解释为 [-1, 1) 区间的小数,最低位(LSB)代表 2^-31。它保留了 float32 的内存占用,但运算完全基于整数指令,在无 FPU 的芯片上速度远快于软件浮点。q31 常用于需要高精度的 DSP 算法,如 PID 控制器、IIR 滤波器。CMSIS-DSP 提供 arm_q31_to_float 和 arm_float_to_q31 进行互转,转换时需指定缩放因子(通常为 2^31)。

4.3.3 q15(1.15 定点格式)

q15 使用 16 位存储,LSB 代表 2^-15,精度约为 3.05e-5。它是音频处理和通信基带的经典格式,因为 16 位 ADC/DAC 的原始数据天然就是 q15 格式。CMSIS-DSP 的 FIR、IIR、FFT 等函数均有 q15 版本,且支持饱和运算(arm_sat_q15),防止溢出。内存占用仅为 float32 的一半,适合存储大量采样数据。

4.3.4 q7(1.7 定点格式)

q7 是 8 位定点格式,LSB 代表 2^-7,精度约 7.81e-3。它主要用于神经网络推理(CMSIS-NN 库)和传感器数据预处理。由于内存占用极小(1 字节/样本),可以在 RAM 有限的 MCU 上容纳更大的特征图。但精度较低,使用时需确保输入数据已归一化到 [-1, 1] 且分布均匀,否则量化误差会显著影响模型精度。

风险提示:定点格式的加减法可能溢出。例如,两个 q15 数相加,结果可能超过 [-1, 1) 范围。CMSIS-DSP 提供饱和运算函数(如 arm_add_q15 内部使用饱和指令),但若手动编写循环,必须使用 __SSAT 指令或 CMSIS 提供的饱和宏,否则会产生不可预测的环绕行为。

4.4 实战场景:从 float32 特征到 q7 模型输入的转换

假设我们有一个基于 Cortex-M4 的振动监测设备,采集 3 轴加速度数据,每轴提取 8 个频域特征(共 24 维特征向量)。模型输入要求为 q7 格式,且每个特征需归一化到 [-1, 1]。

初始现象:直接使用 float32 特征送入 CMSIS-NN 模型,推理时间 12ms,但 RAM 占用 96 字节(24×4),且模型精度仅 89%。

目标:将特征转换为 q7,RAM 降至 24 字节,推理时间缩短至 5ms,精度损失不超过 1%。

操作步骤:

  1. 离线统计:在 PC 端对 10000 组训练样本计算每个维度的最大值和最小值,得到 scale[i] = max(abs(min), abs(max)),用于归一化。
  2. 浮点归一化:在 MCU 上,对每个特征 f[i] 执行 f_norm[i] = f[i] / scale[i],确保结果在 [-1, 1] 内。
  3. 转换为 q7:调用 arm_float_to_q7(f_norm, q7_buffer, 24, 1),其中第 4 个参数为缩放因子(此处为 1,因为已归一化)。
  4. 验证:将 q7 数据反变换回 float,计算最大误差。若误差超过 0.01,则需检查是否有特征值超出归一化范围。

结果对比:

指标float32q7变化
RAM 占用96 B24 B-75%
推理时间12 ms5 ms-58%
模型精度89%88.2%-0.8%

复盘经验:q7 量化误差主要来源于归一化不充分。若某个特征在训练集中最大值为 0.8,但实际部署时出现 0.9 的异常值,则会被饱和截断为 0.992(q7 最大值),导致信息丢失。解决方案是保留 10% 的头部裕量,即 scale[i] 乘以 1.1 的安全系数。

4.5 常见误区与总结

  • 误区一:所有数据都适合 q7。若特征值分布极不均匀(如大部分接近 0,少数接近 ±1),q7 的均匀量化会浪费大量动态范围。此时应使用非均匀量化或考虑 q15。
  • 误区二:忽略字节对齐。CMSIS-DSP 的 FFT 函数要求缓冲区 4 字节对齐,若使用 uint8_t 数组存储 q7 数据,再强制转换为 q7_t*,可能导致对齐错误。应使用 __ALIGNED(4) static q7_t buffer[24]。
  • 误区三:转换时忘记缩放因子。arm_float_to_q31 的第 4 个参数是缩放因子,若设为 1,则浮点 0.5 会转换为整数 0(因为 0.5×1=0.5,取整为 0),造成严重失真。正确做法是传入 2^31 或 2^15。
  • 误区四:混合使用不同定点格式。在同一个计算图中,q15 和 q31 不能直接相加,必须先统一格式。CMSIS-DSP 提供 arm_q15_to_q31 等转换函数,但会引入额外开销。
经验法则:选择数据类型时,遵循“够用就好”原则。若 MCU 有 FPU 且 RAM 充足,优先使用 float32;若内存紧张或需要极致速度,先评估 q15,再考虑 q7。对于神经网络模型,CMSIS-NN 官方建议使用 q7 作为输入,但需配合 per-channel 量化(即每个特征维度独立的 scale)以提升精度。