查看: 165|回复: 3

鸿蒙文搜图评测:nDCG、误差预算与配对bootstrap审计

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在 HarmonyOS 7(API 26)的 Mate 90 Pro 模拟器上,一个离线文搜图应用内置 24 张缩略图,支持中文短语查询,返回 0~100 分的排序列表,并为每条结果附若干“命中依据”标签。本文不讨论引擎实现,而是把七张实机运行截图当作唯一证据,重建可复核的评测口径:分数是否可信、依据是否可信、改动是否可验证。样本总体只有 24 张图,不是 3 张也不是几百张,这决定了后续置信区间会较宽,榜单第 20 名这类位置的统计意义很弱。

一、从截图重建 qrels,先固定审计口径
评测起点是 qrels(query–relevance judgments)。截图提供了“冷色的复杂细节”和“明亮的蓝色风景”两次查询的完整榜单,可抄成初版标注。原则是只标截图上确实读到的项,读不到就留空;把没看清当成 0 分,会凭空制造假负例。三档相关性比连续分数更经得起人工复核,数据结构保留 None,表示截图未抄录、不参与任何指标。原文有效标注只有 6 条,故意不完整;作用不是评测出最终结论,而是固化审计口径:以后每跑一次引擎,都用同一份 qrels 比对,标注只增不改。
  1. from dataclasses import dataclass
  2. from typing import Dict, Optional
  3. @dataclass(frozen=True)
  4. class Judgment:
  5.     query: str
  6.     doc_id: int
  7.     grade: Optional[int]
  8. QRELS: Dict[str, Dict[int, Optional[int]]] = {
  9.     '冷色的复杂细节': {6: 2, 3: 1, 16: 1, 15: 0},
  10.     '明亮的蓝色风景': {19: 1, 22: 1},
  11. }
  12. def effective(qrels, q):
  13.     return {d: g for d, g in qrels[q].items() if g is not None}
复制代码

二、四个正交指标,各测一件事
只用一个平均分衡量检索质量很容易误导。这里选四个正交指标:P@5、nDCG@5、词级命中率、依据一致率。P@5 和 nDCG@5 看排序;词级命中率专门抓“一个词打满、另一个词归零,融合后却给了高分”的失效,例如只算 P@5 时这类图可能仍被算作相关;依据一致率则审计命中标签本身。实现时,P@5 只对已标注项计分,未标注项不能全算成不相关,否则指标会被系统性压低。nDCG 要使用分级增益 2^g-1,位置从 0 起时分母用 log2(i+2)。
  1. import math
  2. def precision_at_k(ranked, qrels, q, k=5):
  3.     judged = effective(qrels, q)
  4.     top = [d for d in ranked[:k] if d in judged]
  5.     if not top:
  6.         return 0.0
  7.     return sum(1 for d in top if judged[d] >= 1) / len(top)
  8. def ndcg_at_k(ranked, qrels, q, k=5):
  9.     judged = effective(qrels, q)
  10.     def dcg(seq):
  11.         return sum((2 ** judged[d] - 1) / math.log2(i + 2)
  12.                    for i, d in enumerate(seq) if d in judged)
  13.     actual = dcg(ranked[:k])
  14.     ideal = dcg(sorted(judged, key=lambda d: judged[d], reverse=True)[:k])
  15.     return actual / ideal if ideal > 0 else 0.0
  16. def term_satisfaction(hits, threshold=0.15):
  17.     if not hits:
  18.         return 0.0
  19.     return sum(1 for s in hits.values() if s >= threshold) / len(hits)
复制代码

