基于统计与评分

推荐系统

推荐系统是一种信息过滤系统,用于预测用户对物品的“评分”或“偏好”。

对于推荐系统系统来说,目前采用的主要方式是:

  • 基于内容推荐:内容之间的相似度,如文章的标签、电影的属性、书籍的分类。
  • 协同过滤(待实现):用户之间的相似度,如喜欢看科幻片的 A、B 用户、并且都看过 a 电影,A 喜欢看的 c 电影,B 也可能喜欢 c 电影。

要实现这两种方式有一个前提是,用户数据。特别是协同过滤,需要有大量的用户行为数据。对于一些大的社交应用、有大量的用户,如微信来说,还会有:

  • 基于社区推荐,如,你的好友喜欢什么,就会为你推荐王者荣耀。
  • 基于人口统计学,即我们网上看到的各种区域性人的偏好,各种地域黑~。

上面主要是依赖于大量的用户数量,当我们没有大量的用户数据时。我们可以先采用其它的方式:

  • 基于统计学推荐,诸如文章的阅读量、分享量,又或者文章的评分数。
  • 基于标签推荐,对于专业领域的文章来说,作者提交的标签往往比机器生成更加可靠。

除此,按我的理解,对于专业领域来说,还会有一种方式是:

  • 基于知识图谱推荐,如我之前做的技能树和 Growth,便是其中的一种方式。

这种成知识体系的文章,往往对于用户来说,更具备价值。

收集用户数据(一):统计

那么,现在先让我们从收集用户数据谈起。

因为不论是哪一种推荐方式,其都依赖于应用服务提供者所拥有的数据数据数据。没有数据,你所谈的算法都是在耍流氓,你所学的机器学习、深度学习算法也是在而流氓,只谈算法不谈收集数据都是在耍流氓。他们的学习成本都很低,几星期几个月,差不多能学好七八十。可是要是没有 ImageNet 的图片数据、CNN 的上亿条新闻数据,这一些算法都没有价值。

而如我在《全栈应用开发:精益实践》所写,数据分析应该在我们上线了第一个 DEMO 之后,或第一个正式版就必须上线的功能,以实现产品的精益化。

精益环路

它只是数据分析的第一步,引入一些数据分析的工具——只需要引入 Google Analytics、又或者 Piwik 这样的工具,就可以轻松地帮我们做数据统计。这些功夫,基本上只需要半天就做完了。这时,当我们谈及收集用户数据的时候:

  • 对于技术人员来说,无非就是用户的地域、浏览器、操作系统等等,这些相关的信息会影响到用户的体验、技术决策等等。
  • 对于业务人员来说,他们可以了解某个产品的浏览量、受欢迎程度、爱欢迎的区域等等。

只是这些数据,并不能帮我们做出一个优秀的推荐系统。这时,我们是基于统计学,只能统计出哪些产品受用户欢迎:

事件追踪

但是,这已经可以实现我们的第一个推荐系统。

(PS:另外一部分用户数据收集,见下文)

基于统计学:访问量及评论数推荐

我过去一直觉得,依据统计博客、文章的访问量来推荐是不可靠的。

  • 一篇文章可能因为观点受争议,如 『PHP 不再是最好的语言』,而着有极高的访问量。可这个时候,用户往往是通过标题和摘要来理解作者的观点,往往就会轻易地下定论。又有一些用户,比如我则喜欢看热闹,去下面回复一个『JavaScript 是最流行的语言』。
  • 一篇文章可能因为大 V 的流量效应,而导致 他/她/也 的每一篇文章都有极高的访问量
  • 。。。

并且使用流量统计也容易被攻击,只需要一些诸如『流量精灵』这样的软件,就可以提高文章的访问——虚假的繁荣。

一般来说,大部分的社区都会将流量大的内容、话题等,放在首页显眼的位置。从这个推荐的位置,我们就可以知道这个社区的『水平』。衡量一个社区的『水平』,无非就是最受欢迎文章的类型,如简书的鸡汤,知乎的故事。但是,这些并不代表着这些社区的真实水平,却反应了这些社区的主要受众。

简书示例

好在简书是编辑推荐制,但章的质量还是『有一定』保证的,但是文章的性质改不了鸡汤。

考虑到我过去曾经刷过访问量,以及流量统计对于数据库性能的影响,我决定改进一下统计代码,即将统计代码放在 JavaScript 中,通过 Ajax 请求实现。而我在这个过程中,犯了一个严重的错误就是,忘了在前端屏蔽中的爬虫。我虽然在 Nginx 里,直接过滤了一部分的爬虫,但是诸如 Google、百度、Bing 都是允许的,而 Google bot 则会在页面上执行 JavaScript,因此每篇博客都被刷了好多阅读量。

Google 爬虫数据

于是,只好在前端做一些相关的处理。

var botPattern = "(googlebot\/|Googlebot-Mobile|Googlebot-Image|Google favicon|Mediapartners-Google|bingbot...";
var botRe = new RegExp(botPattern, 'i');
var userAgent = navigator.userAgent;
if (!botRe.test(userAgent)) {

}

