【问题标题】:How do I calculate the importance/weight of input based on users reputation?如何根据用户声誉计算输入的重要性/权重?
【发布时间】:2012-12-14 17:34:04
【问题描述】:

我有几个系统,其中包含用户表以及某种形式的业力/重量/声誉。有时是用户发布的帖子数量,有时是用户在网站上的所有活动中收到的赞成/反对票数。

USER {
    id int
    name string
    karma int
}

如何使用这些数字来计算该用户的“体重”或“权威”?例如,一位老会员的投票通常比新用户的 4 票更有价值。

我正在考虑将所有成员的总积分/业力/声誉相加,然后尝试得出 1-100 的比例。

SUM(user.points) / COUNT(user.*) = average user points

然后像

CEIL(userA.points / average user points) = their weight on an issue

但是,这种方式也需要有一条曲线,因为我不希望拥有 5,000 个帖子/业力的人超过 20 个新用户的投票。

【问题讨论】:

  • 嗯...由您来定义它。 5k 用户应该超过多少新用户?一种方法是使用log(),基数由您决定。
  • 仅供参考:所以,weight= log(karma)/log(n);,其中n 是您想要摆弄的数字,可能是1 < n < 10,但更可能您想要它在1 < n < 3 之间的某个地方。

标签: mysql rdbms weighted weighted-average


【解决方案1】:

从数学上讲,最好的办法是根据相关用户的百分位排名对数进行加权。然而,这在 SQL 中是很痛苦的。

更简单的方法是欺骗并假设平均值与中位数相同(从统计上来说这是一个非常糟糕的假设,但在编程上要简单得多):

 SELECT 1 - log10(SELECT COUNT (*) FROM user 
 WHERE (SUM(user.points) / COUNT(user.*)) < user.points)  
 / SELECT (COUNT (*) from user))

通过这种方式,前 10% 的业力会产生普通用户的一倍半影响,几乎是新手的两倍。 很明显,更改日志基数会扩大规模,自然日志(mysql 中的 log())会给上层 10% 的人带来 3 倍于菜鸟的影响,以及两倍于平均水平的影响。 Log2() 更加极端。 (注意:需要减法,因为对数会是负数。)

如果您想要更严重的效果,您可以尝试对日志进行平方。 (注意:平方使对数平方为正,因此此处适合加法。)

如果你想要一个超精确的规则,你可以进入标准偏差,但是 sql 变得繁琐和缓慢。这完全取决于你想去兔子洞多远......

【讨论】:

  • 我需要一个在合理时间内完成的查询,因为在某些情况下我可能无法缓存结果。所以更快比启动要好,但需要更多的测试和研究才能找到最佳位置。
  • 我希望我所提供的会是最快的,同时防止绝对值破坏整体结果。但是,我可能会补充说,您可以在 cron 作业中设置另一个表来根据业力计算“体重”,并可能每周更新一次,然后将您的整体计算转换为简单的查询,并允许像您一样复杂的公式只要每周更新的影响力是可以接受的,并且你有空余的桌子
【解决方案2】:

可能有一些资源可以为此提供参数,但您可能应该准确地决定您想要什么,而不是使用一些预定义的模型。我建议您定义一些规则,哪些用户集应该是等效的,或者哪些应该相互超过(例如 10 0 业力用户 = 1 5k 业力用户)(等效性更容易使用),这将很快为某些用户生成参数选择方程。

使用对数(如前所述),一些(分数)幂(如平方根)甚至只是线性都可以工作。

我建议类似newKarma = a.karma^b + c,解决abc 应该不难。我建议你选择b 而不是试图计算它。使用新用户(karma = 0)应该很容易解决这个问题。猜测值以接近您想要的值可能比数学确定它们更容易(因为一些规则一起不适合任何简单的方程式)。

请注意,上面的c 是对业力的抵消,这将使许多新用户比高业力用户获得更多的总业力。您可能还想考虑a.(karma + c)^ba.(karma + c)^b + d。分析您定义的规则应该会告诉您使用哪一个。

更新:c添加了替代项

编辑:您有一些 SQL 选项。临时表(带有总和)实际上可能是最快的。您也可以只使用视图。尽管我不确定,但也可以在同一张表上进行连接。使用视图看起来像:(对于某些选择的 a、b、c 和 d)(您可能还想向视图添加索引)

Votes(issueID, userID) // table structure
User(userID, karma, ...) // table structure

CREATE VIEW Sums AS
SELECT issueID, SUM(1*POWER(karma + 2, 3) + 4) AS sumVal
FROM Votes JOIN User ON User.userID = Votes.userID
GROUP BY issueID

查询:

SELECT (1*POWER(karma + 2, 3) + 4)/sumVal AS influenceOnIssue
FROM Votes JOIN User ON User.userID = Votes.userID
  JOIN Sums on Sums.issueID = Votes.issueID
WHERE Votes.userID = @UserID AND Votes.issueID = @IssueID

简化可能是有一个计算列 = 1*POWER(karma + 2, 3) + 4

更快的选择是在插入/更新时计算派生业力,方法是增加一列并使用触发器,或者只是在调用插入/更新之前计算,然后使用新值调用插入/更新。

【讨论】:

  • 我实际上正在寻找 SQL 来执行此操作。但是,除了一些预先制作的数据库查询之外,我还希望有一个很好的逻辑概述。我会在这里考虑您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多