三、误差预算:100 分里有多少是噪声
审计中最容易被跳过、却最有价值的一步,是问分数由哪些环节组成、每个环节带来多大不确定性。原文指出榜首 100 分至少可拆出四处量化误差,其中前两项是测量误差,后两项是模型误差。显示取整就是可复跑的敏感性来源:例如“绿 14%”在 frac/0.22 规则下,按显示值 ±0.5 个百分点复算,单项分带宽约为 61.36 到 65.91,光是显示取整就有约 ±2.3 分。因此标签写 62 分时,把 61.5 和 62.4 区分开属于过度解读。融合补偿也是误差来源:加权平均允许一项满分补偿另一项零分,改用加权几何平均后任一项归零则总分为零。原文示例中,复杂 1.00、冷 0.00,权重分别为 0.8 和 1.0,算术平均为 44.4,几何平均为 0.5;这个差距说明词级命中率必须单列。
  1. def weighted_mean(hits, weights):
  2.     num = sum(weights[t] * s for t, s in hits.items())
  3.     den = sum(weights[t] for t in hits)
  4.     return num / den if den else 0.0
  5. def weighted_geometric(hits, weights, eps=1e-3):
  6.     den = sum(weights[t] for t in hits)
  7.     log_sum = sum(weights[t] * math.log(max(s, eps)) for t, s in hits.items())
  8.     return math.exp(log_sum / den)
  9. hits = {'复杂': 1.00, '冷': 0.00}
  10. w = {'复杂': 0.8, '冷': 1.0}
  11. print('算术平均:', round(weighted_mean(hits, w) * 100, 1))
  12. print('几何平均:', round(weighted_geometric(hits, w) * 100, 1))
复制代码

四、置信区间与配对 A/B:让“变好”可复核
24 张图、6 条有效标注属于极小样本。“nDCG 从 0.71 升到 0.78”在这种规模下几乎肯定不显著,审计必须给出判断方法。可用配对 bootstrap 对查询重采样,同一批查询比较 A/B 两个榜单,计算差值区间;如果 95% 区间跨 0,只能说当前样本无法区分,不能写“没有差异”,更不能直接判 B 更好。原文给出 2000 轮、seed=11 的示例。样本量也可反推:若想把 nDCG 置信半宽压到 ±0.05,在观测标准差约 0.18 时,至少需要约 50 个独立查询,当前只有 2 个查询,任何“提升 7 个点”的说法都不该写进结论。

A/B 协议的最小要求是:配对而非分组,两个评分函数跑在同一批查询、同一批图上,逐查询记录差值;固定随机种子,保证 bootstrap 或后续随机采样可复现;预注册主指标,例如以 nDCG@5 为主、词级命中率为护栏,避免事后挑一个涨得最多的指标。原文的极简判定逻辑还规定,查询数少于 8 不下结论;主指标未达显著则判证据不足;护栏指标退化超过 0.02 则拒绝上线;bootstrap 与 t 检验结论不一致时,以区间更宽者为准。只盯 nDCG 会奖励“把低分项全砍掉”的粗暴改动,词级命中率能保证多词查询没有被悄悄牺牲。

五、依据一致率:给“可解释”本身打分
命中标签是该应用最特别的部分,也必须被审计。做法是把每条标签变成二元判断题:“标签声称冷色 95%,肉眼看是否成立”,由两个人独立判定,再算一致率与 Cohen’s κ;κ 会扣除随机一致的部分,比裸一致率严格。κ 低于 0.6 时,问题往往不在引擎而在标注指南:明显偏冷到底是多冷,细节丰富按整图还是按主体判定。把这些写成带例子的规则,比换算法更能提升一致率。
  1. def cohens_kappa(pairs):
  2.     n = len(pairs)
  3.     if n == 0:
  4.         return 0.0
  5.     po = sum(1 for a, b in pairs if a == b) / n
  6.     pa1 = sum(1 for a, _ in pairs if a == 1) / n
  7.     pb1 = sum(1 for _, b in pairs if b == 1) / n
  8.     pe = pa1 * pb1 + (1 - pa1) * (1 - pb1)
  9.     return (po - pe) / (1 - pe) if pe < 1 else 0.0
复制代码

六、结论与边界
这套审计最后要落回一句话:“可解释”不是一种质量,而是一种可审计性。它让每个错误能定位到某个词、某个百分比、某条融合规则;但定位之后是否正确,仍要靠标注、区间与配对实验来判断。qrels 只有 6 条时,指标的意义在固化口径,不在得出结论;截图上的数字是引擎输出,不是外部真值,只能作为一致性锚点。几何平均不一定优于加权平均,它会减少结果数量,对部分匹配的召回有伤害,是否采用必须由配对实验决定。四个指标、误差预算、配对 bootstrap 和护栏实验不依赖具体实现,只要能导出“查询→有序 doc_id 列表+逐项依据”,就可以迁移到其他检索应用。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙文搜图评测:nDCG、误差预算与配对bootstrap审计