而除了,上面说到的鸡汤问题。它也有一些额外的好处,如:

  • 长尾效应。这种高流量的文章、商品,往往能带来长尾效应,就像亚马逊上的畅销书,畅销书本身是不赚钱的。但是网站可以通过相关的文章、产品,来获得更多的阅读及利润。而这取决于,我们为用户推荐的相关产品,是不是真正是用户需要的

考虑到上面的鸡汤流量问题,它可以吸引大量的人气,但是会导致劣币驱除良币的产生——大量产生优秀内容的作者,写不出受大众欢迎的文章。举个例子,技术写作来说,面向新手的文章,往往会有比较高的阅读量;而面向中高端用户的文章,则阅读量低。可要是首页都是新手文章,流量和受众就会越来越多,但是高端用户就会离开这个社区。

因此,我们还可以采用用户评分,来增加一个新的榜单,如 Medium 和 『玩点什么』的第二种推荐方式。

玩点什么首页推荐

它可以在保证流量的同时,也不降低网站的质量。

基于统计学:评分及 IMDB 加权算法推荐

软件开发,本身是以演进的形式进行的。不论,我们是开发基于内容的推荐系统,还是协同过滤的系统,它都依赖于我们拥有一个评分系统。与此同时,如果我们没有足够的用户,我们也进行不了内容推荐和协同过滤,因此设计一个稍微完善一点的评价排名,便显得很有必要。

下图是『玩点什么』的评分,用户不需要登录就可以评分:

玩点什么评分示例

尽管没有登录是一个风险问题,然而对于一个内容网站来说,刷评价的意义并不大。

在真实应用的过程中,遇到了一个问题:

  • A 文章只有 5 个评分,且都是 5 分;
  • B 文章则有 100 个评分,平均值则是 4.8 分;

如下表示:

idxxkeywordsvotesrating_sumrating_averagepublishedtitle
"323 ""0 ""tech tools ""45 ""165 ""3.66666666666667 ""1 ""每个程序员必知之:程序员差别的本质"
"63 ""0 ""programmer resume latex ""24 ""66 ""2.75 ""1 ""程序员该如何去写自己的简历(草稿)"
"207 ""0 ""beageek geek anywherehtml ""20 ""79 ""3.95 ""1 ""be a geek 1:无处不在的html"
"38 ""0 ""iot osiot laravel ajax RESTful ""19 ""84 ""4.42105263157895 ""1 ""一个最小的物联网系统设计方案及源码"
"361 ""0 ""write type writer programmer ""17 ""65 ""3.82352941176471 ""1 ""编程同写作,写代码只是在码字"
"259 ""0 ""gitbook ""12 ""51 ""4.25 ""1 ""gitbook 制作书籍"
"37 ""0 ""iot ajax laravel RESTful serial ""11 ""40 ""3.63636363636364 ""1 ""最小物联网系统(一)——系统组成"
"391 ""0 ""javascript anonymous encapsulation ""11 ""50 ""4.54545454545455 ""1 ""Javascript 匿名函数与封装"
"512 ""0 "" ""9 ""36 ""4.0 ""1 ""如何通过github提升自己"
"508 ""0 ""emacs vim github ""8 ""40 ""5.0 ""1 ""努力只是因为想去做想做的事"
"548 ""0 ""full stack mustache django rework ""8 ""35 ""4.375 ""1 ""全栈工程师的思考"

这个时候,我们很难判定 A 就比 B 好,于是在知乎上看到了一个相关的评分算法,即(更多信息可以阅读:IMDB 给出的电影评分的计算方法是怎样的?),又可以称为 IMDB TOP 250 评分算法。

它是由贝叶斯统计的算法得出的加权分(Weighted Rank-WR),其公式如下:

(WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
  • WR, 加权得分(weighted rating)。
  • R, 该电影的用户投票的平均得分(Rating)。
  • v, 该电影的投票人数(votes)。
  • m, 排名前 250 名的电影的最低投票数(现在为 3000)。
  • C, 所有电影的平均得分(现在为6.9)。

于是,我的算法代码就变成了这样:

def imdb_rank(average_rating, votes_number):
    minimum_votes = settings.MINIMUM_VOTES
    correctly_votes_rate = settings.CORRECTLY_VOTES_RATE

    return (votes_number / (votes_number + minimum_votes)) * average_rating + (minimum_votes / (
    votes_number + minimum_votes)) * correctly_votes_rate

然而,在计算排序的时候,我不是拿所有的文章排序,而是:

  1. 从所有文章中过滤出能达到最小评分数的文章
  2. 按评分值,对这些文章进行排序,取前 10
  3. 对前 10 中的这些文章,进行 imdb_rank 计算,取前 3

这样做的主要原因是,出于服务器性能考虑。

待改进

可是我给一个文章五分,并不代表我真的喜欢这篇文章。正如,我在某宝上不敢给差评一样,万一被骚扰了呢。但是我喜欢一个东西,我会给一个评论。因此,我会开心地留个言,又或者是在留言给个差评:卖家真好,卖了个手机壳,送了个手机

因此,目前行业内有一些做法是,评分 + 评论分析,从评论中分析出用户的真实想法。

https://www.phodal.com/blog/how-to-design-a-recommend-system-part-1-statistics-rating-up/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值