# 检索调参与 LTR 工作流

## 1. 目标

这份文档记录本仓库当前可复用的调参与分析流程，适用于：

- 搜索相关性调优
- rerank fusion 参数实验
- bad case 定位
- 后续 Learning to Rank（LTR）特征设计

## 2. 先看什么指标

当前主指标不是单一指标，而是一组主 scorecard：

- `NDCG@20`
- `NDCG@50`
- `ERR@10`
- `Strong_Precision@10`
- `Strong_Precision@20`
- `Useful_Precision@50`
- `Avg_Grade@10`
- `Gain_Recall@20`

实验排序时使用：

- `Primary_Metric_Score`

说明：

- `Primary_Metric_Score` 是上述 8 个指标的均值。
- 其中 `Avg_Grade@10` 先除以 `3` 再参与平均。
- 这个分数适合做实验排序，但真正决定是否采纳配置，仍然要看关键 query 和各主指标分布。

## 3. 调参顺序

推荐按以下顺序做，不要一上来只盯最终 rerank 分数。

1. **确认标注覆盖**
   - 先看 query 是否已有离线标签。
   - 没有标签的 query，不要拿它做正式 batch 结论。
   - 例如这次 `patterned bodysuit` 不在 canonical `queries.txt` 内，默认没有离线标签，只能做 live diagnosis。

2. **判断问题属于哪一层**
   - `missing_relevant` 很多：优先怀疑召回不够。
   - 召回到了但没进前 20：优先看 `coarse_rank` / `rerank_window`。
   - 进了 rerank 仍排不好：再看 fusion 或 reranker 行为。

3. **先改覆盖，再改融合**
   - 如果高相关商品连候选都进不来，只改 rerank fusion 没有意义。
   - 典型动作：
     - 增大 `knn_text_k` / `knn_text_num_candidates`
     - 增大 `knn_image_k` / `knn_image_num_candidates`
     - 增大 `coarse_rank.output_window`
     - 增大 `rerank.rerank_window`

4. **最后才微调 fusion**
   - 适合调整：
     - `es_bias`, `es_exponent`
     - `rerank_bias`, `rerank_exponent`
     - `text_bias`, `text_exponent`
     - `knn_image_weight`, `knn_bias`, `knn_exponent`

## 4. 看日志的方法

`debug=true` 时，优先读这三块：

### 4.1 `retrieval_plan`

确认本次 query 实际用了哪套 KNN 计划：

- text KNN 的 `k`
- text KNN 的 `num_candidates`
- image KNN 的 `k`
- image KNN 的 `num_candidates`
- 是否走了 long-query 分支

### 4.2 `ltr_summary`

看最终 top-N 里信号结构是否异常：

- `translation_match_docs`
- `text_knn_docs`
- `image_knn_docs`
- `text_fallback_to_es_docs`
- 各类 score 平均值

经验：

- `translation_match_docs` 很高且 `source_score` 很低，通常说明结果主要依赖翻译召回。
- `image_knn_docs` 很高但精度下降，通常说明 image KNN 权重过强或候选过宽。
- `text_fallback_to_es_docs` 很高，说明 named query 子分信息不稳定，后续要重点检查 query plan。

### 4.3 `ranking_funnel.*.ltr_features`

每个 doc 在各阶段都有稳定特征块，核心字段：

- `es_score`
- `text_score`
- `knn_score`
- `rerank_score`
- `source_score`
- `translation_score`
- `text_knn_score`
- `image_knn_score`
- `has_translation_match`
- `has_text_knn`
- `has_image_knn`

最常见的判断模式：

- `source_score > 0` 且 `translation_score = 0`
  说明主路是原文 lexical。
- `source_score = 0` 且 `translation_score > 0`
  说明主路基本完全靠翻译。
- `rerank_score` 很强但仍然上不来
  说明 `text_score/knn_score` 或上游窗口裁剪在压制。
- `coarse_rank` 排名很差、`rerank_rank` 没机会出现
  说明问题在 coarse 阶段，不在 rerank 阶段。

## 5. 这次几个 key query 的经验

### `sock boots`

问题模式：

- lexical 会把 `sock` 和 `boots` 分开吃，导致袜子、boot socks、cowboy boots 大量混入。
- 高相关 boots 里不少根本没进最终候选。

调参启示：

