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