FeedLens反馈透镜

项目复盘

1. 做成了什么,没做成什么

做成了

没做成

所以这个项目目前能说明的是:我能把一个小模型微调项目从头到尾做完,并且有办法知道它到底行不行。它不能说明这个模型在真实场景里有用。

我认为最有价值的三个发现

  1. 基线和独立测试集比模型本身更重要。 如果没有写那 90 行规则,我会把“微调后 67%,训练前 0%”当成一个不错的结果。如果没有那份手写的分布外集和按核心表达分组的划分,我看到的会是一个高得多、也假得多的数字。
  2. 验证损失不能用来选检查点。 两次训练里,验证损失最低的检查点都不是生成准确率最高的,其中一次选中的甚至是不到一轮的权重。
  3. 模型和规则犯的错不一样。 两者判断一致时准确率在 86%–99%,覆盖一半左右的样本。相比“用模型替代规则”,“把模型当作规则的第二意见”可能是这个小模型更现实的用法——这还需要真实数据验证。

2. 关键决策回顾

决策 当时的理由 回头看
选“反馈结构化分诊”而不是意图识别或需求结构化 输入输出都短、标签封闭、能量化;一个生成模型同时出分类和摘要 分类部分适合小模型。摘要部分是整个任务里最不可靠的:模型学到的是“从见过的摘要模板里挑一个再改几个字”,遇到没见过的问题就会拼出不通的句子。如果重来,我会把摘要改成“从原文中抽取片段”,或者干脆在 v0.1 不做摘要
基于官方权重微调,而不是从零训练 本机没有 NVIDIA 显卡;任务不需要重新学语言 对照实验支持这个选择:随机初始化只用任务数据训练,验证集上低 20 个百分点
全参数和 LoRA 都跑,按验证集选 模型只有 64M,没有必须省资源的理由 都跑是对的。但两者在验证集和测试集上的高低方向相反,只有一个种子,说不出哪种更好;按验证集选出的全参数模型,在测试集上反而是几个微调模型里最低的
数据全部自己合成 没有可用的、许可清晰的中文反馈标注数据 这是项目最大的局限。合成语法让流程能跑通、能精确控制泄漏,但也让模型学会的是“这套语法”,而不是“用户反馈”
按“核心表达”分组划分,再加一份手写分布外集,再加一个规则基线 防止合成数据的测试分数虚高;给模型一个必须跨过的门槛 这是整个项目里最值得的设计。没有它们,我不会知道模型其实没有超过规则
用验证损失选检查点 最省事,训练时顺手就能算 错了。应当用验证集上的生成准确率,见训练记录第 7 节
预先写下验收标准 避免事后挑有利的指标讲 值得。其中“三标签全对率 ≥ 90%”定得没有依据;应当先跑出基线,再定目标
第二轮按失败案例手工补语法 最直接的改法 得到了一个清楚的否定结论:补到的学会了,没补到的没有改善。代价是多花了一轮训练和一份不再独立的开发集
重写训练循环,而不是直接用上游脚本 上游脚本不支持 MPS 混合精度以外的设备、没有验证环节 多写了约 250 行,换来验证集选模、结构化日志和可测试的续训。值得
输出用四行文本,不用 JSON 小词表下 JSON 符号容易出错 微调后的模型格式几乎不出错,说明这个格式对小模型是友好的。没有做 JSON 的对照实验,所以不能说它“更好”
应用里不用规则兜底 兜底会让“模型到底行不行”说不清 坚持了。代价是访客会直接看到模型的错误输出

3. 过程中犯的错和发现方式

这些都是实际发生过的,按发现顺序记录。

