Featured image of post 从零开始讲清楚Elo级别分

从零开始讲清楚Elo级别分

象棋、电竞、段位分、和 Logistic 回归

如果你稍微关注过棋类比赛、电子竞技排位、甚至大语言模型能力排行榜,那么你很有可能见过「1400」、「1800」、「2500」这样形式的分数,或者这些隐藏分数所决定的「白银」、「钻石」、「特级大师」段位等等。你甚至可能听说过「Elo等级分」这个名词。

国际象棋等级分排行 LLM竞技场排行榜

如果你不满足于「分数高低就是代表能力强弱嘛」这个表面叙述,而是想深入了解「这些分是怎么算出来的」、「为什么可以按这个分排名」、「使用分数有什么好处/坏处」、「有其他可能性吗」,那么这篇文章正适合你。

本文将上述在对弈、电竞系统中用来表征选手级别的分数统称为「级别分」。

级别分是什么

很多文章会先直接塞给你最常见的「Elo等级分」的公式,再讲怎么用。但我想倒转过来:先圈定级别分的用处,再反过来看Elo的数学模型如何实现了这些用法。

按能力排序

级别分可以量化「能力」。更准确地说,它让多位选手可依其能力被排序。最终的结果,便是你看到的各种排行榜。

首先我们要知道级别分可以量化怎样的能力,因为并非所有类型的能力都能被轻易排序:

  • 不好比较的:「文无第一,武无第二」,文章好恶的标准因人而异,从而其优劣难以定论,但武功高低一较便知。
  • 能比较、但不好排序的:若把石头、剪刀、布看作三名选手,形成循环克制关系,就无法排出1-2-3的线性顺序1

级别分可以量化的是能比较且需要排序的能力。

不同的实际情况下,「比较」的方式也会不同。在某些竞赛里,存在按某种标准对所有选手同时计分且完成排序的全局手段:如百米冲刺计时,考试分数等。但在对弈类、对战类竞技中,「比较能力」的唯一方式是局部的:「一对一胜负」。

级别分仅适用于后者。它是把「一对一胜负」的局部结果换算成「整体能力排序」的方法。

一种理想的级别分:胜率

明确了级别分的输入是「一对一胜负」的历史结果,而输出是「整体能力排序」之后,我们先来看在一种理想情况下要怎么做这个换算。

假设有$N$名选手,他们两两对局,决出胜负(暂不考虑和局)。为了减少比赛的运气成分,每次对决会重复进行$M$次。当穷尽了所有$M\times N(N-1)/2$次比赛后,一个直观无争议的排名方式是,按选手各自的获胜次数来排序。也就是说,我们以充分的胜负结果决定选手能力

由于每位选手参加的比赛次数是相同的,当$M$足够大时,这里用来排序的数字,即所谓级别分,趋近于该选手对所有对手的平均胜率

这个洞见非常重要:所有级别分算法的核心都是在预测某种胜率。

在理想情况下,这个胜率可以在趋于无限次的充分比赛后轻松统计出。然而现实比理想残酷很多:

  • 选手数量$N$不固定。随时有新人加入,有老将退役,而级别分系统需一直持续。
  • 重复对决不充分。很难让$M$足够大到消除对比两位选手能力时运气因素。
  • 级别分需要「积累」。不能等大量比赛后再统一计算。最好能每场比赛后更新。
  • 对决匹配不可能真正均匀。在现实中,我们很难强迫象棋特级大师与一位初学者对局。

一个好的级别分系统,必须能在在上述诸多混杂因素之下尽量准确地估计胜率。

级别分的实际用途

级别分主要有两种用处:

排序选拔。不管是荣誉排行榜,还是方便晋级管理的段位制,这些需要公开、公正、全局决策的情况下,我们需要一个相对客观、绝对、简单的分数做排序和分层,即便选手的竞技能力并不能完全被这些数字表示。这一点和考试没有区别。

能力匹配。让选手找到与自身水平相近的对手,也即「胜率在50%左右的匹配」。这样比赛才有意思,也能给选手们提供快速学习进步的环境。纯粹的随机匹配只会导致大量无积极意义的虐与被虐。围棋的段位比赛、电竞的天梯,都是这个道理。

马上可以注意到的一点是,「能力匹配」其实不必建立在「排序选拔」所需的全局分数之上,因为我们可以用任意复杂的现代非线性方法(如个性化推荐系统)给任一选手$A$找到一批局部胜率 $P(胜|对手是A)$ 约50%的对手,而不是那些级别分相差不多的选手(在上述理想情况下,等价于总体胜率 $P(胜)$ 与$A$相近的选手)。