- 单纯增大 rerank 权重不够。
- 先扩大候选覆盖更有效，尤其是 image/text KNN 和 rerank window。
- image KNN 对这类 footwear query 有价值，但不能放得过猛，否则会拉入太多“像鞋但不是 sock boots”的商品。

### `minimalist top`

问题模式：

- 很多结果的 `source_score=0`，主要靠 translation 命中。
- query 意图偏抽象，容易把“简约风”“纯色上衣”“性感短上衣”等都混进来。

调参启示：

- 这类 query 对翻译和 broad semantic 非常敏感。
- `text_exponent` 降太多会丢掉本来还不错的 lexical 排序稳定性。
- 更稳妥的方式是保留 baseline fusion，只做小范围偏置微调。

### `tassel maxi skirt`

问题模式：

- 结果里会出现“maxi skirt”“tassel dress”“sequin tassel skirt”混排。
- 放大 image KNN / KNN exponent 后，容易把视觉上像裙装或带流苏元素的商品抬太高。

调参启示：

- 这类 query 说明 image KNN 很容易帮助，也很容易过拟合。
- 一旦 `knn_image_weight` 与 `knn_exponent` 同时上调过猛，整体长尾 query 容易掉分。

### `patterned bodysuit`

问题模式：

- 默认没有离线标签，不能直接纳入 batch 指标结论。
- live 结果能用于观察“patterned / lace / mesh / floral”这些属性如何被 text 与 rerank 解释。

调参启示：

- 先补标签，再讨论是否加入长期评估集。

## 6. 这次实验的结论

本轮实验里，**已验证**的现象是：

- 扩大 KNN 候选与 rerank 窗口，能改善 `sock boots` 一类“高相关没召回”的问题。
- 但如果同时明显放大 `knn_image_weight`、`knn_exponent` 并显著降低 `text_exponent`，会让 `tassel maxi skirt` 一类 query 变差，并拖累整体 batch 分数。
- 两轮全量 batch 里，激进配置都没有超过已验证 baseline。

因此当前建议是：

- 先把 **日志、特征、主指标体系** 升级好。
- 在后续真正推进配置采纳前，继续做“只扩候选、不大改 fusion”的实验。
- 如果未来做 LTR，优先把当前 `ltr_features` 直接沉淀成训练样本特征，而不是继续纯手调 fusion。

## 7. 推荐的下次工作

1. 给 `patterned bodysuit` 建离线标签集。
2. 单独验证“baseline fusion + 更大 KNN/窗口”的 batch 效果。
3. 从 `debug_info.per_result[].ranking_funnel.*.ltr_features` 导出训练样本。
4. 先做轻量 LambdaMART / GBDT 排序实验，再决定是否继续手工调乘法融合。

## 8. LTR 项目视角下的数据闭环

如果把后续工作从“手工调 fusion”升级为“正式 LTR 项目”，建议把整个流程理解成一条固定的数据闭环，而不是一次性的离线实验。

核心链路如下：

1. **在线检索服务产生日志特征**
   - `searcher.py` 在 `debug_info` 中输出：
     - `retrieval_plan`
     - `ltr_summary`
     - `per_result`
     - `ranking_funnel`
   - `rerank_client.py` 在 `_build_ltr_feature_block` 中把各阶段稳定特征整理成统一结构。

2. **评估框架持久化离线标签**
   - 标注缓存保存在 `artifacts/search_evaluation/search_eval.sqlite3`
   - 关键表是 `relevance_labels`
   - 标签由 `scripts/evaluation/eval_framework/constants.py` 定义，为 4 档：
     - `Fully Relevant`
     - `Mostly Relevant`
     - `Weakly Relevant`
     - `Irrelevant`

3. **离线脚本把“日志特征 + 离线标签”拼成训练样本**
   - 当前实验脚本为 `scripts/evaluation/offline_ltr_fit.py`
   - 日志源默认是 `logs/backend_verbose.log`
   - 训练粒度是 `query x doc`
   - 每个 query 默认取日志中 top-100 结果

4. **用 group-aware 排序目标做离线拟合**
   - 当前先用简单版 `RankNet Pairwise Loss`
   - 训练函数用 FM（Factorization Machine）
   - 验证方式包含：
     - query-group K-fold cross validation
     - 单独留出 10 个 query 作为 holdout test

