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

亲手训练第一个小模型

让数据读取、前向、更新和评估都能实际运行。先用人工数据检查程序,再把真实记录放进同一条流程,并保留每次实验的依据。

接续上一篇:训练在改变什么:从一个分数手算起

1 · 先运行完整流程,再逐段阅读

复制示例到独立目录,按 requirements.txt 准备依赖后执行

python train_activity.py --demo --out practice_mlp --epochs 8 --export

--demo 生成三个有规则差异的人工信号类别。它能检查代码能否训练、导出和保存结果,不代表真实传感器或真实识别成绩。用真实数据时改成 --csv capture.csv,并确保符合前面定义的列和单位。脚本禁止同时指定 demo 与 csv。

输出包括 metadata.json、metrics.json、weights.pt、训练集校准输入和独立测试窗口;指定 --export 时还生成 ONNX。教学产物保存在自己的目录,不覆盖仓库原有网络。

2 · 先看小模型接收什么

需 import torch 和 from torch import nn

model = nn.Sequential(
    nn.Flatten(),
    nn.Linear(6*512, 16),
    nn.ReLU(),
    nn.Linear(16, classes),
)

Flatten 把每个窗口展平成 3072 个数,Linear 将它们加权组合成 16 个中间值,再由 ReLU 和下一层输出每类一个分数。classes 是标签类别数。输出称为 logits,即还未转成概率的原始分数。模型不是靠名字知道“走路”,类别顺序来自标签。

3 · 把训练循环逐行读清楚

x 为一批窗口,y 为类别整数;criterion 使用 CrossEntropyLoss

model.train()
logits = model(x)
loss = criterion(logits, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()

train 设置训练模式,前向得到分数。交叉熵接收分数和正确类别,内部按相应规则计算损失,不要先手动 softmax 再把结果误当 logits。zero_grad 清除上次累积梯度,backward 计算本次梯度,step 更新权重。

完整脚本每次取八个窗口,遍历训练集称为一轮 epoch。每轮顺序可以打乱,人员划分和时间窗口仍在此前固定;打乱训练批次不允许把测试窗口混进训练。随机种子与轮数写入实验记录。

4 · 验证怎样与训练分开

验证时不更新参数,也不建立反向求导记录

model.eval()
with torch.no_grad():
    predicted = model(x_valid).argmax(dim=1)

验证集用于比较配置、选择轮数;测试集在方案确定后才作最终独立检查。配套脚本演示固定轮数,输出验证变化及最后模型的测试结果,没有自动搜索最佳结构或早停。自己比较多次实验时,应记录选择依据,避免反复看测试分数选方案。

5 · 保存什么,才能下次继续解释这个模型

文件要回答的问题
weights.pt这一套参数是什么?
metadata.json六轴顺序、单位约定、100 Hz、512 点、步长、统计量与类别数是什么?
metrics.json验证与测试的逐类表现是什么?
model.onnx部署工具可读取的模型计算图与参数。

仓库原活动识别模型为七类,教学默认人工例子只有三个编号类别。新模型不能直接替换旧权重而沿用原来的输出数组、类别表和特征提取位置。先完整理解新产物,再对照现有工程的接口。

动手观察

运行两轮与八轮各保存一个目录,比较验证变化。检查实际输入形状和输出类别数;再用一份自有连续记录替换人工数据,把数据来源写到实验说明中。

资料与代码

配套文件

先复制到独立练习目录;用法见 支线示例说明。