actpred 预训练与推理测试报告
| 项目 |
值 |
| 日期 |
2026-08-08 |
| 模块 |
actpred |
| 测试人 |
qing |
| 环境 |
Intel Xeon E3-1200 v2 (Ivy Bridge), 4 核, Linux 24.04, Python 3.x, PyTorch (CPU-only) |
| 关联文件 |
config.py, mt_parser.py, pretrain_mt.py, test_actpred.py, export_onnx.py |
一、测试目标
- 验证
action_dim 默认值从 8 改为 18 后模型结构与测试的正确性
- 验证
.mt 脚本 @Action 矩阵解析器的功能正确性
- 执行
.mt 脚本预训练并评估训练收敛情况
- 测量推理延迟与吞吐量
- 调研 PyTorch 对 NPU / 向量计算单元的支持现状
二、action_dim 参数变更验证
2.1 变更内容
| 文件 |
变更 |
config.py |
action_dim: int = 8 → 18 |
test_actpred.py |
test_forward_simple_mlp / test_forward_simple_gru 的 shape 断言 8 → 18;test_default_config 断言 8 → 18 |
README.md |
训练命令、推理示例、DataRecorder 示例、配置表说明 |
2.2 参数量对比
| action_dim |
参数量 |
增量 |
输出形状 |
| 8 |
138,184 (0.138M) |
基准 |
(batch, 8) |
| 18 |
142,034 (0.142M) |
+3,850 |
(batch, 18) |
| 30 |
146,654 (0.147M) |
+8,470 |
(batch, 30) |
每增加 1 维 action_dim 约多 385 参数(action_encoder 输入层 +5×64=320,head 输出层 +64+1=65),对 0.14M 的模型影响微乎其微。
2.3 单元测试
17 项测试全部通过,包括:
test_forward_simple_mlp(action_dim=18, output shape (2, 18))
test_forward_simple_gru(action_dim=18, output shape (2, 18))
test_default_config(assert action_dim == 18)
test_forward_dynamic_batch(action_dim=4, 未改,测试不同维度兼容性)
三、.mt 脚本解析器测试
3.1 解析器实现
mt_parser.py 实现了轻量级 .mt 脚本 @Action 矩阵解析器:
- 正则提取
@Action ... @ 块(先去除 # 注释行,避免注释中的 @Action 干扰)
- 按行解析,去除行尾
;,按空白分割列
- 第一行为表头(列名如
s1.A, s2.A),跳过
- 占位符前向填充(沿用上一行同列值)
- 返回
(n_data_rows, n_cols) float32 矩阵
3.2 解析结果
从 ../bot4cj/scripts/ 目录解析到 13 个 @Action 矩阵:
| 文件 |
shape |
列数 |
数据行 |
| jump.mt |
(5, 12) |
12 |
5 |
| left-hand.mt |
(4, 12) |
12 |
4 |
| left-turn.mt |
(11, 12) |
12 |
11 |
| lie-down.mt |
(6, 12) |
12 |
6 |
| rght-hand.mt |
(4, 12) |
12 |
4 |
| std.mt |
(1, 12) |
12 |
1 |
| stdd.mt |
(7, 12) |
12 |
7 |
| t0.mt |
(10, 12) |
12 |
10 |
| t1.mt |
(1, 2) |
2 |
1 |
| tilt-b.mt |
(7, 12) |
12 |
7 |
| tilt-f.mt |
(7, 12) |
12 |
7 |
| tilt-l.mt |
(7, 12) |
12 |
7 |
| tilt-r.mt |
(7, 12) |
12 |
7 |
3.3 占位符填充验证
以 jump.mt 为例:
前向填充正确。- 占位符被正确替换为上一行同列的值。
3.4 列数适配
.mt 脚本 12 列 vs action_dim=18:解析器自动补零至 18 列,不影响训练。t1.mt(2 列)同样补零至 18 列。
四、预训练测试
4.1 训练配置
| 参数 |
值 |
| 数据来源 |
../bot4cj/scripts/*.mt (13 文件) |
| 总样本数 |
22(history_len=5 滑动窗口) |
| 训练集 |
19 样本(85%) |
| 验证集 |
3 样本(15%) |
| 模型 |
ActionPredictor (SimpleCNN + MLP, 142,034 参数) |
| 输入 |
零图像占位 (1, 3, 64, 64) + action_history (1, 5, 18) |
| 损失函数 |
MSE Loss |
| 优化器 |
AdamW (lr=0.001, weight_decay=1e-4) |
| 学习率调度 |
CosineAnnealingLR (T_max=200) |
| 数据增强 |
Gaussian noise (std=1.0) |
| batch_size |
8 |
| 最大轮数 |
200 |
| 早停耐心值 |
30 |
| 随机种子 |
42 |
4.2 训练过程
| Epoch |
train_loss |
val_loss |
备注 |
| 1 |
3340.79 |
2125.46 |
初始 loss |
| 7 |
2106.50 |
1051.22 |
快速下降阶段 |
| 12 |
1404.49 |
917.81 |
|
| 20 |
~300 |
~400 |
进入收敛区 |
| 48 |
171.64 |
228.02 |
|
| 63 |
124.30 |
190.58 |
最优 checkpoint |
| 93 |
92.29 |
223.89 |
早停触发(patience=30) |
4.3 训练结果
| 指标 |
值 |
| 最终轮数 |
93(早停) |
| 最优 val_loss |
190.58(epoch 63) |
| val_loss 下降幅度 |
2125 → 190(-91%) |
| RMSE |
√190 ≈ 13.8 |
| 训练耗时 |
~2-3 分钟(CPU) |
4.4 checkpoint 文件
| 文件 |
大小 |
说明 |
checkpoints/pretrain_best.pt |
1.7 MB |
含 optimizer state,可恢复训练 |
checkpoints/pretrain_best_inference.pt |
572 KB |
仅模型权重 + config,直接推理用 |
4.5 checkpoint 兼容性验证
预训练 checkpoint 可被 ActionPredictorInference 直接加载:
与现有 predict.py 推理管线、export_onnx.py ONNX 导出完全兼容。
五、推理性能基准
5.1 测试方法
- 模型:预训练 checkpoint(
pretrain_best_inference.pt)
- 输入:随机图像 (64, 64, 3) uint8 + 随机 history (5, 18) float32
- warmup:10 次推理后计时
- 测量:1000-2000 次取平均
5.2 结果
| 环节 |
耗时 (ms) |
FPS |
占比 |
| 端到端推理(含预处理) |
1.61 |
622 |
100% |
| 纯前向(含 CNN) |
1.09 |
916 |
100% |
| ├ image_encoder (SimpleCNN) |
0.82 |
— |
75% |
| └ action_encoder + FusionHead |
0.27 |
— |
25% |
5.3 性能评估
- 622 FPS 远超 bot4cj 控制循环所需的 30 FPS(20 倍余量)
- 瓶颈在 image_encoder(75%),但 SimpleCNN 仅 98K 参数,进一步优化收益有限
- 预处理(numpy → tensor + resize)仅占 0.52ms
六、PyTorch NPU / 向量计算单元支持现状
6.1 原生支持
| 硬件 |
支持程度 |
说明 |
| x86 AVX2 |
✅ 最低要求 |
PyTorch 2.x 起强制,不支持的 CPU 回退到非向量化代码 |
| x86 AVX-512 |
✅ oneDNN 后端 |
Intel Xeon Scalable+,torch.compile 自动利用 |
| x86 AMX |
✅ oneDNN 后端 |
Intel Sapphire Rapids+,矩阵乘法加速 |
| ARM NEON |
✅ 长期支持 |
树莓派/手机端 |
| ARM SVE/SVE2 |
✅ PyTorch 2.9+ |
2025 年新增,向量化长度自适应 |
| Intel iGPU (XPU) |
✅ PyTorch 2.5+ |
device="xpu" |
6.2 间接支持(需格式转换)
| 硬件 |
路径 |
说明 |
| Intel NPU |
PyTorch → ONNX → OpenVINO |
Core Ultra 系列内置 NPU |
| Apple ANE |
PyTorch → CoreML |
M1/M2/M3 芯片神经引擎 |
| Qualcomm Hexagon |
PyTorch → ExecuTorch |
手机端 NPU |
| ARM SME2 |
PyTorch → ExecuTorch + KleidiAI |
ARMv9 旗舰核 |
6.3 当前环境分析
测试机器 CPU 为 Intel Xeon E3-1200 v2(Ivy Bridge, 2012 年):
- 支持 AVX(128bit),不支持 AVX2(需 Haswell+)
- PyTorch 可能回退到非向量化代码
- 无独立 GPU,无 NPU
6.4 可行的加速路径
| 路径 |
预估推理 |
说明 |
| 当前(PyTorch CPU) |
1.61 ms (622 FPS) |
可能未启用向量化 |
torch.compile |
~1.0 ms (~1000 FPS) |
自动融合 + oneDNN |
| ONNX → OpenVINO |
~0.5 ms (~2000 FPS) |
自动利用 AVX2/AVX-512/AMX/NPU |
| 换 AVX2 CPU |
~0.5 ms (~2000 FPS) |
任何 Haswell(2013)+ CPU |
6.5 结论
622 FPS 对 bot4cj 的 30 FPS 控制循环已有 20 倍余量,推理加速优先级低。加速投入应留给训练环节(微调阶段 batch_size=32 + MobileNetV2 2.4M 参数时 CPU 较慢)。
七、结论与下一步
7.1 测试结论
| 测试项 |
结果 |
| action_dim=18 参数变更 |
✅ 通过(17 项单元测试全通过) |
| .mt 解析器 |
✅ 通过(13 文件,22 样本,占位符正确) |
| 预训练 |
✅ 通过(val_loss 2125→190,91% 下降) |
| checkpoint 兼容性 |
✅ 通过(与现有推理管线完全兼容) |
| 推理性能 |
✅ 通过(622 FPS,20 倍余量) |
7.2 已知局限
- 数据量极少:22 个样本(19 训练 / 3 验证),预训练仅学到基本的动作序列模式,val_loss 190(RMSE ≈ 14)仍有优化空间
- 列数不匹配:.mt 脚本 12 列,action_dim=18,补零的 6 列在训练中贡献零梯度
- 无图像预训练:image_encoder 在零图像上训练,学到的是常数映射,微调时需要重新训练
7.3 下一步建议
- 用真实图像微调:收集 bot4cj 运行时摄像头图像 + 动作序列数据,以预训练 checkpoint 为起点微调
- 增加 .mt 脚本:编写更多动作脚本(当前仅 13 个),扩充预训练数据量
- 列数对齐:扩展 .mt 脚本至 18 列(增加 6 列预留通道),或调整 action_dim 为 12
- ONNX 导出验证:测试
export_onnx.py 对预训练 checkpoint 的导出兼容性
- bot4cj 集成:修复 bot4cj 审计 P0 项(S01/S02/S07),打通 actpred → bot4cj 的动作执行闭环
附录 A:训练曲线关键节点
附录 B:文件清单
| 文件 |
类型 |
说明 |
actpred/config.py |
修改 |
action_dim 默认值 8 → 18 |
actpred/mt_parser.py |
新增 |
.mt @Action 矩阵解析器 |
actpred/pretrain_mt.py |
新增 |
.mt 脚本预训练入口 |
actpred/_run.sh |
修改 |
新增 pretrain 子命令 |
actpred/README.md |
修改 |
新增预训练文档 |
actpred/test_actpred.py |
修改 |
测试断言更新为 18 |
actpred/checkpoints/pretrain_best.pt |
生成 |
预训练 checkpoint(含 optimizer) |
actpred/checkpoints/pretrain_best_inference.pt |
生成 |
预训练 checkpoint(推理用) |