5. **根据离线结果判断是否能进入正式线上化**
   - 不是只看训练集和全量拟合表现
   - 最关键是看：
     - cross-validation 是否稳定优于 baseline
     - holdout test 是否仍优于 baseline
     - feature importance 是否符合业务直觉
     - 是否出现明显的“记住当前样本窗口”的过拟合信号

这条闭环的意义是：之后每次改特征、改候选、改标签、改 loss，都能复用同一条训练与验证路径，而不是重新临时拼脚本。

## 9. 当前日志结构如何支撑 LTR

这次日志增强的价值，不是“方便人工 debug”这么简单，而是已经具备了进入 LTR 训练样本层的必要条件。

### 9.1 query 级信息

主要来自 `debug_info.query_analysis` 与 `debug_info.retrieval_plan`：

- 原始 query / rewrite query
- 检测语言
- translation 结果
- query tokens
- text KNN 是否开启
- text KNN 的 `k`
- text KNN 的 `num_candidates`
- 是否走了 long-query 计划
- image KNN 是否开启
- image KNN 的 `k`
- image KNN 的 `num_candidates`

这类信息本质上是 **query context feature**。即使某个 doc 的 `ltr_features` 不变，不同 query plan 下它的含义也会不同。

### 9.2 doc 级稳定特征

主要来自 `per_result[].ltr_features` 和 `ranking_funnel.*.ltr_features`。

当前最核心的数值/布尔特征包括：

- `es_score`
- `text_score`
- `knn_score`
- `rerank_score`
- `fine_score`
- `source_score`
- `translation_score`
- `text_primary_score`
- `text_support_score`
- `text_knn_score`
- `image_knn_score`
- `knn_primary_score`
- `knn_support_score`
- `style_boost`
- `stage_score`
- `has_text_match`
- `has_translation_match`
- `has_text_knn`
- `has_image_knn`
- `text_score_fallback_to_es`
- `has_style_boost`

这些特征的优点是：

- 来源清晰
- 各阶段定义稳定
- 可以直接落盘
- 后续加新特征时不需要破坏旧特征含义

### 9.3 funnel 级特征

`ranking_funnel` 很重要，因为它不仅告诉我们“最终分数是什么”，还告诉我们“这个 doc 是怎么一路走到最终排序的”。

例如当前可以直接抽出的 funnel 信息包括：

- `initial_rank`
- `coarse_rank`
- `rerank_rank`
- `final_rank`
- `es_score_normalized`
- `coarse_score`
- `fused_score`
- `coarse_stage_score`
- `rerank_stage_score`

这类特征在离线拟合时非常强，但也最容易带来过拟合。原因是它们会携带一部分“现有排序器已经做过的决定”。

因此正式项目里要把 funnel 特征分成两类看：

- **可长期保留的过程特征**
  - 例如 `coarse_rank`、`initial_rank`
- **容易泄漏当前排序器决策的特征**
  - 例如 `final_rank`
  - 或者与当前 fusion 公式几乎等价的派生项

当前离线实验里，我们保留了大部分 funnel 特征，是为了先快速判断“是否存在可学信号”；正式收敛时需要再做一轮特征裁剪。

## 10. 样本定义：LTR 训练样本到底是什么

LTR 项目里最容易混淆的点之一，是“训练样本”到底按什么定义。

### 10.1 基础样本单元

基础单元不是 pair，而是：

- 一条 query
- 在该 query 下的一个 doc
- 这条 doc 的 feature vector
- 这条 doc 的 relevance label

也就是一个标准的 `query-doc` 样本。

### 10.2 为什么最终训练用的是 pair

当前采用的是 `RankNet Pairwise Loss`，所以优化时不是直接回归 label，而是把同一 query 下 label 不同的两个 doc 组成一个 pair。

构造规则很简单：

- 同一 query 内
- 若 `label_i != label_j`
- 且 `grade_i > grade_j`
- 就构造一个正负有序 pair：`(doc_i, doc_j)`

在当前 4 档标注下，grade 映射为：

- `Fully Relevant -> 3`
- `Mostly Relevant -> 2`
- `Weakly Relevant -> 1`
- `Irrelevant -> 0`

因此：

- `Fully Relevant` 会压过其它三档
- `Mostly Relevant` 会压过 `Weakly Relevant` 和 `Irrelevant`
- `Weakly Relevant` 会压过 `Irrelevant`