如果你一眼还看不出上面这两种描述有什么区别,可以考虑「技术克制」的情况。例如一位乒乓球选手$A$非常不擅长应对削球,所以面对一位专精削球但其他方面技术较弱的选手$B$时,两人胜负各半,而且$A$在这个过程中能针对自己弱点进行训练。但由于$B$的整体技术远不及$A$,所以在按级别分匹配的系统中,二人很难相遇。

虽然使用另一套建立在局部胜率上的匹配系统能够更灵活地提升选手的比赛体验,但在竞技公平公正的大原则下,由于使用单一分数同时作为选拔和匹配的依据对绝大多数人来讲都更简单易懂,可以避免争议,所以级别分匹配制在很多现代在线游戏中也一直被沿用下来。

所以级别分到底是什么……

综上,级别分本质上是一个卡着极细瓶颈的胜率预测模型:

flowchart LR
    n1["历史胜负记录"] --> n2["选手A的级别分"] & n3["选手B的级别分"] & n4["选手C的级别分"] & n5["选手D的级别分"]
    n2 --> n6(["预测A与C对决胜率"])
    n4 --> n6

    n1@{ shape: procs}
    n2@{ shape: rounded}
    n3@{ shape: rounded}
    n4@{ shape: rounded}
    n5@{ shape: rounded}

把所有过往对决的「胜负记录」压缩成每位选手一个分数,从而使用任意两位选手的分数就可以最优预测两人对决的「胜负概率」。

需要再次强调,这里的「最优」,是限制在只能使用双方各自一个分数的外界条件之下。

拆解Elo等级分

厘清级别分系统的适用场景之后,我们来研究下最经典最常见的Elo等级分怎么实现所需功能。

一点背景:阿尔帕德·埃洛(Arpad Elo,1903-1992)是美籍匈牙利裔物理学家,也是一位国际象棋大师。他在1960年发明了Elo等级分系统,该系统首先被美国国际象棋协会采用,很快流行开来,并于1970年成为国际棋联的正式评分系统。

国际棋联颁发的职业棋手称号有如下大致对应:

  • 2500分以上:国际特级大师
  • 2400-2499分:国际大师
  • 2300-2399分:棋联大师

而业余棋手的分数一般在1400到2200之间。2

Elo在各类电竞游戏中也广泛应用。例如,王者荣耀的钻石段位对应约2000分,而王者段位需要2400分以上。

用Elo等级分估算胜率

先看看怎么用Elo级别分来预测胜率。Elo的核心公式极其简洁:将选手$A$和选手$B$的Elo分数计为$R_A$和$R_B$,那么两人对弈时$A$的胜率估计为

$$ \hat{P}(A胜) = \frac{1}{1+10^{(R_B-R_A)/400}} $$

$B$的胜率估计是对称的

$$ \hat{P}(B胜) = 1-\hat{P}(A胜) = \frac{10^{(R_B-R_A)/400}}{1+10^{(R_B-R_A)/400}} = \frac{1}{1+10^{(R_A-R_B)/400}} $$

在Elo等级分的模型之下,一对选手的胜率仅由双方级别分之差决定:$x=(R_B-R_A)/400$。也就是说,那些1400、2200之类的分数,其绝对数值是没有意义的,只有两者的相对差才有。这里的400也只是个约定俗成方便书写记录的标准化分母,同样没有实际意义。如果你把所有人的级别分都加上或者减去任意常数、再乘除任意常数,不会对Elo的模型产生任何实质影响。

而公式里的函数$f(x)=1/(1+10^x)$只是为了将级别分差 $x$ 映射成一个合法的在$0$到$1$之间的概率值:

  • 当$R_B=R_A$时,双方胜率估计都等于$1/(1+10^0)=1/2$
  • 当$R_B-R_A$趋于正无穷大$+\infty$时,$A$的胜率趋于$1/\infty$,即$0$
  • 当$R_B-R_A$趋于负无穷大$-\infty$时,$A$的胜率趋于$1/(1+0)=1$

有了公式,在实际运用中就能快速估算胜率:

分数差 ($R_A - R_B$)A的预期胜率
+800~99%
+400~91%
+200~76%
+100~64%
050%

用胜负结果计算Elo等级分

再看看Elo等级分如何由历史胜负结果计算。如果$A$与$B$在一局对弈中,$B$获胜,那么双方的分数会发生如下更新:

