feat(models): 落地 compare_models(指标名别名映射)+ 同步你的三条入口口径
你的三条改动(决策 61,已复测入库): - verify_yt_yp 拦 Inf:rmse([1.0, inf], ...) 从安静返回 inf 变成 ValueError。 - 至少 2 个样本:rmse(1.0, 1.0) 不再被当成 1 个样本算出 0.0。 - mape 从"只拦 0"改成拦 y_true <= 0:原来对负数返回 -1.0(无意义)。 Codex 侧把这三条写进 7 处 Raises(易错点 30 复发 1 次), test_mape_rejects_zero_in_y_true 的 match 文案改为"非正数",另补 Inf / 样本数两条测试。 compare_models(决策 62,A 档,Codex 实现): - 别名映射 _METRIC_FUNCS:r2 与 r2_score 指向同一个函数,传哪个列名就叫哪个, 两个一起传报 ValueError;adjusted_r2 不进表(需要 n_features)。 - cv=0 全量拟合后打分;cv>=2 用手写 K 折(get_rng(random_state).permutation + np.array_split),不引入 sklearn 依赖;报折间均值;每折至少 2 个样本 => cv <= n // 2。 - 排序方向跟第一个指标走(误差类升序、R² 降序);models 必须传模型对象(fit/predict), X 必须二维,metrics 必须是 tuple/list。 - 原 test_compare_models_... 的用法是错的(传拟合结果当模型),改成测试桩后摘 skip。 tests/test_models.py:23 -> 31 条(排序两条、别名、坏指标名 / 坏 models / 坏 cv、 每折下限、random_state 可复现)。 三连:pytest 233 passed / 25 skipped(258 收集)、ruff 0、pyright 0。 文档:STATUS 决策 61 / 62 + 第十轮(第九轮那 4 条标办结);CHANGELOG 本轮条目; personal-pitfalls 易错点 30 记复发 1 次 + 新增 33(多行文案少引号 / ValueError 多参数)。
This commit is contained in:
1 parent
9907289ec8
commit
748affb7f0
5 files changed
+414
-50
No files matched your search
@@ -644,6 +644,37 @@
|
||||
`rmse(1.0, 1.0)` 这类标量被当成 1 个样本、`compare_models` 的键名 `"r2"` 与函数名 `r2_score` 不一致。
|
||||
详见 `STATUS.md`「第九轮新增:4 条口径待你拍板」。
|
||||
|
||||
### Added
|
||||
- `models.compare_models`:落地(**Codex 按 A 档实现**,决策 62)。返回 `pd.DataFrame`(行 = 模型、列 = 指标),
|
||||
按第一个指标排序(误差类升序、R² 降序)。`cv=0` 全量拟合后打分;`cv >= 2` 用**手写 K 折**
|
||||
(`get_rng(random_state).permutation` + `np.array_split`,**不引入 sklearn 依赖**)报折间均值。
|
||||
- `models/metrics.py` 的**指标名别名映射** `_METRIC_FUNCS`:`"r2"` 与 `"r2_score"` 指向同一个函数,
|
||||
传哪个名字列名就叫哪个;两个一起传报 `ValueError`。`adjusted_r2` 不进表(需要 `n_features`)。
|
||||
- `tests/test_models.py`:23 → **31 条**。首列排序(升序 / 降序)、别名映射、坏指标名 / 坏 `models` / 坏 `cv`、
|
||||
每折样本数下限、`random_state` 可复现;另新增 `Inf` 与"至少 2 个样本"两条入口测试。
|
||||
原 `test_compare_models_returns_table_sorted_by_first_metric` 的**用法是错的**(把拟合结果当模型传),
|
||||
已改写成用测试桩 `_MeanModel` / `_LinearModel` 并摘掉 `skip`。
|
||||
|
||||
### Changed
|
||||
- `models/metrics.py`:用户的第三轮入口改动入库(决策 61)—— `verify_yt_yp` 增加 `Inf` 拦截、
|
||||
增加"至少 2 个样本"(标量不再被当成 1 个样本);`mape` 由"只拦 0"改成拦 `y_true <= 0`
|
||||
(原式对负数返回**负数**,实测 `-1.0`)。
|
||||
- `models/metrics.py`:三条新口径同步进 7 处 `Raises`,`mape` 的 `Returns` 与摘要改为"`y_true` 必须全为正数"
|
||||
(**易错点 30 复发 1 次**:口径一改、docstring 立刻过期)。
|
||||
- `models/metrics.py`:`compare_models` 的入口收口 —— `X` 必须二维(`as_array(ndim=2)` 不替你猜)、
|
||||
`cv` 白名单(`bool` 拒收 / `cv=1` 无意义 / `cv <= n // 2`)、`models` 必须是"有 `fit` / `predict` 的对象"、
|
||||
`metrics` 必须是 `tuple` / `list`(单个字符串给专门的报错文案)。
|
||||
- `models/metrics.py`:模块 docstring 改为"指标函数只返回 `float`,唯一例外是 `compare_models`(返回 `DataFrame`)"。
|
||||
- `STATUS.md`:新增**决策 61 / 62**,第九轮那 4 条口径标记办结,「下一步」推进到第十轮;
|
||||
验证计数更新为 **233 passed / 25 skipped(258 收集)**。
|
||||
- `docs/dev/personal-pitfalls.md`:易错点 30 记为**复发 1 次**;新增易错点 33
|
||||
(多行报错文案少引号 / `raise ValueError("a", "b")` 多参数 —— ruff 一秒能抓,别等运行时)。
|
||||
|
||||
### Notes
|
||||
- **1 条小口径待用户拍板**:`verify_yt_yp` 里 `yt.ndim == 0` 是死代码(`as_array(ndim=1)` 必然摊平),
|
||||
可塌成 `if yt.shape[0] <= 1:`。详见 `STATUS.md`「第十轮新出现的 1 条小口径」。
|
||||
- **等 `fit_linear` 落地时补一条集成测试**:`compare_models` + 真实模型对象。
|
||||
|
||||
## [0.0.1] - 2026-10-01
|
||||
|
||||
### Added
|
||||
|
||||
Reference in new issue
Block a user