这样做的好处是：

- 不需要先定义复杂的 gain 权重
- 逻辑与人工排序直觉一致
- 很适合作为第一版 baseline

### 10.3 为什么不用 doc 级随机切分

排序任务必须按 query 分组切分，不能把同一个 query 下的 doc 同时放到 train 和 test。

否则模型只是在“见过这个 query 的局部排序关系”的前提下做插值，泛化评估会明显偏乐观。

所以当前脚本里：

- cross-validation 用 `GroupKFold`
- 额外再留出 `10` 个 query 做 holdout test

这是正式项目里必须坚持的评估原则。

## 11. label 获取与质量边界

### 11.1 label 来源

当前 label 来自评估框架的离线缓存：

- DB 路径：`artifacts/search_evaluation/search_eval.sqlite3`
- 表：`relevance_labels`

脚本会按：

- `tenant_id`
- `query_text`
- `spu_id`

去查 label，并拼回日志中的 `query-doc` 样本。

### 11.2 label 语义

4 档标签不是“点击率标签”，而是人工/LLM 语义相关性标签。因此它更接近：

- 检索相关性监督
- 召回和排序质量监督

而不是：

- 转化率预测
- CTR / CVR 预估

所以这套 LTR 更适合作为 **semantic relevance ranker**，而不是最终商业目标排序器。

### 11.3 label 的边界与风险

这点需要在项目初期说清楚。

当前标签有几个天然限制：

1. **标签覆盖的是固定 query 集**
   - 未标注 query 不能直接拿来做正式结论

2. **标签覆盖的是 query 对 doc 的语义相关性**
   - 不含价格、库存、点击、转化等业务偏好

3. **标签池来自当前检索系统可见候选**
   - 如果上游召回漏掉了大量相关 doc，LTR 只能在“已见候选”上学习

4. **LLM 标注存在噪声**
   - 特别是 `Exact` 和 `High` 的边界可能不够稳定

因此正式项目中，label 质量治理要作为单独工作项推进，而不是把模型问题和标签问题混在一起。

## 12. 当前离线特征工程思路

### 12.1 为什么要做特征工程

虽然 `ltr_features` 已经比较完整，但直接喂原始特征给 FM 还不够。

原因是：

- 很多数值特征分布偏斜
- 不同特征的量纲差异很大
- 排序规律往往不是线性的

所以当前离线实验里做了轻量级特征展开。

### 12.2 当前使用的特征展开

对大部分数值特征，会扩展出：

- `raw`
- `log1p`
- `sqrt`
- `square`
- `inv = 1 / (1 + x)`

比如：

- `text_score__raw`
- `text_score__log1p`
- `text_score__sqrt`
- `text_score__square`
- `text_score__inv`

这类展开的目的很简单：

- 让模型能表达“分数高一点”和“分数非常高”不是同一个效应
- 让模型能表达某些特征的边际收益递减
- 让一些长尾数值特征更稳定

### 12.3 当前额外构造的组合特征

除了单特征变换外，还增加了少量人工组合特征：

- `translation_share = translation_score / text_score`
- `source_share = source_score / text_score`
- `image_knn_share = image_knn_score / knn_score`
- `text_knn_share = text_knn_score / knn_score`
- `rerank_x_text`
- `rerank_x_knn`
- `rerank_x_es`
- `text_minus_es`
- `knn_minus_text`
- `coarse_minus_rerank`

这些特征本质上在回答几类问题：

- 当前 doc 更偏 lexical 还是 translation
- 当前 doc 更偏 text knn 还是 image knn
- rerank 分和上游分数是否协同
- coarse 与 rerank 是否发生明显冲突

### 12.4 当前特征工程的结论

这套特征工程足够支持“第一版是否有信号”的判断，但还不够适合直接进入生产。

原因是目前的强特征中，已经出现了不少明显依赖现有排序器状态的项，例如：

- `initial_rank__log`
- `initial_rank__inv`
- `fused_score__*`
- `stage_score__*`
- `rerank_stage_score__*`

这些特征有助于模型快速拟合当前数据，但可能会让模型过度学习“旧排序器的决策痕迹”。

正式项目里建议将特征分桶：

- **A 类：原始可解释特征**
  - text / knn / rerank / translation / style