问题 怎么发现的 怎么修的 教训
冒烟测试“取前 256 条”,而数据文件按问题类型排序,取到的全是同一个类别 冒烟训练的训练损失降到 0.05,验证损失却停在 1.2,差得不合常理 改成按种子随机抽样 取子集一定要随机;指标反常时先怀疑数据
“训练是否被中断”的判断写在循环内部,恰好停在一轮的最后一步时会判断成“已跑完” 续训一致性测试失败 改为循环结束后比较已完成步数与总步数 边界条件靠测试发现,比靠读代码可靠
在 MPS 张量上转 float64 报错 第一次冒烟训练直接崩溃 先搬到 CPU 再转 换设备后第一件事是跑通最小流程
训练的同时在 CPU 上跑评测,两边都被严重拖慢 训练吞吐从约 35 条/秒掉到约 17 条/秒,评测十几分钟跑不完一个划分 停掉并发任务,改为顺序执行 统一内存的机器上,CPU 和 GPU 任务会互相抢资源;ft-full-v1 记录的训练用时因此偏长,不能用来比较方法快慢
以为 GPU(MPS)推理一定更快 在基础模型上生成 48 个 token,CPU 实测约 240 ms,MPS 约 490 ms 应用默认用 CPU 小模型逐 token 生成时,每一步的调度开销比计算本身大
写 v2 语法时无意中用了测试集里的词(“拖动排序”) 写完后用程序扫描语法与 ood_test 的字面重合 删除该取值,改写两处相近措辞,重建数据 自己出题自己答,泄漏不需要故意;能做的是加检查,并在报告里明说

4. 实际执行过的验证

下面每一项都真的运行过,括号里是依据。

数据

训练

评测

应用

5. 没有做的事

没有执行,只有方案或命令

事项 现状 需要什么才能做
在真实用户反馈上评测 没有数据 100–300 条脱敏后的真实反馈,按标注规范标注
合成数据的人工抽样复核 待填写的表格已生成(data/reports/review_*.csv),无人填写 约 1 小时人工
用户访谈与可用性测试 提纲和模板已写好 5–8 位目标用户
NVIDIA GPU 上的训练、从零预训练 只有命令和估算 一张 8 GB 以上显存的显卡,几小时
多个随机种子、超参数搜索 每种方式只跑了一组 更多训练时间
“从仅预训练权重微调”的对照、LoRA 在 v2 数据上的训练 配置已写好,没有运行 各约 10–30 分钟
按生成准确率选检查点 发现了问题,训练脚本还没改,只是额外保存了训练结束时的权重 约 1 小时开发
BERT 类分类器对照 没做 半天
线上部署 只在本机运行过。给静态托管用的展示包已生成并本地验证(见 部署到个人网站),还没有公开部署;实时推理的线上版没有做 静态版:登录 Cloudflare 上传即可。实时版:一台有 1 GB 以上内存的服务器

做了但有明显不足

6. 如果继续做,下一步的顺序

完整的计划和每一项的依据见 评测报告 第 11 节。顺序是:

  1. 先拿真实数据。 哪怕只有 100 条。在此之前,任何进一步的调参或补数据都是在对着合成数据优化。
  2. 修评测和选模的方法:按生成准确率选检查点;每个配置跑多个种子。这两项不需要新数据,立刻能做。
  3. 换一种造数据的方式:用大模型改写来扩充说法;测试集由别人或别的模型来写。
  4. 重新设计摘要:改为抽取,或者只在有把握时输出。
  5. 验证“模型与规则一致则采信”的组合策略。

不打算做的:继续按失败案例手工扩充语法。第二轮已经说明这条路走不通。

7. 需要补充的资源

资源 用途 优先级
一批真实用户反馈(哪怕 100 条) 建立真实测试集;检验类别体系是否合用 最高
第二位标注者 检验标注规范是否清晰,计算一致率 高
5–8 位愿意聊半小时的目标用户 验证需求假设 高
一张 NVIDIA 显卡的几小时使用时间 更大规模的数据、多种子实验、从零预训练 中
代码仓库地址 让文档里的代码链接可点击 中

本页由 docs/10-retrospective.md 生成。