背景介绍
参考各类竞技比赛的评分排序系统,我们在具体公司业务上也可以进行相应评分排序,从而得到最能体现用户偏好的商品评分系统。
- 目标
- 从用户角度出发,给出平台商品的真实排序
- 数据
- 需要数据类型:A和B比赛的胜负数据,即(A,B,1)代表A击败B
- 例如在有A和B同时曝光可选时,用户选择了A,则代表A击败B一次
- 方法
- Elo rating system
- Glicko rating system
Elo rating system
Elo等级分制度(Elo rating system)是指由匈牙利裔美国物理学家 Arpad Elo创建的一个衡量各类对弈活动水平的评价方法,是当今对弈水平评估的公认的权威方法。被广泛用于国际象棋、围棋、足球、篮球等运动。游戏界比较著名的应用有: WOW(魔兽世界)、DOTA、LOL。
计分方法
系统中有A和B两位选手,$R_A$ 和$R_B$分别代表A与B的当前等级分,之后A和B的进行一次竞技,结果记为$S_A$(如果A胜则$S_A=1$,负为0,平为0.5)。该次竞技后A的等级分更新如下:
$$ R_{A}^{‘} = R_A + K(S_A - E_A) $$
其中:
- $E_A$,代表A相对于B的获胜概率(胜率期望值)
- $E_A=\frac{1}{1+10^{(R_B-R_A)/400}}$
- $K$ 为一个常数,代表理论上最多可以赢一个玩家的得分和失分
- K/2就是相同rating的玩家其中一方胜利后所得的分数
- 在大部分的游戏规则中,K=32; 国际象棋大师赛中,K=16
- 竞技的选手水平越高K取值越小(避免少数比赛改变顶尖玩家排名)
- Elo模型原先采用正态分布。但是实践显明棋手的表现并非呈正态分布,所以现在的等级分计分系统通常使用的是逻辑分布。
- 公式中分母的400来由: 根据公式可以得出,当K值相同的情况下,越高的分母,越低的积分变化。总体来说400是一个平衡的、让多数玩家积分保持标准正态分布的值
实例说明
若当前A玩家积分为1500,B玩家积分为1600
- 预估A玩家的胜负值: Ea = 1/(1+10^[(1600-1500)/400])≈ 0.36
- 预估B玩家的胜负值: Eb = 1-Ea = 1-0.36 = 0.64
- 假设A玩家获胜,实际胜负值为Sa = 1
- A玩家最终得分为 :R’a = 1500 + 32*(1-0.36) = 1500+20.5 = 1520
- A玩家赢20分,B玩家输20分。
- 假设B玩家获胜,实际胜负值为Sa = 1
- B队最终得分为 R’b = 1600 + 32*(1-0.64) = 1600 + 11.52 = 1612
- B玩家赢12分,A玩家输12分。
Glicko rating system
Glicko是由Mark Glickman提出的方法,是对Elo评分系统的改进,加入了评分偏差项RD(ratings deviation)。
- 考虑未进行对战的时间长度,时间越长则RD越大
- 举例解释:一个很久未参与竞技比赛的选手A,其能力值很可能不再等于系统记录的$R_A$,如果A与能力值相同的B($R_A=R_B$)比赛,而选手B是近期一直活跃在系统的玩家,则明显能力值更加可信。
- 若A击败B,则A加分应该更多,B减分应该更少
- 对于A:其能力不确定,击败了系统中相同等级的对手,说明很可能A的能力早已高于系统的记录,因此需要‘快速加分’
- 对于B:被一个不太确定能力的人击败,说明A很可能本来就比B强,因此被击败不应该扣除太多积分,因此需要‘减少降分’
计分方法
对于选手A,1)记其能力评分(rating)为$r$;2)偏差(可理解为:标准差)为$RD$,为了方便计算,记方差为$v$ ($v=RD^2$);3)第$j$次的比赛结果为$S_j$。则其进入系统后,随着比赛的增加,其得分相应计算如下:
注意:比赛以周期为单位更新选手评分,此处假设选手A在一个周期t+1内,参与了m次比赛
- Step1:初始化评分
- a) 无历史评分则,评分$r=1500$,方差$v=350^2$ (初始分可根据实际情况设置为其他数值)
- b) 有历史评分则,评分 $r=r_{old}$,方差$v=min(v_{old}+c^2t,350^2) $
- $c$,衡量时间因素的常量系数
- $t$,本次比赛和上次比赛的时间间隔(几个时间周期)
- Step2:更新评分$r_{new}$与方差$v_{new}$
- 方差:
$$ v_{new}=(\frac{1}{v}+d)^{-1} $$ - 评分:
$$ r_{new}=r+qv_{new}{\sum_{j=1}^{m}k_j(s_j-e_j)} $$ - 其中:
- 对比Elo的常量$K$,Glicko的系数是方差的函数:$k_j=\frac{1}{\sqrt{1+3q^2v_j/\pi^2}}$ (实际上要和Elo的$K$对等,还需要再乘$qv^*$)
- 对比Elo的$E_A$,Glicko的获胜概率期望值加入$k_j$乘数,从而也和方差$v$有关:$e_j=\frac{1}{1+10^{-k_j(r-r_j)/400}}$
- $q=ln(10)/400$
- $d=q^2\sum_{j=1}^{m}k_j^2e_j(1-e_j)$
- 方差:
预测方法
现有选手A,其评分和方差为$(r_a,v_a)$,若A与$(r_b,v_b)$的选手B进行比赛,则可预测A的胜率为:
$$ e_{ab}=\frac{1}{1+10^{-k_{ab}(r_a-r_b)/400}} $$
其中,
$$ k_{ab}=\frac{1}{\sqrt{1+3q^2(v_a+v_b)/\pi^2}} $$
tips
- 关于$RD$:随着选手的活跃,参赛次数的增加,偏差会越来越小,$RD$太小会导致选手即使提升了能力赢得比赛,也只能加极少的分数,一般应用中会设置$RD$的下限,例如 $ RD=max(30,RD)$
- 置信区间:根据 quasi-Bayesian derivation of the Glicko system,一般可以认为95%的置信区间如下:
$$(r-1.96RD,r+1.96RD)$$
工程实现
使用 Alec Stephenson 写的R包PlayerRatings
共有参数
- data,数据,由四列组成:
- 时间:第几个比赛周
- 主场方方选手名称,比如说中国队和西班牙队这次在中国比赛,那么中国为主场方
- 非主场方选手名称
- 得分,胜=1,平=0.5,负=0
- status,当前计分系统的状态数据框
- 主要包括:选手名称(Player)、评分(Rating)、比赛总场次(Games)、胜场次(Win)、平场次(Draw)、负场次(Loss)、该队结束比赛后还剩的比赛周次(Lag)
- 有‘RD’参数的系统,例如Glicko,还包括Deviation列
- gamma,对主场方的偏置
- 主要用于预测,例如在A的地区和B比赛,那么同等水平下会A的胜率应该更高
- 建模函数中gamma默认为0,而预测函数(
predict()
)中gamma默认为30
建模函数
elo()
,实现Elo评分系统,主要参数:- data,status=NULL,gamma=0
- init,初始分,默认
init = 2200
- kfac,K值,
- 给定常数,默认
kfac=27
- 也可以设置不同规则下的K值,例如场次在30以上取26,否则取32(
kfac=kgames
)
- 给定常数,默认
glicko()
,实现Glicko评分系统- data,status=NULL,gamma=0
- init,初始分和标准差,默认
init = c(2200,300)
- cval,衡量时间因素的常量系数,默认
cval = 15
,(区别于Elo的重要参数)
steph()
,实现作者基于 Glicko 改进的 Stephenson 评分系统- status = NULL, gamma = 0,
- init,初始分和标准差,默认
init = c(2200,300)
- cval = 10, hval = 10, bval = 0, lambda = 2
- 区别于其他系统的重要参数
- 详细修改点和公式见Glicko rating system