- **B 类：轻量派生特征**
  - ratio / log / sqrt / square
- **C 类：过程排序特征**
  - rank / stage score / fused score

第一阶段可以保留 A+B+C 做诊断；
第二阶段应重点验证 A+B 是否足够支撑泛化。

## 13. 模型与 loss：为什么先选 FM + RankNet

### 13.1 为什么先不用复杂模型

正式 LTR 项目可以有很多路线：

- LambdaMART / GBDT
- DNN
- DSSM / cross encoder 后融合
- listwise ranking

但在当前阶段，首要目标不是追求“最强模型”，而是先回答两个问题：

1. 当前日志特征有没有可学习信号？
2. 这些信号能否超越手工 fusion baseline？

所以第一版需要：

- 足够简单
- 可解释
- 容易离线验证
- 便于做 feature ablation

### 13.2 FM 的角色

Factorization Machine 的价值在于：

- 一阶部分可以学习单特征权重
- 二阶部分可以学习特征交互
- 相比显式枚举所有交叉项，更节省参数

在当前场景里，FM 很适合回答：

- `translation` 和 `text_score` 是否存在稳定交互
- `rerank_score` 与 `knn_score` 是否协同
- `initial_rank` 与某些语义特征是否共同决定最终排序

### 13.3 当前 loss 选择

当前用的是简化版 RankNet Pairwise Loss：

- 对每个有序 pair `(i, j)`，希望 `score_i > score_j`
- 用 `softplus(-(s_i - s_j))` 作为损失

也就是：

- 若 `s_i - s_j` 很大，loss 很小
- 若 `s_i - s_j` 不够大甚至反了，loss 会增大

当前**不加 deltaNDCG 权重**，目的是先把流程跑通，让误差来源更容易解释。

### 13.4 为什么暂时不加 LambdaRank 权重

因为当前阶段更重要的是“建立稳定 baseline”：

- pair 采样是否正确
- query-group split 是否正确
- 特征是否有用
- 模型是否明显过拟合

如果一开始就加入复杂的 listwise 权重，很容易把问题混在一起，导致难以定位：

- 是 label 问题
- 是 feature 问题
- 是 weighting 问题
- 还是 train/valid split 问题

因此现在的选择是合理的：先简单，后增强。

## 14. 当前离线实验结果与含义

### 14.1 数据规模

当前一次离线实验使用：

- `54` 个 query
- 每个 query `100` 个 doc
- 共 `5400` 个 `query-doc` 样本
- 共 `154592` 个有效 pair

标签分布大致为：

- grade `3`: `1035`
- grade `2`: `1633`
- grade `1`: `1191`
- grade `0`: `1541`

这说明数据量对“验证可学性”已经够用，但对“高置信正式定型”还不算很大。

### 14.2 cross-validation 结果

当前 FM 模型在 query-group cross-validation 下：

- `Primary_Metric_Score = 0.654043`

当前线上 fusion baseline：

- `Primary_Metric_Score = 0.641844`

这说明：

- 特征里确实有可学习信号
- 模型在交叉验证中可以平均超过手工 fusion

### 14.3 holdout test 结果

为了进一步检查泛化，额外留出 `10` 个 query 作为 holdout test。

holdout 上：

- FM：`0.53056`
- 当前 fusion baseline：`0.5674`

这说明一个很关键的事实：

- **当前模型存在明显泛化风险**
- 虽然 cross-validation 平均提升，但在这组留出 query 上没有赢 baseline

这不是坏消息，反而是好消息，因为它告诉我们：

- 当前项目已经进入“可以认真做泛化治理”的阶段
- 不是完全没信号，而是信号与过拟合同时存在

### 14.4 如何理解这个结果

更高层地说，这说明我们已经知道：

1. **LTR 是值得继续做的**
   - 因为 CV 有提升

2. **当前特征集合还不够干净**
   - 因为 holdout 掉分

3. **当前模型还不是可上线模型**
   - 因为泛化未验证通过

所以正式项目下一步不是“直接部署”，而是“收敛特征与验证体系”。

## 15. FM 权重解释：如何读 feature importance

当前离线脚本已经输出两类权重文件：

- `feature_importance_linear.csv`
- `feature_importance_interactions.csv`

### 15.1 一阶权重

可以理解为单特征对排序分的直接影响。

当前绝对值较高的一阶特征包括：

