代码改变世界

新闻推荐系统:基于内容的推荐算法(Recommender System:Content-based Recommendation)

2018-07-07 14:32  bluemapleman  阅读(5626)  评论(0编辑  收藏  举报

因为开发了一个新闻推荐系统的模块,在推荐算法这一块涉及到了基于内容的推荐算法(Content-Based Recommendation),于是借此机会,基于自己看了网上各种资料后对该分类方法的理解,用尽量清晰明了的语言,结合算法和自己开发推荐模块本身,记录下这些过程,供自己回顾,也供大家参考~

目录

一、基于内容的推荐算法 + TFIDF

二、在推荐系统中的具体实现技巧

正文

一、基于内容的推荐算法 + TFIDF

主流推荐算法大致可分为:

  • 基于内容(相似度)的推荐

  • 基于用户/物品相似度的协同过滤

  • 热点新闻推荐(你看到的那些头条新闻)

  • 基于模型的推荐(通过输入一些用户特征进入模型,产生推荐结果)

  • 混合推荐(以上十八般兵器一起耍!)

(本文只详述基于内容的推荐,其它的推荐方法大家可以另行搜索。)

概念

基于内容相似度的推荐:顾名思义,把与你喜欢看的新闻内容相似新闻推荐给你。基于内容的推荐算法的主要优势在于无冷启动问题,只要用户产生了初始的历史数据,就可以开始进行推荐的计算。而且随着用户的浏览记录数据的增加,这种推荐一般也会越来越准确。

这里有两个重要的关键点需要首先有个基本理解:

  1. 怎么知道用户喜欢看那些新闻;

用户有历史的浏览记录,我们可以从这些用户历史浏览的新闻中”提取”能代表新闻主要内容的关键词,看哪些关键词出现的最多。比如可以有”手机“,”电脑游戏“,”发布会“等等关键词。

或者,统计这些新闻所属的领域是哪些,比如国际政治、社会、民生、娱乐,找出用户看的新闻来源最多的几个领域。不过按这种方式判断用户兴趣容易太宽泛,哪怕是同一个领域下的新闻,可能也会差异很大。比如某用户可能喜欢A女星,而不喜欢B女星,而如果你只是认为该用户喜欢娱乐新闻,结果把B女星的新闻不停给用户推,那就肯定不好。而上述的关键词就可以比较好地规避这个问题。

  1. 怎么判断两个新闻内容相似;

找到定义用户喜好的方法——关键词,那么我们自然而然就可以想到,能不能提取出两个新闻的关键词,然后对比看它们两的关键词是不是相同的呢?恩!思路正确,不过毕竟一个新闻可以有好几个关键词,要想全部一样,还是比较困难的。所以我们需要对两个新闻的关键词匹配程度做一个合理的量化。

那么这时就要说到TFIDF算法了。

给大家一个链接去看TFIDF算法的具体原理,而此处只是简单地解释:TFIDF算法可以能够返回给我们一组属于某篇文本的”关键词-TFIDF值”的词数对,这些关键词最好地代表了这篇文本的核心内容,而这些关键词的相对于本篇文章的关键程度由它的TFIDF值量化。

好了,那我们现在也有了提取关键词并量化关键程度的方法,那么我们现在就可以来对比两篇文本的相似程度了。公式如下:
$$Similarity(A,B)= \Sigma_{i\in m}TFIDF_A*TFIDF_B$$
m是两篇文章重合关键词的集合。此即将两篇文本的共同关键词的TFIDF的积全部加在一起,获得最终代表两篇文本的相似度的值。

	  举例:
		  刚抓进系统的两个新闻,分别提取出关键词与TFIDF值如下:
		  A新闻:“美女模特”:100,“女装”:80,“奔驰”:40
		  B新闻:“程序员”:100,“女装”:90,“编程”:30
		  两篇文章只有一个共同关键词“女装”,故相似度为:80*90=7200。

用户喜好衡量:喜好关键词表

但是实际操作中,以上思路有一个问题了,用户以前看了辣么多新闻,每个新闻有好些个关键词,我们难道拿刚抓进系统的新闻跟它们一个个比对吗?

为了解决这个问题,我们需要引入新的东西:喜好关键词表

其实很好理解:我们为每个用户在数据库里维持一个map,这个map里放的都是“用户喜好的关键词-喜好程度”这样的Key-Value对。而这个map最开始当然是空的,而从任意时刻开始,我们可以开始跟踪某用户的浏览行为,每当该用户新浏览了一条新闻,我们就把该新闻的“关键词-TFIDF值”“插入”到该用户的喜好关键词表中。当然这个“插入”要考虑关键词表里已经预先有了某预插入的关键词的情况,那么在这个基础上,我们可以将预插入的关键词的TFIDF值直接和词表里的值加起来。

当然,考虑到存储问题,我们可以为用户的喜好关键词表设定一个容量上限,比如最多1000个词,当然具体数值还是需要在实际运行过程根据效果做调整。

兴趣迁移——衰减机制

最后一个问题。

我们大家会不会想到,我们的兴趣点可能是会随时间改变的呢?比如这段时间苹果出了一款新产品,我关注一下,但一个月后,我可能就完全不在意这件事了,但是可能苹果相关的关键词还一直在我的关键词表里,那会不会导致我依然收到相似的我已经不关心的新闻的推荐呢?也就是如何处理这种兴趣迁移问题呢?

为了解决这个问题,我们可以引入一个衰减机制,即让用户的关键词表中的每个关键词喜好程度都按一定周期保持衰减。考虑到不同词的TFIDF值可能差异已经在不同的数量级,我们考虑用指数衰减的形式来相对进行公平的衰减。即引入一个$\lambda$系数,$1>\lambda>0$,我们每隔一段时间,对所有用户的所有关键词喜好程度进行*$\lambda$的衰减,那么就完成了模拟用户兴趣迁移的过程。

当然,一直衰减下去,也会使得一些本来就已经完全不感兴趣的关键词可能衰减到了0.0000001了,还在衰减,还死皮赖脸地待在词表里占位置,那么自然而然,我们可以设置一个阈值L,规定对每个用户的每次衰减更新完成后,将词表里喜好值小于L的关键词直接清除。

在推荐系统中的具体实现技巧

自己实现的推荐系统,包括了协同过滤、基于内容的推荐和基于热点新闻的推荐,放在Github上了,欢迎拍砖!

这里TFIDF值的提取我用的是ANSJ,有直接的TFIDF库函数,直接调用就行,都不用自己分词。

而在数据库里存储与读取用户的关键词表时,我用的是Json形式,相关的工具有fastjson和Jackson,大家选择自己喜欢的用都可以。

另外,推荐过程是用Quartz定时任务库定制在每天0点开始执行,包括像衰减机制,各个推荐算法生成各自的推荐结果,都是这个时候完成的。所以这个推荐并不是实时的,当然做成实时的完全也没问题,只要服务器性能够好。

后话

这里只是提出自己的一个实现思路,思路的形成过程也是在看了许多推荐系统相关的学术文献并进行了自己的总结与改变,并非权威的做法,欢迎各位提出修正意见。

听说几年前开始,ACM有一个每年举办的推荐系统学术会议叫RecSys,有兴趣的小伙伴们也可以关注一下。

有问题欢迎私信我!