$$ \begin{align*} R_A^{新} &= R_A+K(0-\hat{P}(A胜))\\ R_B^{新} &= R_B+K(1-\hat{P}(B胜)) \end{align*} $$

这里$K$是一个人为设置的参数,表示单局比赛里Elo级别分的理论最大变动幅度。在国际象棋中,大师比赛按例用$K=16$;而新手比赛用$K=32$,允许分数有更多变动。上方公式中的$0$表示$A$输了,而下方公式中的$1$表示$B$赢了。如果是和局,那么两行都会用$0.5$。双方分数变化之和始终为零——符合零和游戏要求。

最后,也是最重要的性质:胜利者级别分的上升值被自己在本局的胜率预测打了折扣

假设$K=32$:

  • 若原本$\hat{P}(B胜)$为99%,也就是$B$比$A$高800分时,这次胜利仅给$B$加了0.32分
  • 但倘若$\hat{P}(B胜)$为36%,也就是$B$比$A$低100分时,这次胜利给$B$加分则是可观的20.5分

这意味着高手虐菜的收益非常之少,而黑马胜出则获利颇丰。再换言之,原本的预测离比赛结果越远,那么分数就会得到越大的更新,从而更快地纠正下次的预测

没有参加过任何正式比赛的新手,一般会被给予1200到1500的初始分。各系统惯例不同,有些协会要求新手先参加一次小型锦标赛,然后根据其成绩加上已有级别的对手的分数来给予初始分。之前没有赛绩但实力优秀的选手会因为一次次击败分高的对手(尤其是新手比赛中设置的较高$K$值),快速上升到自己应有的级别。

flowchart LR
    n2["选手A当前级别分"] --> n6(["预测A与B对决胜率"]) & n8["选手A的新级别分"]
    n4["选手B当前级别分"] --> n6
    n6 --> n7["A与B本场比赛结果"] & n8 
    n7 --> n8 & n9
    n6 --> n9["选手B的新级别分"]
    n4 --> n9
    n2@{ shape: rounded}
    n4@{ shape: rounded}
    n8@{ shape: rounded}
    n9@{ shape: rounded}

以上就是整个Elo等级分的「生态闭环」。用双方级别分在赛前估算胜率、赛后更新分数都非常简单,选手们甚至可以在赛场上手算。

当然,如果一位选手的目的是尽可能精确地估计胜率,那Elo模型是极为简陋甚至可笑的:它竟然认为单单一个数字(选手分数之差)就足以预测一场比赛的胜负概率!一些显而易见能提升胜率预测精度的数据,如电竞的平均击杀数、棋类的妙招漏着统计、单看双方历史战况或者近期对弈状态等等,一个都没用上。但它本来就不是一个追求胜率预测要如何之精准的模型,而是要把影响胜负的选手实力压缩为一个数字

用统计和机器学习的术语来讲,这叫做单自由度的表征学习,也就是通过一个预测性的任务(预测胜率)来提取原始数据(胜负记录)里的精华(决定胜负的能力值)。

Elo级别分的统计解释

本节仅为有统计、机器学习专业背景的读者而写

Elo系统就是把所有选手的级别分当作参数的二元分类线性模型(Logistic Regression),其中参数优化使用了以负对数似然(Negative Log Likelihood)为损失函数(loss function)的在线随机梯度下降法(Stochastic Gradient Descent, SGD)2

本节的数学记号切换回常用符号。令 $\bm{\theta}=(\theta_1,\dots,\theta_N)$ 为 $N$ 位选手当前级别分,下一次比赛(第 $t$ 次)的数据为 $(\mathbf{x}_t,y_t)$,其中:

  • 特征 $\mathbf{x}=(x_1,\dots,x_N)$ 用来表示比赛双方是谁:$x_i=1$ 指第 $i$ 位选手是 $A$,$x_j=-1$ 指第 $j$ 位选手是 $B$,其他的 $x_n=0,n\neq i,j$
  • 二元目标 $y = 1$ 表示这场比赛结果是 $A$ 胜,$y = 0$ 则是 $A$ 负(即 $B$ 胜;假设不存在和局)。

不失一般地,我们把原Elo公式的对数底从 $10$ 改为 $e$, 并移除 $400$ 的标准化因子,它就变成了Logistic回归模型对 $A$ 胜利概率 $P(y=1|\mathbf{x})$ 的预测:

$$ \hat{y}_t = \frac{1}{1+e^{-\bm{\theta}^\intercal\mathbf{x}_t}} $$

