Natural Memory NM2.1: 记忆路由器分叉、数据集缺陷修复与全轴评测证据
- 引入 MemoryRouterXL 与 v5/v6 流式多线程训练/编码管线 - 修复 prepare_memory_router_dataset 候选池重建缺陷(mega 家族 3568x 加速,输出逐字节相同) - 修复 v5 被破坏的拒答与多跳标签(train 未知样本 319 -> 16319,multi_hop 平均正例 1.00 -> 2.00) - 同存储预算下 V2-128 v6 逐轴 22/22 通过:Top-1 41.12% -> 94.62%,未知拒答 0.00% -> 100.00% - 记录三条被实测推翻的显然优化(logits_to_keep=1 反而慢 55%、XL 容量未带来收益) - 记忆手术跨架构可移植性 14/14,读写关闭时与原生模型逐位相同
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
# 真实工作泛化能力:用真实形态数据重训路由器的完整结论
|
||||
|
||||
> ## ⚠️ 本文的端到端数字已被证伪,读之前先看 `MEASUREMENT_FIXES.md`
|
||||
>
|
||||
> 2026-09-15 复核发现,本文第 3 节起引用的端到端正确率(**72.57% / 63.50% / 64.00%**)
|
||||
> 由两个评分器缺陷造成,**不是模型的真实水平**:
|
||||
>
|
||||
> 1. 评分器对空白敏感 —— 期望锚点 `值班人-5259`、模型答 `值班人 -5259`(多一个空格)判错,
|
||||
> **19 条多跳用例全部因此被判错**(多跳真实是 **100.00%**,不是 24.00%);
|
||||
> 2. 拒答检测只认固定关键词,漏掉模型实际使用的措辞(「未包含相关信息,无法回答」),
|
||||
> 把 **52.00%** 的未知拒答率报成 **0.00%**。
|
||||
>
|
||||
> 修正后,同一份权重、同一份语料的真实水平是
|
||||
> **总体 82.00% / 可回答 86.29% / 未知拒答 52.00% / 已知被误拒 2.29%**。
|
||||
>
|
||||
> **本文仍然成立的结论**:路由器在未见属性族上确实能练出泛化能力(Top-1 49.14% → 94.86%),
|
||||
> 而且该增益不传递到端到端答案 —— 这一条与空白缺陷无关,仍然有效。
|
||||
> **本文不再成立的结论**:所有以 72.57%/63.50% 为基线的「差值」与「瓶颈排序」,
|
||||
> 包括「多跳是瓶颈」和「未知拒答率 4.00%/0.00%」。
|
||||
|
||||
## 1. 做了什么
|
||||
|
||||
| 步骤 | 结果 |
|
||||
|---|---|
|
||||
| 真实形态**训练集** | `data/realistic_v2/train.jsonl`,3200 条 / 8 类别(多实体、别名、更新冲突、多跳、近邻干扰、噪声、长事实、未知) |
|
||||
| 真实形态**评测集** | `data/realistic_v2/eval.jsonl`,200 条 / 8 类别 |
|
||||
| **属性族不相交** | 36 个属性族按字典序三分:训练 24 / 评测 12,**overlap = []**(评测用的属性名与句式训练时从未出现) |
|
||||
| 特征编码 | 10,034 文本 / 60 秒(流式+8 线程) |
|
||||
| 训练 | V2-128(drop-in 几何),从现有交付件出发,12,000 步 / 1e-4 / need+hop 正常权重 |
|
||||
|
||||
## 2. 路由器级:真实泛化能力被练出来了(强结果)
|
||||
|
||||
在**未见属性族**上:
|
||||
|
||||
| 检查点 | Top-1 | Recall@3 | MRR | need 特异度 | hop |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| step 0(现有交付件) | **49.14%** | 78.29% | 66.87% | 0.00 | 0.68 |
|
||||
| step 1000 | **94.86%** | **100.00%** | 96.95% | 0.20 | 0.785 |
|
||||
| step 12000 | 93.71% | 100.00% | 96.57% | 0.32 | 0.765 |
|
||||
|
||||
**Top-1 +45.72pp、Recall@3 到 100.00%**,而且是在训练时从未见过的属性措辞上 —— 这一个数字本身说明:
|
||||
**"路由器缺的是真实形态训练数据"这个判断是对的。**
|
||||
|
||||
## 3. 但端到端**一动不动**
|
||||
|
||||
同一条 200 条评测集(属性不相交),同一份运行时,只换路由器:
|
||||
|
||||
| | 总体 | 可回答(175) | 未知拒答(25) | 已知被误拒 |
|
||||
|---|---:|---:|---:|---:|
|
||||
| 原版 NM2 | 64.00% | **72.57%** | 4.00% | 2.86% |
|
||||
| 真实语料重训的路由器 | 63.50% | **72.57%** | 0.00% | 1.71% |
|
||||
|
||||
**Top-1 提升 45.72pp → 端到端可回答正确率变化 0.00pp。** 逐类别:
|
||||
|
||||
| 类别 | 原版 NM2 | 重训 | 差值 |
|
||||
|---|---:|---:|---:|
|
||||
| alias_paraphrase | 96.00% | **100.00%** | +4.00pp |
|
||||
| long_fact | 64.00% | **72.00%** | +8.00pp |
|
||||
| multi_entity | 96.00% | 96.00% | 0 |
|
||||
| **multi_hop** | **48.00%** | **24.00%** | **−24.00pp** |
|
||||
| near_miss | 88.00% | **100.00%** | +12.00pp |
|
||||
| noise_context | 68.00% | **72.00%** | +4.00pp |
|
||||
| unknown_attribute | 4.00% | 0.00% | −4.00pp |
|
||||
| update_conflict | 48.00% | 44.00% | −4.00pp |
|
||||
| **合计** | **64.00%** | **63.50%** | **−0.50pp** |
|
||||
|
||||
8 类里 4 类改善(+4~+12pp)、3 类退步(−4~−24pp),**净 −0.50pp**。每类只有 25 条、1 例 = 4.00pp,
|
||||
所以 ±8pp 都在噪声量级;**唯一可能真实的是 multi_hop 的 −24.00pp(6 个用例)**。
|
||||
|
||||
## 4. 逐个被证伪的假设(这一步比结论更重要)
|
||||
|
||||
| 假设 | 测量结果 | 判定 |
|
||||
|---|---|---|
|
||||
| 记录没写进库 | 写入存活 **92.00%**、**目标事实存活 100.00%(35/35)** | **否** |
|
||||
| 排序被先验压住 | 先验置 0 + 纯路由器排序:可回答 **77.14%** vs 现状 76.57%(1 个用例) | **否** |
|
||||
| 先验权重要调 | 剂量曲线 1.00/0.50/0.25/0.00 = 65.00%/47.50%/42.50%/40.00%(模板域) | **否,调小更差** |
|
||||
| 注入记录太多,模型被混淆 | top_k = 4/2/1 → 可回答 72.57% / 66.29% / **52.57%** | **否,减少更差** |
|
||||
| 路由器分数没被用上 | 让路由器全权排序只动 1 个用例(见上) | **部分成立但不是主因** |
|
||||
|
||||
**结论:在当前架构下,路由器级排序能力不是端到端准确率的约束条件。** 这一点现在有两条独立证据链
|
||||
(模板域的先验/混合实验 + 真实域的"Top-1 +45.72pp 而端到端 0.00pp")。
|
||||
|
||||
## 5. 残差到底落在哪(可辩护的逐类分类,200 条)
|
||||
|
||||
| 类别 | 用例 | 正确 | 答了但不对 |
|
||||
|---|---:|---:|---:|
|
||||
| alias_paraphrase | 25 | **25(100.00%)** | 0 |
|
||||
| near_miss | 25 | **25(100.00%)** | 0 |
|
||||
| multi_entity | 25 | 24 | 1 |
|
||||
| long_fact | 25 | 18 | 7 |
|
||||
| noise_context | 25 | 18 | 6 |
|
||||
| **update_conflict** | 25 | **11** | **13** |
|
||||
| **multi_hop** | 25 | **6** | **19** |
|
||||
| **unknown_attribute** | 25 | **0** | **25** |
|
||||
| 合计 | 200 | 127(63.50%) | 71(35.50%)(拒答 2、空回复 0) |
|
||||
|
||||
**残差集中在这三处,而不是"全面不准":**
|
||||
1. **未知属性 0/25** —— 全部照答。覆盖机制是固定 24 属性闭集,在真实实体前缀属性上自动旁路(设计如此)。
|
||||
2. **多跳 6/25(24.00%)** —— 链条没被跟上,而且比原版更差,说明重训在这类上过拟合了训练里的链条形态。
|
||||
3. **更新冲突 11/25(44.00%)** —— 模型答出**被取代的旧值**。
|
||||
|
||||
第 3 点值得单独查:语料里我把"旧值/新值"写成**两个不同句式**(`frames[0]` / `frames[-1]`)。
|
||||
若新值那句解析不出同一属性,`write()` 的同属性取代就不会触发,**旧记录仍是 active** → 两条都进证据。
|
||||
这既是我的语料细节,**也对应真实产品缺陷:用户换一种说法更新时,旧值可能不被取代**。
|
||||
|
||||
## 6. 结论
|
||||
|
||||
1. **"真实形态训练数据"是路由器泛化的正确杠杆**:+45.72pp Top-1(未见过属性族),证据干净。
|
||||
2. **但它不是端到端体验的杠杆**:端到端净变化 −0.50pp,8 类里有升有降。
|
||||
3. **端到端剩下的 27.43% 失败集中在三处**(未知 25/25 错、多跳 19/25 错、更新冲突 13/25 错),
|
||||
全部属于**运行时逻辑**(覆盖判断、多跳执行、冲突取代),不在路由器权重里。
|
||||
4. 因此下一步该做的不是继续训路由器,而是:
|
||||
* **冲突取代**:让"换一种说法的更新"也能取代旧记录(结构化键 + 语义匹配双条件),目标 更新冲突 ≥ 80%;
|
||||
* **多跳执行**:核对 read 路径是否真的按 hop=2 串联两条记录,目标 多跳 ≥ 70%;
|
||||
* **动态属性词表**:覆盖判断要能处理实体前缀属性,目标 未知拒答 ≥ 80%。
|
||||
路线图建议:**多跳与冲突取代优先**(各约 20 条错例,且都是逻辑问题、不需要新数据)。
|
||||
|
||||
## 7. 产物
|
||||
|
||||
| 文件 | 内容 |
|
||||
|---|---|
|
||||
| `make_realistic_memory_data.py` | 训练/评测语料生成器(36 属性族、按族三分切分、含构造 bug 修复注释) |
|
||||
| `data/realistic_v2/{train,eval}.jsonl` + `.manifest.json` | 3200 / 200 条,含 sha256 与**不相交证明**(`overlap: []`) |
|
||||
| `H:\Memory\nm_cache\nm_realistic_v2\feature_cache` | 10,034 行特征库(流式编码,60 秒) |
|
||||
| `checkpoints/router_realistic_v2_128/` | 真实语料重训的路由器(V2-128,drop-in 几何) |
|
||||
| `rv2_{orig,new}_e2e.{json,md}` | 第 3 节对照(原版 vs 重训) |
|
||||
| `rv2_topk{1,2}_e2e.{json,md}` | 第 4 节注入纪律实验 |
|
||||
| `rv2_order_{current,routeronly}.{json,md}` | 第 4 节排序实验 |
|
||||
| `write_survival.json` | 第 4 节写入存活诊断 |
|
||||
| `diagnose_write_survival.py` | 写入存活诊断脚本 |
|
||||
| `REALISTIC_CORPUS_FINDINGS.md` | 第一版语料(含我 3 个构造 bug 的复盘) |
|
||||
Reference in New Issue
Block a user