详解 ELO 评分系统
文章目录
- ELO 分数的原理
- Chatbot Arena中使用 ELO 分数评估模型
- 代码实现(评估 AI 模型的 ELO 评分系统)
- 代码说明
ELO 分数的原理
ELO 的全称是 “Elo Rating System”,中文名为 “埃洛等级分制度”。
它是由匈牙利裔美国物理学家阿帕德・埃洛(Arpad Elo)创建的一个衡量各类对弈活动水平的评价方法,最初用于国际象棋的棋手排名,如今广泛应用于各类竞技游戏、体育比赛等领域,通过一套复杂的算法来评估参与者的实力水平。
ELO 分数的核心原理是,基于预期表现与实际结果的差异来调整分数。
Chatbot Arena中使用 ELO 分数评估模型
https://arxiv.org/abs/2403.04132
工作原理:
- 互联网上的随机用户输入一个提示词
- 用户会收到来自两个模型的回复,不知道这些回复来自哪个模型
- 用户评价哪个回复更好
- 根据 pairwise 的排名,计算出 ELO 分数
- 最后得到所有模型的排名
用 ELO 评估 AI 模型回复质量,其逻辑可简化为:
- 初始分数:每个新模型赋予相同的初始 ELO 分数(如 1000 分)。
- 预期胜率:当两个模型 A 和 B 对比时,根据当前 ELO 分数计算 A 优于 B 的概率(预期胜率):
EA=11+10(RB−RA)/400E_A = \frac{1}{1 + 10^{(R_B - R_A)/400}}EA=1+10(RB−RA)/4001
其中 RAR_ARA、RBR_BRB 分别为 A 和 B 的当前 ELO 分数,EAE_AEA 是 A 被用户评价为更好的概率(EB=1−EAE_B = 1 - E_AEB=1−EA 是 B 的预期胜率)。 - 实际结果:用户评价后,胜者得 1 分,败者得 0 分(若平局可各得 0.5 分)。
- 分数更新:根据实际结果与预期胜率的差距调整分数:
RA′=RA+K×(SA−EA)R_A' = R_A + K \times (S_A - E_A) RA′=RA+K×(SA−EA)
RB′=RB+K×(SB−EB)R_B' = R_B + K \times (S_B - E_B) RB′=RB+K×(SB−EB)
其中 SAS_ASA、SBS_BSB 是实际得分(1 或 0),KKK 是调节系数(控制分数变化幅度,如取 32)。
代码实现(评估 AI 模型的 ELO 评分系统)
以下是一个简化的 Python 实现,模拟通过用户 pairwise 评价更新模型 ELO 分数的过程:
class ModelELO:def __init__(self, initial_rating=1000, k=32):"""初始化ELO评分系统:param initial_rating: 新模型的初始分数:param k: 调节系数(分数变化幅度)"""self.ratings = {} # 存储模型名称到ELO分数的映射self.k = kself.initial_rating = initial_ratingdef add_model(self, model_name):"""添加新模型(若不存在则初始化分数)"""if model_name not in self.ratings:self.ratings[model_name] = self.initial_ratingdef expected_score(self, rating_a, rating_b):"""计算模型A优于模型B的预期概率"""return 1 / (1 + 10 **((rating_b - rating_a) / 400))def update_ratings(self, model_a, model_b, winner):"""根据用户评价结果更新两个模型的ELO分数:param model_a: 模型A名称:param model_b: 模型B名称:param winner: 获胜模型名称(model_a 或 model_b)"""# 确保模型已添加self.add_model(model_a)self.add_model(model_b)# 获取当前分数ra = self.ratings[model_a]rb = self.ratings[model_b]# 计算预期分数ea = self.expected_score(ra, rb)eb = 1 - ea# 确定实际得分(胜者得1分,败者得0分)sa = 1 if winner == model_a else 0sb = 1 if winner == model_b else 0# 更新分数self.ratings[model_a] = ra + self.k * (sa - ea)self.ratings[model_b] = rb + self.k * (sb - eb)def get_ratings(self):"""返回所有模型的当前ELO分数(按分数排序)"""return sorted(self.ratings.items(), key=lambda x: x[1], reverse=True)# 示例:模拟用户评价过程
if __name__ == "__main__":# 初始化ELO系统(初始分数1000,K=32)elo_system = ModelELO(initial_rating=1000, k=32)# 模拟3个模型:ModelX、ModelY、ModelZmodels = ["ModelX", "ModelY", "ModelZ"]for model in models:elo_system.add_model(model)# 模拟5次用户评价(每次随机选两个模型,用户选择更好的回复)evaluations = [("ModelX", "ModelY", "ModelX"), # 用户认为ModelX更好("ModelX", "ModelZ", "ModelZ"), # 用户认为ModelZ更好("ModelY", "ModelZ", "ModelZ"),("ModelX", "ModelY", "ModelY"),("ModelX", "ModelZ", "ModelZ")]# 更新分数for a, b, winner in evaluations:elo_system.update_ratings(a, b, winner)print(f"评价后:{a} vs {b},胜者{winner},当前分数:{elo_system.get_ratings()}")# 最终排名print("\n最终ELO分数排名:")for model, score in elo_system.get_ratings():print(f"{model}: {round(score, 1)}分")
代码说明
1.核心类 ModelELO
- __init__
:初始化评分系统,设置初始分数和调节系数 KKK(KKK 越大,单次评价对分数影响越大)。
add_model
:添加新模型并初始化分数(支持动态纳入新模型,符合你描述的“可容纳新模型”特点)。expected_score
:计算模型间的预期胜率(基于当前 ELO 分数)。update_ratings
:根据用户评价结果(哪个模型回复更好)更新分数,核心是通过“实际结果 - 预期结果”的差值调整。
2.示例运行流程- 初始化 3 个模型,模拟 5 次用户评价。
- 每次评价后,获胜模型分数上升,失败模型分数下降,变化幅度取决于两者的初始差距(差距越大,强者赢了加分越少,弱者赢了加分越多)。
3.特点
- 实时性:每次用户评价后立即更新分数,反映模型性能的动态变化。
- 扩展性:通过
add_model
可随时加入新模型,与现有模型对比。
这种机制能客观反映模型在真实用户反馈中的相对表现,广泛用于 AI 模型的动态评估(如大语言模型的回复质量排序)。