# AWDE 0617/0618 F1 异常排查

时间：2026-06-18 08:55 CST

## 结论

0617、0618 的 `Has0_F1_score / Non0_F1_score` 并没有比 `/root/AWDE/AWDE_EXPERIMENT_SUMMARY.md` 里的 0615 F1 低很多。真正容易误读的是 `Zero_F1`：它只有约 0.67-0.69，但 `AWDE_EXPERIMENT_SUMMARY.md` 的 F1 列明确定义为 `Has0_F1_score / Non0_F1_score`，不是 `Zero_F1`。

`AWDE_EXPERIMENT_SUMMARY.md:12` 写的是：

```text
`F1 (Has0/Non0)` 使用同一 checkpoint 的 `Has0_F1_score / Non0_F1_score`。
```

所以不能把 `Zero_F1` 和 summary 里的 `F1 (Has0/Non0)` 横向比较。

## 指标口径

- `Has0_F1_score`：二分类 weighted F1，标签为 `truth >= 0`，也就是 negative vs non-negative，包含 zero。
- `Non0_F1_score`：二分类 weighted F1，只在 `truth != 0` 的样本上算 positive vs negative。
- `Zero_F1`：把回归值四舍五入后判断是否为 0，即 `round(pred) == 0` vs `round(truth) == 0`。这是 zero 精确识别指标，比 Has0/Non0 更苛刻，也不是 summary 表的 F1。

## 与 0615 Summary 对比

0615 summary 基准：

| 口径 | Has0_F1 | Non0_F1 | Zero_F1 | MAE | Corr |
| --- | ---: | ---: | ---: | ---: | ---: |
| 0615 mean | 0.8333 | 0.8784 | 0.6727 | 0.4877 | 0.8125 |
| 0615 h160 best | 0.8434 | 0.8869 | 0.6724 | 0.4812 | 0.8184 |

0617/0618 均值：

| 实验组 | Has0_F1 | Non0_F1 | Zero_F1 | MAE | Corr | 相对 0615 mean |
| --- | ---: | ---: | ---: | ---: | ---: | --- |
| 0617 main | 0.8353 | 0.8820 | 0.6724 | 0.4864 | 0.8150 | Has0_F1 +0.0021, Non0_F1 +0.0035 |
| 0617 FD-router | 0.8348 | 0.8780 | 0.6810 | 0.4834 | 0.8122 | Has0_F1 +0.0015, Non0_F1 -0.0004, Zero_F1 +0.0083 |
| 0618 FD-query-boost | 0.8424 | 0.8821 | 0.6822 | 0.4790 | 0.8186 | Has0_F1 +0.0091, Non0_F1 +0.0037, Zero_F1 +0.0095 |

结论：按 summary 的 F1 口径看，0617/0618 没有 F1 崩掉。0618 平均 Has0_F1、Non0_F1、Zero_F1、MAE、Corr 都比 0615 mean 更好；0617 FD-router 的 Non0_F1 与 0615 mean 基本持平，Zero_F1 和 MAE 更好。

## 逐 Run 结果

### 0617 main

| Run | Epoch | Has0 | Has0_F1 | Non0 | Non0_F1 | Zero_F1 | MAE | Corr |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| comp_has0_l02_h128_lr8e5_b12_d12 | 6 | 0.8324 | 0.8278 | 0.8795 | 0.8797 | 0.6733 | 0.4905 | 0.8123 |
| comp_has0_l02_h160_lr5e5_b8_d15 | 4 | 0.8465 | 0.8434 | 0.8861 | 0.8869 | 0.6724 | 0.4812 | 0.8184 |
| has0_h128_lr8e5_b12_d12 | 7 | 0.8311 | 0.8267 | 0.8740 | 0.8743 | 0.6715 | 0.4925 | 0.8109 |
| has0_h160_lr5e5_b8_d15 | 4 | 0.8465 | 0.8434 | 0.8861 | 0.8869 | 0.6724 | 0.4812 | 0.8184 |

### 0617 FD-router

| Run | Epoch | Has0 | Has0_F1 | Non0 | Non0_F1 | Zero_F1 | MAE | Corr |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| fd_router_h128_s025_lr8e5_b12_d12 | 4 | 0.8395 | 0.8359 | 0.8770 | 0.8776 | 0.6892 | 0.4803 | 0.8147 |
| fd_router_h128_s050_lr8e5_b12_d12 | 4 | 0.8343 | 0.8303 | 0.8756 | 0.8762 | 0.6807 | 0.4798 | 0.8145 |
| fd_router_h160_s025_lr5e5_b8_d15 | 4 | 0.8431 | 0.8397 | 0.8814 | 0.8820 | 0.6769 | 0.4840 | 0.8132 |
| fd_router_h160_s050_lr5e5_b8_d15 | 4 | 0.8371 | 0.8333 | 0.8759 | 0.8764 | 0.6774 | 0.4894 | 0.8065 |

### 0618 FD-query-boost

| Run | Epoch | Has0 | Has0_F1 | Non0 | Non0_F1 | Zero_F1 | MAE | Corr |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| fdqboost_h128_a15_lr8e5_b12_d12 | 4 | 0.8399 | 0.8439 | 0.8847 | 0.8843 | 0.6813 | 0.4794 | 0.8165 |
| fdqboost_h128_a20_lr8e5_b12_d12 | 4 | 0.8362 | 0.8403 | 0.8795 | 0.8790 | 0.6876 | 0.4800 | 0.8174 |
| fdqboost_h160_a15_lr5e5_b8_d15 | 4 | 0.8399 | 0.8437 | 0.8839 | 0.8833 | 0.6830 | 0.4770 | 0.8208 |
| fdqboost_h160_a20_lr5e5_b8_d15 | 4 | 0.8375 | 0.8416 | 0.8825 | 0.8820 | 0.6768 | 0.4795 | 0.8196 |