- `text_knn_score__square`
- `knn_primary_score__square`
- `has_translation_match`
- `knn_score__square`
- `text_support_score__square`

直觉上，这说明模型目前非常关注：

- KNN 主信号是否强
- text 支撑项是否强
- translation 是否参与命中

但其中 `has_translation_match` 权重很大且为负，也提示一个风险：

- 模型可能在学习“当前数据中，依赖 translation 的结果往往不够好”
- 这有可能是合理现象，也有可能只是当前样本分布偏差

### 15.2 二阶交互权重

FM 的核心价值在二阶交互。

当前绝对值较高的交互项包括：

- `text_score_fallback_to_es * initial_rank__log`
- `text_support_score__log1p * initial_rank__log`
- `text_knn_score__square * initial_rank__log`
- `has_text_knn * initial_rank__log`
- `translation_share * source_share`

这里最值得注意的是：很多强交互都和 `initial_rank__log` 有关。

这通常意味着：

- 模型高度依赖“原排序位置”作为先验
- 它在做的事情更像“在现有排序上修修补补”
- 而不是“真正只根据语义相关特征重建排序”

这就是当前 holdout 泛化不佳的重要嫌疑之一。

### 15.3 正式项目中如何用 importance

feature importance 不应该只拿来“看着开心”，而应该直接指导迭代：

1. 如果重要特征都来自原始可解释信号
   - 说明特征方向健康

2. 如果重要特征高度集中在 rank / stage / fused score
   - 说明模型可能在记忆旧排序器

3. 如果高权重特征与业务直觉相反
   - 要排查：
     - label 噪声
     - query 覆盖偏差
     - 特征定义异常

## 16. 正式开展 LTR 项目的建议路线

### 16.1 第一阶段：把数据资产固定下来

目标是建立一个稳定、可反复复用的样本生产链路。

建议动作：

1. 固定日志导出格式
   - 保证 `query-level`、`doc-level`、`funnel-level` 字段名稳定

2. 固定样本导出脚本
   - 不只从 `backend_verbose.log` 临时读
   - 后续可直接产出训练 parquet / csv

3. 固定 label join 规则
   - 严格按 `tenant_id + query_text + spu_id`

4. 固定评估切分方式
   - 始终按 query 分组
   - 始终保留固定 holdout query 集

### 16.2 第二阶段：做 feature ablation

建议按特征族做消融：

- 只用 A 类原始特征
- A + B
- A + B + C

重点回答：

- 去掉 `initial_rank` 相关特征后，是否还能赢 baseline
- 去掉 `fused_score` / `stage_score` 后，泛化是否更稳
- translation 相关特征是否真的有效
- image KNN 相关特征是否会引入 query 类型偏差

### 16.3 第三阶段：扩模型但不破坏验证纪律

只有当：

- cross-validation 稳定提升
- holdout test 也提升

再考虑进入下一步：

- LambdaRank / LambdaMART
- 更强的 GBDT 排序器
- 加入 query-level 特征桶
- 更细粒度 pair weighting

### 16.4 第四阶段：考虑线上集成方式

正式上线前，需要先决定 LTR 放在哪一层：

- 替代当前 rerank fusion
- 作为 coarse_rank 之后的再排序器
- 作为最终 fused score 的一个额外因子

当前更推荐的顺序是：

1. 先离线验证
2. 再 shadow score
3. 再小流量 AB

而不是直接替换线上排序。

## 17. 当前最推荐的下一个动作

如果要推动 LTR 项目正式开展，建议下一步按优先级做：

1. 固定一份长期 holdout query 集，不随实验随机变化。
2. 对当前特征做一次系统性裁剪，优先移除强依赖 `initial_rank`、`fused_score`、`stage_score` 的项。
3. 做 feature family ablation，确认“原始语义特征”本身是否足够支撑泛化。
4. 给更多 query 补齐高质量离线标签，尤其是当前容易失真的风格类和属性组合类 query。
5. 在 FM baseline 收敛后，再进入 LambdaMART / GBDT 路线。

一句话总结当前阶段：

- **日志体系已经足够支持 LTR 样本化**
- **离线标签体系已经足够支持第一版监督训练**
- **FM + RankNet 已经证明“有信号可学”**
- **但 holdout 结果说明“离正式可上线还有一段特征治理与泛化治理工作要做”**
