第 4 步round 2政策 v1 与 v2

误报人工复核与字符 n-gram

第二步发现自动处置在测试集上的精确率是 0.904,达不到 0.99。这一步调查标注口径和拼写变体两种可能的解释:人工复核部分误报,并比较字符 n-gram 特征。两项检查都不能单独确认首轮差距的原因。

为什么做这一步

第二步的诊断留下两个调查方向。词典命中后被标为 toxic 的比例,选择集是 0.76,测试集是 0.51;这可能涉及评论内容或标注口径差异,不能直接证明测试集标注更宽松。测试集的 OOV 比例约是选择集的两倍,提示可以尝试字符特征,但尚不能说明拼写变体造成了多少误报。

这一步开始时项目仍采用首轮设计,自动处置层要求 0.99。做到一半,第三步把设计改成了全部人工确认,所以字符特征又在 v2 下重新比较了一次。两组结果都保留,读的时候要分清它们回答的是哪个设计下的问题。

误报人工复核

从首轮自动处置的 204 条误报里,按“是否命中固定词典”和“是否有其他标签为真”分层,按比例抽了 100 条。误报的定义与门槛一致:进了自动处置层,但触发它的标签在测试集里是 0。

分层(词典命中 / 其他标签为真)总体样本
lex/none13365
nolex/none6431
lex/other53
nolex/other21

先由 Claude 按一条写明的规则预读,再由项目负责人逐条读完,只在不同意的地方改判。这是看过预读结果的单人复核,不是独立标注者之间的一致性检验。判定规则:

人工改判了 11 条,方向有两种:讽刺和影射被改成 toxic,只是喊名字或只是提到身份词被改成 clean。

