科技微讯

用户评论排序方法:威尔逊置信区间

在 v2ex 有人发帖问:如何优雅处理社交系统的评论权重?

这个帖子引起了我的兴趣,因为我写的微信小程序“通知中心”也有评论系统,我的排序方法综合考虑了点赞数、点踩数、字数、发布时间、是否被删除这五个因素,但点赞、点踩之间的权重计算我一直不太满意。

所以我认真看了这个帖子提到的以下两篇文章:

Evan Miller 在 2009 年的一篇文章中分析了为什么要使用威尔逊置信区间(Lower bound of Wilson score confidence interval for a Bernoulli parameter)对项目进行排序,该算法解决了什么问题,以及具体的实现方法。如果你英文或数学不是很好,可以看阮一峰写的基于用户投票的排名算法,这篇文章大体上是 Evan Miller 文章的翻译,但有所补充,更易于理解。

以下是使用 javascript 对威尔逊置信区间算法的实现,核心是 lower_bound() 函数:

const epsilon = 0.0001;

//出处:https://github.com/simple-statistics/simple-statistics/blob/main/src/inverse_error_function.js
function inverseErrorFunction(x) {
  const a = (8 * (Math.PI - 3)) / (3 * Math.PI * (4 - Math.PI));
  const inv = Math.sqrt(
    Math.sqrt(
      Math.pow(2 / (Math.PI * a) + Math.log(1 - x * x) / 2, 2) -
        Math.log(1 - x * x) / a
    ) -
      (2 / (Math.PI * a) + Math.log(1 - x * x) / 2)
  );
  if (x >= 0) {
    return inv;
  } else {
    return -inv;
  }
}

//出处:https://github.com/simple-statistics/simple-statistics/blob/main/src/probit.js
function probit(p) {
  if (p === 0) {
    p = epsilon;
  } else if (p >= 1) {
    p = 1 - epsilon;
  }
  return Math.sqrt(2) * inverseErrorFunction(2 * p - 1);
}

//出处:https://gist.github.com/timelf123/dadca20e7faa17969d3eb6ee375e2c98
//参数 n 表示点赞数和点踩数的和
const lower_bound = (upvotes, n = 0, confidence = 0.95) => {
  if (n === 0) return 0;
  // for performance purposes you might consider memoize the calcuation for z
  const z = probit(1 - (1 - confidence) / 2);
  // p̂, the fraction of upvotes
  const phat = (1.0 * upvotes) / n;
  return (
    (phat +
      (z * z) / (2 * n) -
      z * Math.sqrt((phat * (1 - phat) + (z * z) / (4 * n)) / n)) /
    (1 + (z * z) / n)
  );
};

计算一个评论的权重,我觉得字数也是一个重要依据,有些用户评论就用两三个字,其价值大概率比不上十几二十字的评论,但威尔逊置信区间没有考虑字数,所以计算评论权重不应该只用上述算法。

thumbsup0
thumbsdown0
暂无评论