Skip to content

Release v1.11.0: TrainingSession修改

Choose a tag to compare

@EthanPeng-2048 EthanPeng-2048 released this 22 Oct 23:11
· 30 commits to main since this release

neuralnet.cpp v1.11.0

主题:TrainingSession 单步协议(train_step)与 global/micro batch 语义(docs/todo/30)
范围:v1.10.0 → v1.11.0 · 模型文件格式 v8 不变


⚠️ 破坏性变更

API 层

旧 新
session.train_state() / set_train_state() 删除 运行态移至 TextTrainer::train_state();Session 侧只读 session.state()(TrainingSessionState)
手写 update 管线(zero_grad → fwd/loss/bwd → clip → step) session.train_step(micro_batch, TrainingStepOptions, step_fn);失败后用 reset_accumulation() 丢弃半截 update
TextTrainer::steps_per_epoch(batch_size) 无参 steps_per_epoch()(返回 update 数);新增 micro_batch_size()
TextSampleSet::steps_per_epoch(batch_size) 参数语义改为 global batch,返回 update 数

新增:TrainingStepOutput / TrainingStepOptions / TrainingStepReport、TrainingConfig.grad_accum_steps(默认 1)、TextSampleSet::valid_target_count(indices)。

Batch 语义(同名参数、行为变化,升级必须核对脚本)

  • --batch-size:micro-batch → 理论 global batch(micro = batch_size / accum_steps,须整除,否则 TextTrainer::create fail-fast)
  • step 计数统一为 optimizer update:steps_per_epoch、global_step、lr 调度、--log-interval / --save-interval / --max-steps 全部按 update 计
  • 等效换算:旧 --batch-size 8 --accum-steps 4(有效 32)→ 新 --batch-size 32 --accum-steps 4(micro 8)

✨ 新特性

  • TrainingSession::train_step() 单步协议:接收已装配 micro-batch,经 Step 回调完成 forward/loss/backward;内部维护梯度累积,在 update 边界执行归一化、裁剪、optimizer.step()、zero_grad。不拥有数据集/epoch/lr 曲线/评估/断点策略(仍归 TextTrainer)
  • 低层原语 zero_grad() / clip_grads() / step() 保留(mnist_train 仍用);新增 reset_accumulation() 与只读 state()

🐛 修复

  • v1.10.0 在 --accum-steps > 1 时对每个 micro 梯度乘 1/accum_steps("micro 均值之均值"),当 loss_mask 使各 micro 有效 token 数不同或末批不满时偏离理论目标函数。本版按 gradient_units / normalization_units 精确归一化(分母 = 全 global batch 有效 token 数),与"逐样本求和后一次归一"严格等价;默认 accum=1 路径不受影响
  • normalization_units == 0 明确报错,不再执行无意义更新

🔄 兼容性

  • 格式仍为 v8;训练状态段新增 batch_size_semantics / micro_batch_size 键
  • v1.10.0 .nnckpt 可继续 --resume:缺语义键按 legacy micro 语义解释,global_batch_size = legacy_batch_size × accum_steps,micro step 折算为 update step
  • 反向不成立:v1.10.0 二进制读到新断点会按 micro 语义解释 batch_size,回退旧二进制前请保留原文件

✅ 验收

项目 结果
Windows clang 23.1 / Vulkan (40HX) Release 构建 219/219(0 warning);59 测试 → 58 pass + 1 skip(540 s)
WSL g++ 15.2 / CPU-only Release 构建 112/112;57 → 39 pass + 18 skip(GPU 依赖,预期)
本机 clang 24.0 / libc++ / GPU 219/219;57 pass + 2 fail(llvmpipe 软件光栅 f16 差异,40HX 真卡全绿)
门禁审计 gui_cli_audit.py / doc_inventory.ps1 / doc_align_audit.ps1 全 PASS,可行动 0
GPU 端到端(tinystories_20k,GPT d64,global batch 8 = micro 4 × accum 2,20 step) f32 8.7576→7.6022;--f16 8.7676→7.7230;--t1_58 8.9011→8.1010;无 NaN/冻结
断点续训 新格式 step20 续 2 步 7.6539→7.5228;legacy 断点 micro step 10 → update step 5 折算正确,续训 8.6738→8.5822 与 legacy 末值 8.7711 连续
新增回归 global/micro 等价、累积边界(force_update / 尾批 / mask 不均)、legacy 断点折算(training_session_test 等扩充)

📦 提交

  • bc37df3 — TrainingSession 单步协议 + global/micro batch 语义 + 状态拆分
  • 另含发布提交 release: v1.11.0(tag 所指)

⚠️ 已知限制

  • TrainingStepReport.loss_sum 设备侧回读为同步语义;异步回读由 Run Driver 经 session.state() pending 槽自行安排
  • global batch 尾部不满时按剩余样本切 micro,最后 micro-step 走 force_update;归一化分母为实际有效 token 数
  • mnist_train 仍走低层原语,迁移 train_step 留作后续