改判的 11 条
文本预读人工备注
== gay == are you gay?borderlinecleanMight be just a question
Alexhead8835 SHUT UP >:(borderlineclean
:Your timing sucks.borderlinetoxicYou
Then you stop messing around with my pag4e. I like the Civil War, and I don't want you and your stupid puffin…borderlinetoxic
== hey == u gay bro.toxicclean
You just inserted someone else's crap?borderlinetoxic
WHAT THE HELL Justinborderlineclean
Cool story bro'. What the fuck does it have to do with anything?borderlinetoxic
== what the hell? == why did you delete my edit! I WAS EXPRESSING MY OPINION!! YOU ARE RACIST!!!borderlinetoxic
==Stop the stupid edit wars== Seriously, decide what it says, and just keep it. Stop freaking changing it bac…borderlinetoxic
..why are you acting dumb??borderlinetoxic

最终结果:toxic 46,borderline 23,clean 31。

下面是条件敏感性估计,不是重标后的正式测试成绩:假定未复核的原真阳性仍然正确,把样本中的未加权比例外推到全部原误报。原始 Jigsaw 标签保持不变;这批历史自动处置误报也不是当前人工审核价值的独立评估集。

假设口径条件估计的自动处置精确率近似 95% 区间
按测试集标签0.904
假定判为 toxic 的原误报应算正确0.948[0.939, 0.958]
假定 toxic 和 borderline 都应算正确0.970[0.961, 0.978]

在上述假设下,要达到 0.99,2,125 条自动处置里最多只能有 21 条误报,换算到样本上至少要有 90 条被改计为正确。实际判为 toxic 的有 46 条,合并 borderline 也只有 69 条。区间由 Wilson 区间近似换算,未计入分层抽样、有限总体修正或人工判断的不确定性,不能视为完整的不确定性估计。

按本次人工复核口径,样本中仍有 31 条被判为 clean,不能把这些误报都解释为测试集漏标。攻击对象和语境是值得继续检查的因素;这次复核没有证明词袋特征必然无法识别它们,也没有量化各因素对总体缺口的贡献。

标签质量疑点与研究依据

2026-09-23 补充。Daniel Borkan 等,Jigsaw,2019:Nuanced Metrics for Measuring Unintended Bias with Real Data for Text Classification。中文题意为“利用真实数据细致衡量文本分类中的非预期偏差”。发表于 WWW 2019 Companion,DOI。

论文提供的依据

论文指出,毒性判断复杂且带有主观性;标注者偏见、用户构成和样本选择都可能造成模型学到不当关联。作者明确承认,跨群体的可靠测试标签是重要前提,并非所有应用都满足。这支持检查标签与抽样过程,不能直接证明本项目某条标签错误。见第 1 节。

论文的三个 AUC 指标不依赖某个固定阈值。这里的群体指评论所提及的身份群体,背景是该群体之外的评论;阳性和阴性均按评估标签划分。见第 3.1 节。

指标比较哪些样本低值提示什么
Subgroup AUC群体内部的阳性与阴性群体内部的区分能力较弱
BPSN AUC背景阳性与群体阴性群体阴性相对背景阳性被排得过高,可能导致误报
BNSP AUC背景阴性与群体阳性群体阳性相对背景阴性被排得过低,可能导致漏报

它们检查模型排序与标签的关系,不能单独鉴定标签质量,也不等于某个阈值下的 FPR 或 FDR。论文第 4.4 节还保留了标注者“难以判断”的选项,提醒我们不要把所有分歧都当成确定的标错。

与本项目的关系

本项目怀疑标签不足以支撑当前任务,有两类本地依据。第一,已有误报审计中,46 条被复核为 toxic、23 条为 borderline,说明原标签与本次判定口径存在分歧;但样本只来自历史误报,且由看过预读结果的一人复核,无法估计全测试集的标签错误率。第二,“值得送人工审核”与“已有毒性阳性标签”并不等价:含糊或需要语境的评论可能值得送审,最终却没有确认违规。这属于评估目标与标签含义的差异,不一定是原标签标错。

论文使用了另行构建、带身份标注的真实评论数据,不能把它的结论直接套到本项目的 Jigsaw 2018 测试行。当前身份词匹配只是代理分组,并不等同于论文的人工身份标注。

记录结论:标签可靠性和任务适配性值得复核,但模型偏差、标注分歧与任务口径不一致需要分别判断。目前保留原始标签与现行验收门槛;本文仅作为研究依据记录,不新增 AUC 实现。独立人工评估集继续暂缓。

字符 n-gram 改了什么

模型配置新增 model.analyzer:word 是原来的词级 TF-IDF;char_wb 是词边界内的 2 到 5 字符片段;word+char_wb 把两组特征并排。下游的六个逻辑回归、Platt 校准、阈值选择和路由都不变。对比用的配置只在这几行上与 baseline 不同。

首轮设计下的结果

这三次运行来自未提交的工作区(20260922T131503586656Z-baseline, 20260922T144755110181Z-char-ngram, 20260922T145018681873Z-word-char),数字可以从保存的运行目录复算,但不能从某个提交完整重现。

运行特征自动处置精确率95% 区间条数选择集精确率人工层精确率条数
baselineword0.904[0.891, 0.916]2,1250.9920.5514,185
char-ngramchar_wb0.898[0.886, 0.909]2,5140.9900.5114,420
word-charword+char_wb0.907[0.895, 0.918]2,4600.9920.5114,633
标签 APbaselinechar-ngramword-char
toxic0.7520.7740.780
severe_toxic0.3110.3090.319
obscene0.7730.7890.796
threat0.4580.4540.504
insult0.6960.7240.731
identity_hate0.4800.5600.562

排序在大部分标签上变好,identity_hate 提升最多,但自动处置的精确率区间互相重叠,没有一个接近 0.99。配对来看,word+char 去掉了基线 204 条误报中的 62 条,同时新放进 517 条,其中 87 条是新误报。人工复核里判为 clean 的行,word+char 仍送进自动处置的比例是 14/31。

v2 设计下的结果

两次运行都来自干净的提交 01897e45,配置只差特征。词特征这次运行与第三步那次运行的分层、队列精确率、各标签 AP 和模拟汇总完全相同;第三步那次来自未提交的工作区,这次说明它的结果可以从干净的提交复现。

分层与工作量

特征层级条数测试精确率95% 区间选择集精确率
wordpriority_review4,6250.763[0.750, 0.775]0.972
wordhuman_review1,6850.419[0.396, 0.443]0.797
word+char_wbpriority_review5,0300.756[0.744, 0.768]0.972
word+char_wbhuman_review2,0630.387[0.366, 0.408]0.794

需要人工审核的评论从 6,310 条增加到 7,093 条(占全部评论 9.86% 到 11.09%),队列精确率从 0.671 降到 0.649。

召回:真阳性和高风险评论去了哪里

特征标记真阳性被标记高风险被标记高风险进优先档高风险留在放行
word6,3104,233 / 6,243(67.8%)916 / 1,080(84.8%)838 / 1,080(77.6%)164
word+char_wb7,0934,603 / 6,243(73.7%)958 / 1,080(88.7%)874 / 1,080(80.9%)122

word+char 多抓到 370 条真阳性,留在放行里的高风险评论从 164 条降到 122 条。但它也多标记了 783 条。

相同标记量下的排序

为了把“排序更好”和“标记更多”分开,两个模型都按最大标签概率排序,取前 k 条,看抓到多少。

两幅折线图:横轴为按最大标签概率排序后标记的评论数,纵轴分别为抓到的真阳性数和高风险评论数。两条线几乎重合,word+char 略高;圆点标出两个模型实际的标记量。
两条曲线几乎重合,word+char 略高一点。word+char 的工作点更靠右,主要是因为它标记得更多。
kword 真阳性word+char 真阳性差word 高风险word+char 高风险差
6,3104,2344,338+104916941+25
7,0934,4884,601+113936958+22

真阳性和高风险评论要分开看。word+char 多出的 370 条真阳性中,约 255 条只要让词模型也标记 7,093 条就能得到,剩下约 115 条来自排序,所以真阳性的提升大约七成来自多标记。高风险评论不一样:多出的 42 条里只有约 20 条来自多标记,一半以上来自排序。换成漏检的角度看,标记 6,310 条时,词模型漏掉 164 条高风险评论,word+char 漏掉 139 条,少了约 15%,多出的主要是 identity_hate。按最大概率排序与路由实际使用的分标签阈值不完全相同,这里是近似的分解;复核用路由本身重做,结果相差不到 3 条。

按标签看也是一样。在相同条数下,word+char 每个标签的精确率都更高:

标签word 的条数word+char 的条数word 在 word 条数word+char 在 word 条数word 在 word+char 条数word+char 在 word+char 条数
toxic6,2487,0300.6630.6810.6250.642
obscene2,9393,1200.7730.7900.7530.774
insult1,1301,3460.8790.9060.8480.894

word+char 在人工审核阈值处的条数更多,是因为同一条“选择集精确率 0.90”的规则,在排序更好的模型上会选出更多行。它不是一个可以随意调低的阈值:把词模型的阈值调到同样条数,toxic 和 insult 的精确率会跌破门槛。

队列:同等审核量

第三步报告里的模拟固定的是进入人工队列后的到达率,两个模型每小时收到同样多的审核任务。

特征审核量/h危害代理值/人时高危完成高危未完成高危等待 p90,分钟
word10850.47 ± 3.40123.6 ± 17.40.2 ± 0.41.06 ± 0.08
word18070.24 ± 1.71184.2 ± 5.622.8 ± 5.31.63 ± 0.31
word+char_wb10848.26 ± 2.36118.8 ± 13.90.2 ± 0.41.29 ± 0.40
word+char_wb18067.62 ± 4.01172.2 ± 22.519.6 ± 2.11.55 ± 0.59

这个口径下 word+char 略差。5 个种子分不出差别,但复核用 200 个种子重跑后,差距是系统性的,每人时处理的危害低 3% 到 5%:它的队列里每条评论的平均危害更低(1.79 对 1.88)。注意这个口径让 word+char 看到的评论流比词模型少约 11%,它回答的是“每个审核任务的价值”,不是“哪个模型在同样的评论上做得更好”。

队列:同等评论流量

更接近实际的比较是固定进来的评论流量。每个种子生成一条评论流,两个模型共用;每个模型只审核自己标记的评论,被它留在放行层的高风险评论算作未审核。流量取词模型在 60 / 108 / 180 条每小时审核量时对应的评论流量,200 个种子,按种子配对比较。下表是优先排序,均值 ± 样本标准差,数量按一个 8 小时班次计。

评论/h特征审核任务完成率结束积压危害处理/h高风险留在放行高风险在队列未完成高风险未审核合计
608word481 ± 211.00 ± 0.000.1 ± 0.3113.0 ± 7.312.7 ± 3.60.2 ± 0.513.0 ± 3.6
608word+char_wb540 ± 221.00 ± 0.000.2 ± 0.7120.9 ± 7.59.4 ± 3.10.2 ± 0.59.6 ± 3.1
1,095word865 ± 310.99 ± 0.014.0 ± 4.9202.9 ± 10.822.5 ± 4.70.7 ± 0.823.2 ± 4.8
1,095word+char_wb973 ± 320.96 ± 0.0232.1 ± 22.4215.1 ± 10.316.7 ± 3.91.2 ± 1.117.9 ± 4.0
1,825word1440 ± 340.66 ± 0.02480.6 ± 34.4283.8 ± 9.936.7 ± 5.921.6 ± 4.758.4 ± 7.3
1,825word+char_wb1618 ± 360.59 ± 0.01658.0 ± 35.6292.7 ± 9.327.6 ± 4.925.5 ± 5.053.0 ± 6.8
评论/h排序审核任务差积压差危害处理/h 差高风险未审核差
608priority+59 ± 1+0.1 ± 0.0+7.9 ± 0.2-3.3 ± 0.2
608fifo+59 ± 1+0.1 ± 0.0+7.9 ± 0.2-3.3 ± 0.2
1,095priority+108 ± 1+28.1 ± 1.5+12.2 ± 0.2-5.3 ± 0.2
1,095fifo+108 ± 1+28.1 ± 1.5+7.8 ± 0.4-2.0 ± 0.3
1,825priority+178 ± 1+177.4 ± 1.4+8.9 ± 0.3-5.4 ± 0.3
1,825fifo+178 ± 1+177.4 ± 1.4-10.8 ± 0.3+9.7 ± 0.3

差值是 word+char 减词模型,± 为配对标准误。优先排序下,三个流量档位 word+char 都每小时处理更多危害,每个班次少漏 3.3 到 5.4 条高风险评论,因为它留在放行层的高风险评论更少。代价是审核量多约 12%:中间档位时它越过了 120 条每小时的容量,结束积压多 28 条。FIFO 排序在超载时结果反过来,高风险未审核反而多 9.7 条,所以这份收益依赖 v2 的优先排序。

回归门槛与成本

用 v2 的回归门槛检查两份报告:词特征 47 passed, 3 skipped in 1.30s;word+char 2 failed, 45 passed, 3 skipped in 1.36s。未通过的两项:

这些分类回归门槛参照词模型的实测值设定:toxic 的下限是词模型的 0.663 减 0.02。word+char 的 toxic 读数低约 0.001,复核的重抽样里有 43% 会通过,说明这一项对抽样敏感;它在原报告中仍未通过。相同条数下的精确率更高,提示不能仅凭这一项把结果概括为分类整体变差。

severe_toxic 的预测量高估相对词模型更严重,复核的所有重抽样也都如此。这是本次数据上的聚合校准诊断,不能据此断言字符特征放大了训练集与测试集之间的阳性率差异。这两次运行中,该标签未通过自身阈值触发路由;现行回归门槛保持不变。

特征完整运行耗时,秒模型文件,MB
word2917.6
word+char17042.4

独立复核

四个独立代理分别复核:一个不用对比脚本、直接从预测文件和报告重算所有数字;一个对同一批测试行做配对 bootstrap(5000 次)并评估模拟差异是否超出种子噪声;一个审查本分支的四个提交;一个逐条尝试推翻结论和建议。原始输出保存在 analysis/v2/verification_raw.json。

这里的独立复核指另外的代理重算和审查同一批结果,没有新增独立评估数据。以下保留复核意见;当前采用方案和后续安排以本页“结论与决定”为准。

重算

29 项检查中,所有计数和均值都与对比结果一致,包括两张模拟表的每一个格子。不一致的两项都是解读:真阳性“多数来自多标记”对高风险评论不成立;超载时 +3% 的危害处理量并不在噪声之内。

配对 bootstrap

两个模型给同一批测试行打分,所以按行做配对重抽样,比较 word+char 减去 word 的差值。区间以两个训练好的模型为条件,没有估计重新训练带来的方差。toxic 门槛只差 0.001,约 0.17 个标准误,43% 的重抽样会通过;severe_toxic 的高估相对词模型更严重,这一点在全部重抽样中都成立。

差值(word+char − word)点估计95% 区间
相同标记量 k=6310:真阳性+104[+55, +153]
相同标记量 k=7093:真阳性+113[+66, +160]
相同标记量 k=6310:高风险+25[+10, +40]
相同标记量 k=7093:高风险+22[+8, +36]
各自阈值下标记的真阳性+370[+320, +422]
各自阈值下标记的高风险+42[+26, +58]
队列精确率-0.0219[-0.0288, -0.015]
审核量相对增幅+0.1241[+0.1099, +0.1385]
toxic 人工审核阈值处精确率-0.0211[-0.0281, -0.0145]
severe_toxic 预测量高估+0.16[+0.1251, +0.1977]
同等审核量 priority@180 每人时危害(去掉种子噪声后的期望)-2.543[-3.436, -1.65]

代码审查

对结论的反驳

结论与决定

决定(2026-09-23,项目负责人):暂不采用字符 n-gram,默认保持词特征。model.analyzer 开关留在代码里,默认值是 word。

它有没有效果:有,但很小,而且集中在高风险评论上。相同标记量下,高风险漏检少约 15%,真阳性多约 2.5%,区间都不含 0。同一条评论流上,优先排序下每个班次少漏 3 到 5 条高风险评论。它没有解决第二步的问题:首轮设计下,自动处置精确率仍然在 0.90 左右。

为什么暂不采用:

之前的说法哪里不对:最初的判断是“收益主要来自多标记,把词模型阈值调低也能得到”。复核不支持把这句话用于高风险评论:相同标记量下仍有排序收益;把词模型阈值调到同样条数,高风险只多抓约 17 到 20 条,而且会让两项精确率门槛不通过。因此,本次保留 word 同时考虑了计算成本、审核容量和证据范围;字符特征在这些运行中的收益仍如实保留。

后续安排:当前继续使用 word,不启动新增独立数据采集或人工标注,也不修改现行门槛。独立数据验证仅保留为可选方向,暂缓且尚未启动。若以后决定开展,可再考虑是否将 word+char 纳入候选,并事先确定比较方法和验收要求。

后续考虑:独立人工评估集,暂缓

2026-09-23 记录。当前用“任一真实标签为阳性”近似衡量审核价值。对有歧义、需要结合语境判断的评论,即使人工最后确认没有违规,送审也可能合理;但缺少语境时,人工也可能无法判断。

后续可考虑建立独立评估集,覆盖优先审核、普通审核和放行,分别记录审核前是否值得送审、紧急程度与所需语境,以及审核后的结论、仍无法判断的情况和耗时。若开展,评估只提供实际可获得的语境,保留原始 Jigsaw 标签;已用于分析的审计样本作为开发案例,最终评估另用未参与调参的新样本。

状态:暂缓,尚未启动。新增抽样与独立人工标注的工作量较大,本次仅记录为后续可选方向,待资源允许时再决定是否开展。

如何复现

python scripts/audit_auto_action_fp.py --score analysis/auto_action_fp_audit
python scripts/run_pipeline.py --config configs/baseline.yaml
python scripts/run_pipeline.py --config configs/word_char.yaml
python scripts/compare_runs.py reports/<word run> reports/<word+char run> --equal-input --out analysis/v2
python record/collect_runs.py --features analysis
python record/render.py

v2 运行 20260923T074244236943Z-human-review-baseline 与 20260923T074315427980Z-word-char,commit 01897e454919,工作区干净。本页读取 features_run.json,它由 analysis/ 下的对比结果和人工复核结果汇总而来。