SMARTWATCH 学习手册有 C 基础 · 嵌入式从零开始
支线四 / 数据、训练与部署 / 03

一个点、一段窗口和一批数据有什么区别

从一张六轴表开始,用小数组看清下标,再扩展到 512 点。最后解释输入形状、滑动窗口和归一化为什么必须与模型一致。

接续上一篇:怎样准备一份能用于训练的数据

1 · 先在四个采样点上画清数组

Python 小实验 · 相同采样值以两种索引访问

import numpy as np

rows = np.arange(24, dtype=np.float32).reshape(4, 6)
print(rows)          # 时间、通道
channels = rows.T
print(channels)      # 通道、时间
print(rows[2, 1], channels[1, 2])

rows 一行是同一时刻的六个通道,形状为 [4,6];转置后每行是一条通道,形状为 [6,4]。shape 描述每一维有多少项,dtype 描述每项的存储类型。这些规则比“输入总共有 24 个数”更具体,因为相同数目也可能有不同排列。

2 · 512 点表示多长时间

活动识别使用 100 Hz 数据,512 点约覆盖 5.12 秒。模型至少要积累这段数据,不能在开机第一点就得到完整窗口。一个原始采样点、一份 512 点窗口和一次推理是三个计数。

窗口每前进 256 点重新形成一个样本,就是约 2.56 秒的步长;窗口之间存在重叠。这个步长用于教学训练脚本。当前固件以每批 25 点加入环形数组,填满以后每批都可推理,具有更大的重叠;比较训练与运行时要记录这种差别。

3 · 批次和张量从哪里来

批大小 2、六通道、每通道 512 点

window = np.zeros((6, 512), dtype=np.float32)
batch = np.stack([window, window])
print(batch.shape)  # (2, 6, 512)

训练一次通常计算几份窗口,它们组成 batch,中文称批次。多维数值数组在训练框架中称为张量;先把它看作带形状和类型的数据,后面才增加自动求梯度能力。PyTorch 的一维卷积按 [批,通道,时间] 接收本例输入。

4 · 不同通道为什么要统一尺度

train_x 为 [窗口,通道,时间];统计量仅从训练数据估计

mean = train_x.mean(axis=(0, 2), keepdims=True)
std = train_x.std(axis=(0, 2), keepdims=True)
std = np.maximum(std, 1e-6)
normalized = (train_x - mean) / std

加速度和角速度的单位、范围不同;减均值、除标准差让模型看到相对变化。axis=(0,2) 表示跨窗口和时间计算,每通道保留自己的统计量;keepdims 保留长度为一的维度,方便与整个数组对应运算。

验证和测试使用训练时保存的统计量,主控也要复现相同处理。不能在每个场景重新取一套均值却仍声称输入相同;也不能把物理单位转换与统计归一化混成一次随意缩放。

5 · 接回 C 数组时,逐个检查位置

C 的扁平数组只是一串数。时间优先布局的下标是 time*6+channel,通道优先布局是 channel*512+time。教学导出模型明确采用后一种布局,再逐元素制作参考输入。

当前 har_inference.c 的 preprocess_window 按 i*6+ch 写入,而网络接口注释给出 6×512。不能只看元素总数便确认两者一致;要结合生成模型的具体输入布局、运行时转换以及同一参考窗口输出核对。教程不会在未验证时改写现有模型或宣称布局已经验收。

动手观察

先用上面的 24 个编号手算两种扁平顺序,再找一个位置故意交换轴。观察 shape 可能合法、数据含义却已经改变。

资料与代码