设计一个属于自己的内容热度值算法
前言
在产品、运营这次做社区改版的过程中,我们大数据部门结合具体的业务细节,通过研究、讨论与试错,最终设计了一个基本符合需求的内容热度值算法,本文就简述其设计方法。
他山之石
有为数很少的几家外国公司开源或公开说明了自家的内容热度值算法,包括Hacker News、Reddit、Stack Overflow/Stack Exchange、StumbleUpon等。我们在设计自己的算法之前,参考了他们的一些理念。为了节省篇幅,就不再重复讲一遍了,直接将reference传送门放在下面:
- https://moz.com/blog/reddit-stumbleupon-delicious-and-hacker-news-algorithms-exposed
- https://github.com/reddit-archive/reddit/blob/753b17407e9a9dca09558526805922de24133d53/r2/r2/lib/db/_sorts.pyx
- https://meta.stackexchange.com/questions/11602/what-formula-should-be-used-to-determine-hot-questions
- https://meta.stackexchange.com/questions/60756/how-do-the-arbitrary-hotness-points-work-on-the-new-stack-exchange-home-page-a
可以攻玉
列举内容数据维度
在我们的社区体系中,与一篇内容相关的指标如下:
- 时间维度:发布时间post_time、最后回复时间last_reply_time、最后操作时间last_op_time
- 互动量维度:阅读量view_num、回复量reply_num、收藏量favor_num、点赞量like_num、回复点赞量reply_like_num、分享量share_num
- 内容维度:内容长度content_length、平均回复长度reply_avg_length、图片数picture_num
-
用户维度:用户对内容的兴趣度、活跃度、发/回帖用户的声望,etc.
明确各维度的业务含义
时间维度
时间维度用来控制热度随时间的衰减,距离当下比较久远的内容应该具有更低的热度值,就像人会逐渐忘记一些之前做过的事情一样。我们认为,三种时间维度指标各自有适合的场景:
- 发布时间:(1)内容时效性强,容易过期,如新闻和资讯网站;(2)UGC远多于PGC,且用户喜欢讨论流行话题,基本不需要内容沉淀,如综合性论坛和BBS。
- 最后回复时间:(1)内容具有沉淀意义,发布很久之后也仍然可读,如专业领域论坛或博客;(2)用户回复的信息量普遍大于内容主体,如交互式问答。
- 最后操作时间:(1)UGC经常或周期性由发布者自己修改,如小说连载;(2)以PGC为主并且运营有明显的指向性(人工推荐、打星标等),如商品推广。
互动量维度
互动量是表征内容热度的最直接指标,一般采用对各项数据加权的方式来计算。
权重值的大小必然会有区别,阅读量的权重几乎总是最低的,而回复、点赞/收藏、分享量的权重值如何排序,也需要根据业务场景来具体讨论。
以新浪微博为例,它追求的是热点内容(如明星相关的内容)的高正向评价与病毒式传播,所以点赞和转发的量相对于回复量而言往往都很高。而以网易新闻为例,其中很多板块都有不少争议性内容(如体育、3C方面),目的是引起用户之间的强烈互动甚至撕逼,所以跟帖量又会远远超过喜欢和分享的数量。
内容维度
内容维度一般只起辅助作用,因为内容的质量与字数、平均回复字数、图片数等指标的关系不太能通过计算来衡量(比如很长的文章也有可能完全是篇水文),只有通过NLP或者人工筛选才能更加精准地看出来。
用户维度
在标签化推荐系统中,如果用户对带有标签的内容产生了互动,那么内容上的标签就会转化并积累为用户的兴趣向量。用户兴趣度和内容热度的综合,可以保证呈现给用户的内容不会过于大众化,也不会造成兴趣的收敛。另外,如果用户分级的体系比较完善,那么KOL、大V创作或参与互动的内容往往会获得比普通用户更高的热度值。
算法设计思路
时间维度
由于我们的定位是针对垂直领域的专业性攻略和交流社区,所以选取了最后回复时间作为时间维度。它的优点是优质内容可以随时获得较高的热度,激起用户的讨论欲望;缺点是无法应对挖坟、灌水等恶意行为,但可以通过反垃圾机制过滤掉这些异常数据。以后可以考虑发布时间与最后回复时间的结合方案。
我们采用牛顿冷却定律作为时间衰减函数,即:
H(t) = Ha · exp[-γ · (t-tlast) / 86400]
其中Ha是内容的原始热度值,即通过互动量算出的热度值。采用以e为底的指数函数,tlast即该内容的最后回复时间。时间的单位都是秒,所以要除一天中的秒数86400,以天为单位做衰减。γ是所谓“重力因子”(gravity factor),即该值越大,帖子的热度会更快地下落。
采用Wolfram Alpha画图可以展示出不同Ha与γ值的影响,我们也会根据具体业务的特点适当调整γ值。
互动量维度
我们暂时还无法从后端日志或其他数据源采集到内容分享量,但是它是一个相对低频的行为,可以日后再实现。至于内容中回复的点赞量,我们认为热评对内容整体热度的贡献有限,并且也不太好采集,暂时也搁置一边。所以互动量维度剩下了四个指标:阅读量、回复量、收藏量、点赞量,内容的原始热度值Ha计算方法如下:
Ha = ln(1+Nview) + 1.0·Nreply + 1.75·Nlike + 3.2·Nfavor
回复、收藏、点赞量都是采用线性加权的方式来做,它们的权重是根据现有内容规律大致推断的。还有一种较为科学的方式是让运营人员根据经验手动为一批较热门的内容打分,然后利用多元线性回归(multivariate linear regression)确定各个系数的值,这件事可以之后做。
阅读量的处理方式比较特殊。由于阅读是门槛最低的互动行为,因此我们倾向于认为那些第一批来阅读的用户对热度贡献值较大,而之后跟风来看的用户会越来越没有价值。自然对数能够很好地满足,如下图所示。
内容维度
内容字数和图片数可以间接地作为内容质量潜力的判断指标,但有很大的随机性。我们目前只采用了字数的常用对数值,即lg(Nlength)作为它对热度的贡献,按数量级增长的幅度很小,因此就算不准,也不会对最终结果造成什么影响。
图片数对某一部分内容而言可能非常具有代表性,可以与运营人员讨论确定一些标准。
用户维度
经过上面的介绍,我们其实已经可以得出通用的热度值计算方法:
H = [lg(Nlength) + ln(1+Nview) + 1.0·Nreply + 1.75·Nlike + 3.2·Nfavor] · exp[-γ · (t-tlast) / 86400]
而用户维度的存在,可以让我们获得更加差异化的推荐效果。
目前我们的标签化推荐系统已经运行了相当长的时间,有不少的用户兴趣积累。我们根据日志采集每位用户的近30天行为,计算其对每个标签的兴趣度,形成兴趣向量,并将它们的值归一化到[0.1,1.0]区间内,以削除最低与最高兴趣之间的巨大差距。然后,计算用户兴趣向量与内容标签向量的相似度(余弦相似度、Pearson相关性等),并将其作为总热度值的系数即可。
在实际使用时,我们还可以用随机数适当打散排序,使内容列表展示在用户面前时看起来更加丰富。即:
rand(0.75,1.25) · Cinterest · H
至于用户声望的影响,是一个更大的话题,还有待我们去探索。需要注意的是,过分强调KOL和大佬的影响力本质上是反社交的,会造成“精英主义”(elitism)的泛滥,所以一旦要上这种逻辑的话,需要严格控制。
总结
从技术人员的角度讲,一句话:技术本身是死的,但业务与人都是活的。如果技术人员对业务逻辑有深入了解的话,就会自然地去寻找更准确、高效的解决方法,双方合作起来也会更愉快。