奖励模型是一面哈哈镜
RLHF 里最被低估的失效模式不是 reward hacking,而是标注者偏好的不一致性如何被模型放大成一种稳定的人格缺陷。
大家讨论 RLHF 的失效模式时,第一个想到的总是 reward hacking——模型找到了奖励函数的漏洞,输出一些得分很高但毫无用处的东西。
这确实会发生,但它有个好处:很显眼。模型开始疯狂输出”作为一个 AI 助手,我很乐意帮您”的时候,任何人都能看出不对。
真正麻烦的是那些不显眼的。
不一致性会被放大,而不是被平均
直觉上,我们会认为多个标注者的偏好噪声应该互相抵消,最后留下”平均偏好”。
但奖励模型不是在拟合平均值,它是在拟合一个排序。当标注者 A 认为详细的回答更好、标注者 B 认为简洁的回答更好,模型学到的不是”中等长度最好”,而是一个在两种模式之间摇摆的、内部矛盾的判据。
然后 PPO 会去优化这个矛盾的判据。结果是模型找到某种”两边都不得罪”的表达方式——通常表现为大量的限定语、免责声明和模糊表述。
那个 项不是随机噪声。它和输入强相关——在有争议的话题上大,在事实性问题上小。所以模型学会了:在争议话题上变得含糊,是一种可靠的得分策略。
怎么发现它
看标注者间一致性(inter-annotator agreement)是不够的,因为它是个全局统计量。我们的做法是按话题分桶来看:
from collections import defaultdict
import numpy as np
def agreement_by_topic(annotations, topics):
"""
annotations: {(sample_id, annotator_id): preferred_index}
返回每个话题的两两一致率
"""
by_topic = defaultdict(list)
for sid, topic in topics.items():
votes = [v for (s, _), v in annotations.items() if s == sid]
if len(votes) < 2:
continue
# 两两比较,统计一致的比例
pairs = [(a, b) for i, a in enumerate(votes) for b in votes[i+1:]]
agree = sum(1 for a, b in pairs if a == b) / len(pairs)
by_topic[topic].append(agree)
return {t: float(np.mean(v)) for t, v in sorted(by_topic.items())}跑出来的结果通常很有启发性:事实类问题一致率能到 0.9 以上,而涉及价值判断的话题往往掉到 0.55——只比随机猜好一点。
在一致率 0.55 的数据上训奖励模型,等于在教模型模仿一个精神分裂的评判者。
我们的应对
不是什么高明的技术,就是三条笨办法:
- 分领域训练奖励模型,而不是一个通吃。至少把”事实性”和”风格偏好”拆开。
- 一致率低于阈值的样本直接丢弃,而不是取多数票。多数票在 0.55 一致率下几乎没有信息量。
- 给标注者写更严格的规范,并且定期用同一批样本做校准测试。
第 3 条最费力,收益最大。我们花了三周重写标注规范,一致率从 0.61 提到 0.78,比任何算法改进的效果都明显。
数据标注是一个需要设计的系统,不是一个需要外包的任务。
如果你觉得我某个判断是错的,欢迎写信讨论。
