一、火星人现象
郑昀认为主要原因是:“推荐系统无法获知用户以前的知识结构”。
- 这是问题一:从根子上就无法完整反映用户的阅读经历。
- 这是问题二:如此大量的阅读视野狭窄的用户,推荐系统能否发挥作用呢?
对于问题一,解决办法我觉得只有两个。
- 尽可能多的扩展公开的数据源。比如,看我在 twitter 上推过哪些短址;看我在 delicious 上收藏了哪些链接;看我在 douban 上分享了哪些内容。GReader 的用户差不多都是网络的重度使用者,这方面可用的来源肯定不少。比如我,如果你订阅了我的 FriendFeed,那么我一天在看什么,你就差不多能知道一个大概了。
- 需要时间来积累。
这个问题,没有捷径。
对于问题二,其实之前在 kuber 做 feedzshare 的时候,我就和他讨论过。当时说了要写一篇 blog 的,后来由于我太懒就作罢了。我个人意见,GReader Share 的数据不适合做推荐,应该拿来做过滤器。这个后面展开。
二、有时效性和无时效性
大多数情况下,这个世界并不是非黑即白的。
对于时效性,我个人觉得别把它作为一个太过绝对的概念,它是和人相关的,应该作为一个相对的概念来理解。对于新近才接触某个领域的人来讲,翻翻老皇历也是有必要的。比如你看了我之前这篇的唠叨,对汪峰起了兴趣,那挖出他在鲍家街的老八卦看看也挺有意思,这些信息是新鲜的。而对于同样的内容,给我看就没什么意思了,它们out了。
因此,除了像刘未鹏所指出的“将文章分为有时效性(如新闻时政类)和无时效性(如读书笔记、GTD方法等)”这个方法,我觉得还可以从用户这个角度做一些事情。简要来讲,第一,划分用户关注的领域,这个基本是文本分类的问题,方法有不少,但大规模做起来很难,当然也并没有难到不可解决;第二,让用户方便地在时间线上游动,这个需要考虑呈现方式,给个带时间的列表是一种,高级点的像下面这个。
三、惊喜很难吗?
我的回答是:确实很难!非常之难!
对于推荐系统的制作者,如果能让用户发出像 @imrchen 这样的感慨,那将是对其工作的最高程度的肯定。
@imrchen: 太神奇了,Amazon 竟然向我推薦 Python 書籍,我從來不曾在亞馬遜買過程式設計的書籍,最近買的和技術有關的書是 Beautiful Data,和 Python 完全搭不上邊。他們怎麼知道我最近在用 Python 開發東西,這樣的推薦未免也太神了吧!?
一个好的推荐系统制作者,需要钻研数据,精修算法,勤于思考,同时最重要的,要有一颗真正愿意帮助用户解决问题的心。
GReader Share 的数据更适合做过滤器
郑昀的文章里面,把 GReader Share 数据所存在的问题已经讲得很清楚了:基于 Google
Reader 的第三方推荐系统,能够拿到的数据是严重不足的。
你无法知道用户有意忽略了哪些文章,你很难拿到他的好友列表,Google不像
FriendFeed那样提供Dislike/Hide的按钮;你只知道他何时Share或like了某篇文章从何处(值得注意的一个细节是,如果用户是
自己订阅了煎蛋并推荐其中一篇文章,显然煎蛋对用户来说更加重要;相比而言,用户只是从其他人的Shared
Items订阅中share了煎蛋的某篇文章,却不去订阅煎蛋,说明煎蛋对他来说可能还不算重要。这个细节有点像“quick
stumbles”的思路)。
1、计算 FollowRank
我曾经在 twitter 上感谢过 @imrchen,因为我发现,我好友的 Share List 里面,让我有精读冲动的,好多都是他 Share 出来的。@imrchen 的例子是我自己人肉过滤出来的,其实这个计算是可以自动化的——协同过滤里所有的 User-based 使用的相似度计算方法这里都适用。然后,根据相似度,我们取 Top50 作为我们的推荐种子,可以得到一个推荐列表。kuber 和 xlvector 应该都是这么做的,这也是最标准的 User-based 方法。
但,对于 GReader Share 数据,我建议再多考虑考虑。
这里面有个典型的例子,应该有好些人都订阅了 keso’s view,然后看到好文章就从这个列表里面进行 ReShare。对于这里面的活跃用户A,如果你用 A 的 Share List 和 keso 进行计算的话,有可能就会因为相似度很高,把 A 加入到了给 keso 进行推荐的种子用户里面。这显然是存在问题的。GReader Share 的产品设计,加重了单向 Follow 的因素,因此在种子用户的选择上,必须对传统 User-based 方法进行修正。
GReader 目前尚未提供相应的 API 获取用户的 Follow 数据,另外似乎也没有提供 Share 的时间让我们可以排排序,因此,要得到 ReShare 线路图应该是不太可能的。我这里提供一个变通的思路供讨论。
假设从用户A的 Share List 出发,查找和 A 共同 Share 了某篇文章的用户,可以得到一个候选用户集 ASet。然后设计一个公式,对隶属于 ASet 的用户B,综合考虑下面几个因素。
- BShare 包含的来源数目。
- 只有 B 单独 Share 的文章数量。
- 有 B 参与 Share 的文章,统计总 Like 数和 Share 数。
- AShare 与 BShare 交集数量 / AShare 数量。
- 第4项得分超过某阙值的周期数。
我把依此计算的结果,定义为用户A对用户B的 FollowRank。
剩下的就简单了,取 FollowRank 的 Top50 作为种子,得到候选集,阙值过滤,排排序,搞掂。
2、区分最新/最热的与我最感兴趣的
时常可以看到关注于解决信息过载问题的探讨,我个人认为,万里长征第一步,就是把用户感兴趣的摘出来,其他的按最新/最热排序。对于 GReader Share,做到此足以。
分析用户的兴趣,前面讲到了可以使用文本分类的办法。简单的还有基于 tag 的办法,不过第三方应该是无法获取 GReader 用户的 tag 数据的,此路不通;但可以绕,比如从 delicious 上提取 url 对应的 tags;然而对于中文内容,delicious 能够提供的帮助相当有限。因此,这里我建议可以考虑使用类似于内容基因的办法,说白了就是基于关键字的方法。我曾经在一些豆瓣影评数据上实验过抽取电影基因,得到的关键字组合还是挺靠谱的。我相信类似的算法用在 GReader Share 上效果应该也不会差,因为 GReader Share 数据集的文章质量应该还是比较好的。
目前在 GReader Share 数据的再利用方面,最领先的无疑是 玩聚SR,但它解决的是社会化排序的问题,是非个性化的。总体来讲,GReader 在个性化方向上能够提高的地方还有很多。像郑昀、kuber、xlvector 这样对此感兴趣的第三方开发者不妨加紧实践,没准哪天就被 Google 收编了。
有兴趣进行讨论的,移步这里。






回头再来看这篇文章,玩聚SR已经被政府放倒,唏嘘不已。