这帖把“看榜单效果”推进到可复核的审计口径,思路很扎实。尤其是 qrels 只标截图确实读到的项、未抄录保留 None、不把没看清当 0 分,这一点能避免假负例,比直接拿榜单当标注可靠得多。P@5 只对已标注项计分、不把未标注项全算不相关,也很合理,否则小样本指标会被系统性压低。四个指标各测一件事的分工清楚,词级命中率单列尤其必要,算术平均和几何平均的差距说明融合补偿确实可能掩盖单词归零的问题。误差预算部分提醒显示取整就能带来约 ±2.3 分带宽,因此 62 分附近不宜过度解读,这个提醒很有实操价值。24 张图、6 条有效标注下,nDCG 小幅提升几乎不可能显著,用配对 bootstrap 看差值区间、区间跨 0 只说当前样本无法区分,措辞也严谨。后续如果继续做,建议把截图证据固定成登记表:查询、doc_id、grade、构建版本、截图时间和 None 都记下来,qrels 带版本号且只增不改;扩展标注时优先补全这两次查询的完整榜单,再报告指标和区间,这样审计链条会更完整。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙文搜图评测:nDCG、误差预算与配对bootstrap审计

这篇评测的审计口径挺扎实,尤其是先把 qrels 固定下来、用 None 区分“未抄录/不参与指标”,以及把 P@5、nDCG@5、词级命中率、依据一致率拆成四个正交指标,这些都比只报一个平均分更能复现问题。误差预算那部分也很有价值,显示取整和融合补偿确实会让 62 分这种标签被过度解读,几何平均和算术平均并排报是个好习惯。 小建议:既然样本只有 24 张、有效标注 6 条,建议把 qrels 快照和截图版本绑定,并额外记录已标注覆盖率,避免以后指标被未标注项比例变化带偏;配对 bootstrap 除了报区间是否跨 0,也可以把查询重采样次数、差值分布和区间宽度一起列出来,方便看出“不显著”是因为样本太小还是差距确实很窄。另外 P@5 只对已标注项计分的处理很谨慎,但最好在结果里注明有效 judged 数量,否则不同查询之间的 P@5 可比性会受影响。整体思路适合作为后续每次跑引擎的固定审计模板。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙文搜图评测:nDCG、误差预算与配对bootstrap审计

这套口径整理得很清楚,尤其是把 qrels 的“只增不改”和 None 不参与指标这两点先固定下来,比一上来就追求分数好看靠谱得多。拿七张截图当唯一证据、读不到就留空,这个约束其实很关键,否则很容易把没看清的项当成 0 分,凭空造出假负例,后面所有指标都会跟着偏。 误差预算那段挺实用。显示取整能拆出约 ±2.3 分的带宽,说明标签写 62 分时去区分 61.5 和 62.4 确实是过度解读;加权算术平均和几何平均那个 44.4 对 0.5 的对比也很直观,词级命中率单列是有必要的。P@5 只对已标注项计分的处理我理解,但有效标注只有 6 条时,分母会变得很小,容易出现个别项把 P@5 抬高的情形,建议在报表里同时带上“进入 top5 的已标注项数量”,不然读者只看数值会误判稳定性。nDCG 的理想序列如果也只由这几条有效标注决定,同样值得把有效标注数和覆盖率一起报出来。 小样本这块我的看法和你一致:24 张图、6 条标注的规模下,nDCG 从 0.71 到 0.78 这种幅度,配对 bootstrap 的 95% 区间大概率跨 0,这时候写“当前样本无法区分”是稳妥的,写成“没有差异”或者“B 更好”都越界了。qrels 只增不改有点像冻结测试集,实际做的时候建议把每次新增的标注单独存版本,避免事后悄悄改判导致前后不可比。 另外正文最后停在“原文给出 2”,配对 bootstrap
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-10 04:48 , Processed in 0.022074 second(s), 29 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部