不管LFM算法(Latent Factor Model)的效果有多么出众,现在广泛使用的算法还是经典的kNN Collaborative Filtering。
但是在单使用评分作为评判user或者item相似度的基础数据时,会遇到一个问题。就是所谓的“相似不相同”。往往这种情况很多,假设A用户喜欢射雕英雄传,B用户喜欢天龙八部,如果是在单单使用用户的评分作相似度计算时,可能会因为这两个没有共同的评分项目,而认为这两个用户不相似,其实很容易看出来,这两个用户都喜欢金庸的武侠剧,是真正意义上的相似用户。但在计算相似度的时候采用共同评分项目可能会导致这两个用户不是相似用户。同样,在item-based中也存在这样的问题。
解决这个问题,我们需要借助一些item的meta信息,将item之间的一些固有信息融入到相似度的计算当中。
这里以电影为例,每部电影都会属于一个或者多个流派,某个层面上看,属于同一个流派的电影是相似的。(当然,可以利用的信息远不止这些,还可以利用电影的导演,演员,时间等等诸多信息,而且做实验用的数据只提供流派的信息。)
所以,我们可以构造两个概念层次,然后分别计算两个层次中user或者item的相似度,然后加权合并成一个相似度,最后利用knn那一套理论做计算。
(1)第一个层次是user的所有item构成的类别。
(2)第二个层次是所有item属于的流派构成的类别。
这两个层次之间的关系是由一个类别关系矩阵联系起来的。类别关系矩阵是个Boolean矩阵,代表的意义是,如果第一个层次的类别属于第二个层次的类别,那么就记作1,否则就记作0.如:第一个层次是由各个电影构成,第二个层次由各个流派构成,如果电影A属于流派a的话,就记作1,否则记作0.
接下来就是计算各个层次的相似度。
(1)第一层次,即用户对各个电影的原始评分矩阵,计算相似度可以用余弦函数,皮尔逊相关法,修正的余弦函数等等那几种传统的方法。
(2)第二层次,即用户对各个流派的评分矩阵,这个评分需要将用户对每个电影的评分矩阵和类别关系矩阵做乘积得到,得到的乘积矩阵需要进一步处理得到用户对各个流派的评分矩阵。具体如下面的公式所示:
这样我们可以得到用户对各个流派的打分,也就是可以计算第二层的用户相似度。用到的方法同样是那些常用的相似度计算的方法。
得到两个层次的相似度以后,接下来需要把这两个层次的相似度以一定的权重合并起来得到最终的相似度矩阵。
然后按照常规的kNN的算法进行TopN个最近邻的选择,然后预测。
这里我还是用了movielens的100k数据包做了实验,得到了比较好的结果,结果如下(这个是其中一组结果,其他结果与之类似):
参数 | RMSE |
(传统的Knn)k=100 | 0.9484460 |
alpha=0.9 | 0.9590775 |
alpha=0.85 | 0.946740 |
alpha=0.83 | 0.946688 |
alpha=0.80 | 0.946762 |
alpha=0.79 | 0.946922 |
alpha=0.7 | 0.947776 |
几点说明:
- alpha表示第一个层次相似度的权值,1-alpha表示第二个层次相似度的权值。
- 因为在计算两层相似度中,对计算方法可以有多种组合选择。上面的结果是各种方法组合后最好的结果,最优的组合方法是两层相似度计算都采用余弦函数法。
- 打红的地方表示,多层次相似度计算的结果会优于传统的相似度计算,但并不是总会优于传统的。当alpha比较接近于1的时候,结果会比传统的要差,当然alpha=1的时候就是传统的单层相似度了。这个alpha参数很重要,它决定了系统对相似的item的评分的转化能力和认知能力,过大过小都不好。
- 当我们拿到用户在第二层的评分,也就是对各个流派的评分后,大部分的值是小数,这个时候对这些值进行四舍五入效果会好一些。(int(r[i][j]+0.5))
- 这个结果的可以看出多层次的相似度计算方法会好于传统的单层次的计算方法,但效果体现的并不那么明显。当然这个结果只是实验上的结果,对于实际的系统,我们考虑的因素会更多,不会仅仅拘泥于电影的流派。我想在实际的系统中,考虑的因素更多了以后,推荐的效果会更好。
- 这个方法中间会计算出用户对流派的评分矩阵,这个矩阵加以拓展的话可以得到用户的兴趣模型,即一个用户可以表示成为几个关键词(tag,这里是流派)的加权和。这样可以解决item的冷启动问题,当一个新的movie进入系统之后,这个movie可以由几个tag来概括,通过tag来寻找和它相似的movie或者相似的user,从而做出推荐;当然某种程度上可以解决user的冷启动问题,假如在用户注册的时候添加了自己喜欢的tag信息,那么当这个新用户刚刚进入系统的时候,系统就可以推荐给他喜欢的movie。
- 关于聚类。其实这里的流派可以看作是一种有先验知识的分类,而且是一种软分类,一部电影属于某个流派分类或者某几个流派分类。那么当我们做拿到一堆原始数据的时候,我们可能并没有一个比较好的先验知识来做分类,这个时候只能做聚类。说道聚类,我就想提LFM的方法,因为矩阵分解其实就是一种软聚类,每个factor的值代表在这种聚类中占到的权值。所以我在想可不可以把MF和多层次的相似度计算方法结合在一起做,将MF的聚类结果当作一个层次,将movie的meta信息作为一个层次,将原始的movie作为一个层次,然后用多层次的相似度方法来作计算。(这个有待进一步思考和验证)