注意到 $\bm{\theta}^\intercal\mathbf{x}_t = \theta_i-\theta_j$。模型的损失函数就是标准的负对数似然函数:

$$ \mathcal{L}(y_t,\hat{y}_t) = -y_t\log{\hat{y}_t} - (1-y_t)\log{(1-\hat{y}_t)} $$

那么针对第 $t$ 次比赛样本的随机梯度迭代为:

$$ \bm{\theta}^{(new)}=\bm{\theta}-\eta \nabla \mathcal{L}(y_t,\hat{y}_t) $$

其中 $\eta$ 为学习率。假设这局 $y_t=1$,即 $A$ 获胜,那么 $A$ 的级别分 $\theta_i$ 的迭代为:

$$ \begin{align*} \theta_i^{(new)} &= \theta_i-\eta \frac{\partial}{\partial \theta_i} \mathcal{L}(y_t,\hat{y}_t) \\ &= \theta_i+\eta \frac{\partial}{\partial \theta_i} (y_t\log{\hat{y}_t} - (1-y_i)\log{(1-\hat{y}_t)}) \\ % &= \theta_i+\eta \frac{\partial}{\partial \theta_i} \log{\hat{y}_t} \\ % &= \theta_i+\eta \frac{\partial}{\partial \theta_i} \frac{1}{1+e^{-\bm{\theta}^\intercal\mathbf{x}_t}} \\ &= \theta_i+\eta \frac{\partial}{\partial \theta_i} \log\frac{1}{1+e^{\theta_j-\theta_i}} \\ &= \theta_i+\eta (1-\frac{1}{1+e^{\theta_j-\theta_i}}) \\ &= \theta_i+\eta (1-\hat{y}_t) \\ \end{align*} $$

倒数第三步到第二步利用了链式法则和Sigmoid函数的求导性质。最后的结果,正是上一节提到过的分数更新公式: $R_A^{新}=R_A+K(1-\hat{P}(A胜))$。

所以Elo级别分系统说白了,就是在手算Online Logistic Regression。

超越级别分

我们已经知道了级别分有何用武之地,又梳理了最经典的Elo等级分系统的背后脉络。显而易见,下个问题自然是:我们能做得更好吗?

如果「能力匹配」可以和「排序选拔」分开的话,级别分模型正中间的「单自由度」瓶颈就能够被松绑,换来更加灵活复杂的建模可能性。

Elo系统使用的是最简单的二元分类模型,那么我们可以换上一个大型神经网络,用循环、卷积、注意力等黑盒编码器来审视比赛过往结果,输出精确得多的胜率预测。同样地,我们也可以采用更前沿的自适应梯度优化器来在每场比赛后更新参数——这些参数可就比人手一个的级别分要繁复得多,但同时也就变得不好解释。我们可以给每个选手一个多维向量而不是一个单一数值表示一位选手的能力,再用降维可视化的办法设计一些六边形战士图,接着将胜率的预测或者与结果的差距归因到某些能力维度上,暴露出选手潜在的能力弱点,从而在之后设计针对性训练。我们甚至可以抛弃单一且短视的当前胜负标准,引入更多长期积极指标——例如线上团队匹配后的长期合作倾向、选手的快速成长期等等。这些复杂的「多能力-多结果」模型能为选手在不同场合下个性化定制匹配对手,来使双方都能获得更有效的进步机会或者更多乐趣。

而对于公开选拔、生成排行榜这些用途,级别分是够用的。Elo系统简单易算、透明公开,即便后来有了很多衍生改进(Glicko3,引入单个选手的能力发挥稳定性衡量;TrueSkill4,引入团队贡献和自洽的贝叶斯更新),也丝毫不显得过时。

但我们还是得警惕那些很想在一个线性的排行榜上「过度解读」的冲动。很多时候,我们关心的能力也好,特质也好,是不可排序的。从剪刀石头布,到大学排行榜,生活中的事物总是要比一列数字复杂太多。

正如Elo教授于1982年接受采访时的感慨5

Sometimes I think I’ve created a Frankenstein’s monster with this system because some of the young players become just like race track habitues who never really see a race; all they do is peruse the tote sheets.

有时我觉得自己(用Elo等级分)创造了科学怪人,因为一些年轻棋手变得就像赛马场的赌徒一样,从不真正关注比赛,只埋头研究赔率表。

Arpad Elo (Photo from wikipedia)

Licensed under CC BY-NC-SA 4.0
主题 StackJimmy 设计