## 0617 F1 实现问题

0617 的训练脚本原来把 sklearn 的 `y_true` 和 `y_pred` 顺序传反了。修复前的关键片段是：

```text
accuracy_score(non_zero_pred, non_zero_truth)
f1_score(non_zero_pred, non_zero_truth, average="weighted")

accuracy_score(binary_pred, binary_truth)
f1_score(binary_pred, binary_truth, average="weighted")
```

accuracy 是对称的，所以 Acc 不受影响；weighted F1 不是严格对称的，所以 0617 历史结果里的 F1 字段有轻微口径问题。这个问题已经在 `/root/AWDE/0617/scripts/train_awde.py:319` 和 `/root/AWDE/0617/scripts/train_awde.py:328` 修掉，后续新 run 会使用标准 `f1_score(y_true, y_pred)` 口径。0618 脚本本来就是正确顺序：

```text
/root/AWDE/0618/scripts/train_awde.py:316-317
accuracy_score(non_zero_truth, non_zero_pred)
f1_score(non_zero_truth, non_zero_pred, average="weighted")

/root/AWDE/0618/scripts/train_awde.py:325-326
accuracy_score(binary_truth, binary_pred)
f1_score(binary_truth, binary_pred, average="weighted")
```

由于历史结果没有保存 test 预测数组，不能直接无损重算 0617 F1。但可以用 test 标签分布、已记录 Acc 和“反向 weighted F1”反推二分类混淆矩阵候选。反推结果显示：0617 的标准 Has0_F1 约比历史表更高，Non0_F1 只差千分级。

| 0617 Run | 历史 Has0_F1 | 标准 Has0_F1 反推 | 历史 Non0_F1 | 标准 Non0_F1 反推 |
| --- | ---: | ---: | ---: | ---: |
| comp_has0_l02_h128_lr8e5_b12_d12 | 0.8278 | 0.8369-0.8370 | 0.8797 | 0.8792-0.8793 |
| comp_has0_l02_h160_lr5e5_b8_d15 | 0.8434 | 0.8496-0.8497 | 0.8869 | 0.8852-0.8853 |
| has0_h128_lr8e5_b12_d12 | 0.8267 | 0.8354-0.8355 | 0.8743 | 0.8736-0.8737 |
| has0_h160_lr5e5_b8_d15 | 0.8434 | 0.8496-0.8497 | 0.8869 | 0.8852-0.8853 |
| fd_router_h128_s025_lr8e5_b12_d12 | 0.8359 | 0.8430 | 0.8776 | 0.8763-0.8764 |
| fd_router_h128_s050_lr8e5_b12_d12 | 0.8303 | 0.8383 | 0.8762 | 0.8750-0.8751 |
| fd_router_h160_s025_lr5e5_b8_d15 | 0.8397 | 0.8465 | 0.8820 | 0.8807-0.8808 |
| fd_router_h160_s050_lr5e5_b8_d15 | 0.8333 | 0.8408-0.8409 | 0.8764 | 0.8753-0.8754 |

因此 0617 的“F1 低”不是方法退化，而是两个因素叠加：

1. 把 `Zero_F1` 当成 summary 的 F1 去比。
2. 0617 历史 F1 记录用了反向 weighted F1，Has0_F1 被轻微压低。

## 对 FD 的判断

这批数据不支持“FD 没用”的结论。

- 0617 FD-router：Zero_F1 从 0615 mean 的 0.6727 提到 0.6810，MAE 从 0.4877 降到 0.4834；Has0/Non0 F1 没有崩。
- 0618 FD-query-boost：Has0_F1 均值 0.8424，Non0_F1 均值 0.8821，Zero_F1 均值 0.6822，MAE 均值 0.4790，Corr 均值 0.8186，整体强于 0615 mean。
- 最符合当前想法的是 0618：FD 做 query boost，只对查到的模态权重提一些，主信息仍由模态解释主导。

## 上传接口研究

`https://varmath.cn/workspace/` 的前端上传代码直接调用：

```js
fetch(`${BASE_PATH}/upload?filename=${encodeURIComponent(file.name)}`, {
  method: 'POST',
  headers: {'Content-Type': file.type || 'application/octet-stream'},
  body: file
})
```

其中 `BASE_PATH = "/workspace"`，所以命令行上传方式是：

```bash
curl -X POST \
  -H "Content-Type: text/markdown; charset=utf-8" \
  --data-binary "@/root/dataset/AWDE_0617_0618_F1_INVESTIGATION.md" \
  "https://varmath.cn/workspace/upload?filename=AWDE_0617_0618_F1_INVESTIGATION.md"
```

上传后可用下面命令验证：

```bash
curl -I "https://varmath.cn/workspace/AWDE_0617_0618_F1_INVESTIGATION.md"
```

## 建议

后续所有 summary 表继续只放 `Has0_F1_score / Non0_F1_score` 到 `F1 (Has0/Non0)`。`Zero_F1` 单独成列，不要混用。

0617 历史结果如果要写论文或总表，建议不要直接引用旧脚本记录的 Has0_F1；要么用已修脚本加载 checkpoint 重评估，要么在内部表中使用本报告的反推范围。0618 的 F1 记录可以直接按标准口径使用。
