基于协同过滤的推荐方法

标签: 数据挖掘 CF Mahout | 发表时间:2015-12-26 18:17 | 作者:Yanjun
出处:http://shiyanjun.cn

协同过滤(Collaborative Filtering, CF)是推荐系统广泛使用的一种技术,它主要通过考虑用户(User)与用户之间、物品(Item)与物品之间的相似度(Similarity),来向用户推荐物品,常被用在电商网站中。其中,在推荐系统中最常使用的协同过滤方法,有如下4种:

  • 基于用户的协同过滤推荐
  • 基于物品的协同过滤推荐
  • 基于模型的协同过滤推荐
  • 混合协同过滤推荐

上面4种方法中,基于用户的协同过滤推荐、基于物品的协同过滤推荐都是基于内存的协同过滤推荐,一般在数据量较小的应用场景下,可以直接在线使用的实时推荐方法;基于模型的协同过滤推荐一般用于离线计算,它采用机器学习的方法,一般首相将用户偏好行为数据分成2个数据集(有时可能会将数据集分成k个子集,采用交叉验证的方式来提高模型精度),一个为训练集,一个为测试集,使用训练集数据来训练出推荐模型,然后使用测试集数据来评估模型的精度,当满足特定精度时,可以将得到的推荐模型应用于实际线上环境;混合协同过滤推荐,是综合基于内存的协同过滤(基于用户的协同过滤推荐、基于物品的协同过滤推荐)、基于模型的协同过滤推荐这两类方法,克服每一种协同过滤方法本身的缺点,比如基于内存的协同过滤推荐方法不适用于大量数据的推荐应用场景,而基于模型的协同过滤推荐方法由于所基于的数据多是大量历史记录,训练模型时间较长,它不适用于在线推荐场景,综合各种协同过滤推荐方法,取长补短,这样的推荐方法更适合实际复杂的推荐需求。

对象相似性度量

在介绍4种协同过滤推荐方法之前,我们先介绍一下有关相似性度量的问题:
基于协同过滤推荐方法,通过计算用户相似度、物品相似度来进行个性化推荐,那么我们结合Mahout机器学习库来说明各种相似性度量的计算方法,Mahout提供了分别针对用户、物品给出了一些相似性度量计算实现,有些是用户、物品可以共同使用的,如下类图所示:
mahout-similarities
上图中,绿色表示计算用户之间相似度、物品之间相似度都可以使用的相似性度量,而SpearmanCorrelationSimilarity只能用于计算用户的相似度。各种相似度说明如下所示:

  • EuclideanDistanceSimilarity

欧几里德距离,又称欧氏距离,在n维欧式空间中,计算欧几里德距离的公式,如下所示:
euclidean-distance
其中,x、y表示两个点的坐标,d(x,y)表示点x和y之间的距离。

  • PearsonCorrelationSimilarity

对于两个数据集X、Y,他们的相关性可以使用皮尔逊相关系数来表达,计算皮尔逊相关系数的公式,如下所示:
pearson_correlation_coefficient
其中,n分别表示两个数据集X与Y中数据点的个数,xi表示数据集X中第i个数据点,yi表示数据集Y中第i个数据点。

  • UncenteredCosineSimilarity

余弦相似度通过计算两个向量的夹角的余弦值,来表示两个向量的相似性,它的计算公式,如下所示:
cosine_similarity
其中,A和B表示两个向量。

  • LogLikelihoodSimilarity

Mahout采用了log-likelihood ratio(LLR)的方法计算相似度,对于事件A和事件B,我们考虑两个事件发生的次数,具有如下事件矩阵:

Event A Everything but A
Event B k11 k12
Everything but B k21 k22

其中:
k11:事件A与事件B同时发生的次数
k12:B事件发生,A事件未发生
k21:A事件发生,B事件未发生
k22:事件A和事件B都未发生
那么,计算LLR的公式如下:
likelihood_radio
其中,H表示香农熵。
在Mahout中给出的实现,如下代码所示:

  public static double logLikelihoodRatio(long k11, long k12, long k21, long k22) {
    Preconditions.checkArgument(k11 >= 0 && k12 >= 0 && k21 >= 0 && k22 >= 0);
    // note that we have counts here, not probabilities, and that the entropy is not normalized.
    double rowEntropy = entropy(k11 + k12, k21 + k22);
    double columnEntropy = entropy(k11 + k21, k12 + k22);
    double matrixEntropy = entropy(k11, k12, k21, k22);
    if (rowEntropy + columnEntropy < matrixEntropy) {
      // round off error
      return 0.0;
    }
    return 2.0 * (rowEntropy + columnEntropy - matrixEntropy);
  }

具体可以查阅相关资料。

  • TanimotoCoefficientSimilarity

Tanimoto相关系数来源于Jaccard距离,它表示两个数据集的相异度,即不相似度量。
计算Tanimoto相关系数的公式,如下所示:
tanimoto_distance
其中,A和B表示两个向量。

  • CityBlockSimilarity

曼哈顿距离有很多种叫法:城市街区距离、L1距离、L1范数、曼哈顿长度、Taxicab距离(出租车距离)。计算曼哈顿距离的公式,如下所示:
manhattan-distance
其中,x和y表示两个n维向量。

  • SpearmanCorrelationSimilarity

Spearman相关系数的计算公式,如下所示:
spearman_rank_correlation_coefficient
其中,di=xi-yi,n表示数据集的大小,xi与yi分别是数据集X、Y中的数据点。

下面,我们会对上面提到的4种协同过滤方法进行详细说明,其中会结合Apache Mahout,并给出相应的实现代码,以求能够更好地理解各种协同过滤方法。

基于用户的协同过滤推荐

基于用户的协同过滤推荐,不考虑用户、物品的属性(特征)信息,它主要是根据用户对物品的偏好(Preference)信息,发掘不同用户之间口味(Taste)的相似性,使用这种用户相似性来进行个性化推荐。基于用户的协同过滤推荐,它是以用户为中心,观察与该用户兴趣相似的一个用户的群体,将这个兴趣相似的用户群体所感兴趣的其他物品,推荐给该用户。下面我们通过一个例子来说明,如下图所示:
user_cf
如上图,已用户U1为中心,用户U1对物品I12、I13、I14有偏好行为,用户U3对物品I12、I13、I14、I31、I32、I33有偏好行为,而物品I12、I13、I14是用户U1和用户U3共同有偏好行为的物品,那么可以将用户U3有偏好行为但是用户U1没有的物品I31、I32、I33推荐给用户U1。
下面通过使用Mahout机器学习库实现,基于用户的协同过滤推荐,来了解计算用户相似度的方法,代码如下所示:

        final DataModel model = new FileDataModel(new File("src/main/resources/u.data"));
        UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
        int n = 20;
        UserNeighborhood neighborhood = new NearestNUserNeighborhood(n, similarity, model);

        final UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);
        long userID = 200;
        int topN = 10;
        List<RecommendedItem> recommendations = recommender.recommend(userID, topN);
        for (RecommendedItem recommendation : recommendations) {
            System.out.println(recommendation.getItemID() + ": " + recommendation.getValue());
        }

对于编号为200的用户,使用皮尔逊相关系数(PearsonCorrelationSimilarity )和NearestNUserNeighborhood计算用户相似度,得到的Top 10推荐物品及其评分列表,如下所示:

316: 5.0
895: 4.6441307
100: 4.6418004
315: 4.564026
896: 4.5467043
285: 4.5023627
344: 4.475635
346: 4.4689593
272: 4.4235177
750: 4.297509

基于用户的协同过滤推荐,比较适合于用户数量少于物品数量的应用,这样,通过更多的用户对物品的偏好行为历史数据,维护用户的相似关系,能够更好地计算出用户的相似性。

基于物品的协同过滤推荐

基于物品的协同过滤推荐,也不考虑用户、物品的属性(特征)信息,它也是根据用户对物品的偏好(Preference)信息,发掘不同物品之间的相似性。基于物品的协同过滤推荐,是以物品为中心,通过观察用户对物品的偏好行为,将相似的物品计算出来,可以认为这些相似的物品属于特定的一组类别,然后根据某个用户的历史兴趣计算其所属的类别,然后看该类别是否属于这些成组类别中的一个,最后将属于成组类别所对应的物品推荐给该用户。下面我们也通过一个例子来说明,如下图所示:
item_cf
上图中,用户U1对物品I5和I6有偏好行为,用户U3对物品I1和I6有偏好行为,那么我们可以向U1推荐用户U3所感兴趣的物品I1。同样,用户U7对物品I3、I4、I7有偏好行为,用户U9对物品I4、I5、I7有偏好行为,那么我们可以向用户U7推荐用户U9所感兴趣的物品I5,因为用户U7和用户U9都对I4、I7有过偏好行为;可以向用户U9推荐用户U7感兴趣的物品I3,这个2个用户可能对彼此其他感兴趣的物品也都会发生偏好行为。
基于用户的协同过滤推荐,使用Mahout机器学习库计算,来了解计算物品相似度的方法,代码如下所示:

        final DataModel model = new FileDataModel(new File("src/main/resources/u.data"));
        ItemSimilarity similarity = new LogLikelihoodSimilarity(model);

        final ItemBasedRecommender recommender = new GenericItemBasedRecommender(model, similarity);
        long userID = 200;
        int topN = 10;
        List<RecommendedItem> recommendations = recommender.recommend(userID, topN);
        for (RecommendedItem recommendation : recommendations) {
            System.out.println(recommendation.getItemID() + ": " + recommendation.getValue());
        }

对于编号为200的用户,使用对数似然(PearsonCorrelationSimilarity )计算物品相似度,得到的Top 10推荐物品及其评分列表,如下所示:

1431: 4.6409993
1156: 4.494837
1127: 4.4886928
1234: 4.481482
1294: 4.442889
1122: 4.442692
1654: 4.419746
1593: 4.419684
1595: 4.392633
1596: 4.392633

基于物品的协同过滤推荐,比较适合于物品远远少于用户的应用,这样可以更好地维护物品之间的相似关系。

基于模型的协同过滤推荐

基于模型的协同过滤推荐,是采用机器学习的方法,通过离线计算实现推荐的,通常它会首先根据历史数据,将数据集分成训练集和测试集两个数据集,使用训练集进行训练生成推荐模型,然后将推荐模型应用到测试集上,评估模型的优劣,如果模型到达实际所需要的精度,最后可以使用训练得到的推荐模型进行推荐(预测)。可见,这种方法使用离线的历史数据,进行模型训练和评估,需要耗费较长的时间,依赖于实际的数据集规模、机器学习算法计算复杂度。有关推荐模型的计算方法,通过机器学习算法实现,我们简单说明一下。
对于我们的用户历史行为数据,我们关注的是用户与物品之间的关系,可以生成一个用户-物品矩阵,矩阵元素表示用户对物品的偏好行为(或者是评分),如果用户和物品的数量都很大,那么可见这是一个超大稀疏矩阵,因为并不是每用户都对所有的物品感兴趣,只有每个用户感兴趣的物品才会有存在对应的偏好值,没有感兴趣的都为空缺值,最终我们是要从这些空缺值对应的物品中选择出一些用户可能会感兴趣的,推荐给用户,这样才能实现个性化推荐。
下面,我们假设使用用户-物品的评分矩阵来实现推荐,定义评分矩阵为R,那么通过将R分解为另外两个低秩矩阵U和M,由于R是稀疏矩阵,很多位置没有值,只能通过计算使用U与M的乘积近似矩阵R,那么只要最终得到的误差尽量小,能满足实际需要即可,一般使用均方根误差(Root mean square error,RMSE)来衡量,那么就要计算一个目标函数的最小值,如下函数公式所示:
als
如果计算该目标函数的最小值,可能需要大量的迭代计算,甚至是不可行的,在满足实际需要精度的前提下,那么我们可以允许一定的误差,通过设定多个参数来控制计算。计算矩阵分解有很多方法,如:随机梯度下降(Stochastic gradient descent,SGD)、交替最小二乘法(Alternating Least Squares,ALS)、加权交替最小二乘法(ALS with Weighted-λ-Regularization,ALS-WR),有关实际计算的理论,可以参考相关资料。
Mahout采用了ALS-WR方法实现矩阵分解,目标函数如下公式所示:
als-wr
其中:
als-wr-alpha
这里,alpha表示的是置信参数,在Mahout中使用隐式反馈(Implicit Feedback )选项时,需要指定该参数;lambda表示的是正则化参数,为了防止求解得到的模型过拟合(Overfitting),在目标函数上,加上一个正则项。
我们可以通过它提供的API来实现一个离线的基于模型的协同过滤推荐,下面我们基于MovieLens数据集,介绍具体使用过程:

  • 准备训练集和测试集

我们选择使用MovieLens数据集,2亿的评分数据(大约有500多MB),首先将数据集进行分割:80%用作训练集,20%用作测试集,Mahout提供分割数据集的工具,分割执行如下命令:

bin/mahout splitDataset -i /test/shiyj/data/ml-20m/ratings.csv -o /test/shiyj/data/splitDS -t 0.8 -p 0.2 --tempDir /tmp/mahout/

这样,生成2个数据集:/test/shiyj/data/splitDS/probeSet和/test/shiyj/data/splitDS/trainingSet。

  • 训练推荐模型

使用训练集/test/shiyj/data/splitDS/trainingSet来训练推荐模型,执行如下命令:

bin/mahout parallelALS -i /test/shiyj/data/splitDS/trainingSet -o /test/shiyj/data/output/als --lambda 0.1 --implicitFeedback true --alpha 0.065 --numFeatures 10 --numIterations 10 --numThreadsPerSolver 2 --tempDir /tmp/mahout

上面命令执行结果,数据会在/test/shiyj/data/output/als/目录下面,可以看到生成如下目录:

/test/shiyj/data/output/als/U
/test/shiyj/data/output/als/M
/test/shiyj/data/output/als/userRatings

这些目录下的文件就是推荐模型对应的数据文件,可以用于后面步骤中的评估和最终推荐。

  • 评估模型

评估模型使用Mahout的evaluateFactorization命令,需要输入上一步生成的模型文件,如下所示:

bin/mahout evaluateFactorization -i /test/shiyj/data/splitDS/probeSet -o /test/shiyj/data/output/als/rmse --userFeatures /test/shiyj/data/output/als/U --itemFeatures /test/shiyj/data/output/als/M --tempDir /tmp/mahout/rmse

可以看到,最后输出了RMSE,在文件/test/shiyj/data/output/als/rmse/rmse.txt中。

  • 推荐

如果我们训练得到的模型在评估以后,误差能够满足实际推荐业务需要,则可以直接用于实际的推荐系统。Mahout提供了一个基于命令行的推荐方式,可以使用recommendfactorized命令,如下所示:
bin/mahout recommendfactorized -i /test/shiyj/data/output/als/userRatings -o /test/shiyj/data/output/als/recommendations –userFeatures /test/shiyj/data/output/als/U –itemFeatures /test/shiyj/data/output/als/M –numRecommendations 10 –maxRating 5
上面指定了,为每个用户选择Top 10个物品作为推荐,并计算出了评分,执行上述命令,得到推荐结果,在目录/test/shiyj/data/output/als/recommendations中,该目录下的文件内容,示例如下所示:

1    [2571:0.65515196,1214:0.63967377,1210:0.5870833,1206:0.58017606,750:0.53064054,1270:0.52714694,1527:0.492824,5952:0.4770518,480:0.4517607,1580:0.43877804]
2    [1196:0.22062394,1210:0.21882197,1198:0.19199324,1240:0.1805339,2571:0.17224884,1200:0.16999668,1291:0.15613373,858:0.14950913,1097:0.14854312,1197:0.1480078]
3    [1196:0.8909414,1214:0.8081364,1270:0.6871423,924:0.64723164,858:0.6388401,1136:0.6263018,1291:0.58192265,1036:0.56856805,750:0.55387926,296:0.5497311]
4    [457:0.34563774,592:0.3424035,150:0.32874095,590:0.32829174,349:0.3071443,153:0.29904938,316:0.29723072,110:0.28530872,344:0.28501293,434:0.27692935]
5    [1:0.64543045,356:0.55862373,733:0.48568383,32:0.48033717,588:0.46519792,62:0.46215564,590:0.4575655,110:0.44682676,597:0.420567,95:0.41918993]
6    [648:0.45023045,736:0.4386352,95:0.34667525,786:0.3351175,1073:0.32370603,32:0.31021506,1210:0.30251333,608:0.2933381,7:0.28936782,36:0.28653657]
7    [1198:0.52251583,2028:0.51249886,1210:0.5006326,1197:0.48272145,1291:0.46804646,2571:0.45988122,1784:0.45771137,2797:0.4538604,1610:0.45373544,1704:0.4534099]
8    [480:0.86542463,318:0.7133561,434:0.6677318,185:0.6504521,208:0.6451925,161:0.64106977,253:0.6124166,34:0.5435114,586:0.5240867,288:0.50809836]
9    [2858:0.16401465,2762:0.12627697,2571:0.123330824,2997:0.11046047,296:0.10837068,2028:0.10639984,2329:0.103341825,1704:0.10107514,1089:0.100894466,50:0.098862514]
10    [1270:0.32084247,2571:0.2983431,608:0.29643345,1291:0.29354194,780:0.2851402,1036:0.27120706,1214:0.2681493,1197:0.26402688,1097:0.2634927,1200:0.24816594]

实际应用中,为了加快在线上推荐系统的检索,这些结果,可以考虑将数据存储到ElasticSearch或者SolrCloud系统中,方便查询。

混合协同过滤推荐

我们前面已经了解到,各种推荐方法都有其优点和缺点,那么对于实际复杂的需求,没有一种推荐方法能解决所有的问题,所以根据不同的需求采用组合多种推荐方法,共同来完成实际的推荐需求。
我们引用IBM Developerworks上一篇文章中介绍的,基于混合协推荐的实现方法,常用的有如下几种:

  1. 加权的混合(Weighted Hybridization): 用线性公式将几种不同的推荐按照一定权重组合起来,具体权重的值需要在测试数据集上反复实验,从而达到最好的推荐效果。
  2. 切换的混合(Switching Hybridization):其实对于不同的情况(数据量,系统运行状况,用户和物品的数目等),推荐策略可能有很大的不同,那么切换的混合方式,就是允许在不同的情况下,选择最为合适的推荐机制计算推荐。
  3. 分区的混合(Mixed Hybridization):采用多种推荐机制,并将不同的推荐结果分不同的区显示给用户。
  4. 分层的混合(Meta-Level Hybridization): 采用多种推荐机制,并将一个推荐机制的结果作为另一个的输入,从而综合各个推荐机制的优缺点,得到更加准确的推荐。

我们可以想到,根据前面介绍的基本协同过滤推荐方法,作为入门,可以这样实现一个混合协同过滤系统:

  • 根据用户的历史行为数据,离线计算推荐模型,得到模型A;
  • 为了使推荐满足实时行要求,可以选择使用基于用户的协同过滤推荐/基于物品的协同过滤推荐,基于实时用户行为数据,得到模型B;
  • 对于用户的冷启动问题,可以考虑采用统计的方式,找到热门的物品推荐给新用户,得到模型C;
  • 对于老用户,可以将模型A和B的结果进行一个排序筛选,得到一个新的Top N推荐列表。

这样,得到的推荐系统,就是一个混合推荐系统。

参考资料

相关 [协同过滤 方法] 推荐:

基于协同过滤的推荐方法

- - 简单之美
协同过滤(Collaborative Filtering, CF)是推荐系统广泛使用的一种技术,它主要通过考虑用户(User)与用户之间、物品(Item)与物品之间的相似度(Similarity),来向用户推荐物品,常被用在电商网站中. 其中,在推荐系统中最常使用的协同过滤方法,有如下4种:. 在介绍4种协同过滤推荐方法之前,我们先介绍一下有关相似性度量的问题:.

协同过滤算法

- - CSDN博客推荐文章
今天要讲的主要内容是 协同过滤,即Collaborative Filtering,简称 CF.    关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那.    么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐. 在问的时候,都习惯于问跟自己口味差不.

协同过滤 Collaborative Filtering

- - IT技术博客大学习
   协同过滤算法是推荐系统中最古老,也是最简单高效的推荐算法. 简单说协同过滤就是根据以往的用户产生的数据分析,对用户的新行为进行匹配分析来给用户推荐用户最有可能感兴趣的内容.    协同过滤算法是为了解决 长尾现象,也就是说推荐系统是为了解决长尾现象而诞生的. 因为在之前在有限的空间(如:书店的书架、服装店的衣架、商店的货架、网页的展示区域)只能摆有限的物品进行展示,造成大量的非热门物品很难进入人们的视野,也就无法产生任何价值.

协同过滤和推荐引擎

- - 刘思喆@贝吉塔行星
推荐系统在个性化领域有着广泛的应用,从技术上讲涉及概率、抽样、最优化、机器学习、数据挖掘、搜索引擎、自然语言处理等多个领域. 东西太多,我也不准备写连载,今天仅从基本算法这个很小的切入点来聊聊推荐引擎的原理. 推荐引擎(系统)从不同的角度看有不同的划分,比如:. 按照数据的分类:协同过滤、内容过滤、社会化过滤.

Spark MLlib中的协同过滤

- - JavaChen Blog
本文主要通过Spark官方的例子理解ALS协同过滤算法的原理和编码过程,然后通过对电影进行推荐来熟悉一个完整的推荐过程. 协同过滤常被应用于推荐系统,旨在补充用户-商品关联矩阵中所缺失的部分. MLlib当前支持基于模型的协同过滤,其中用户和商品通过一小组隐语义因子进行表达,并且这些因子也用于预测缺失的元素.

使用Mahout实现协同过滤 spark

- - zzm
Mahout使用了Taste来提高协同过滤算法的实现,它是一个基于Java实现的可扩展的,高效的推荐引擎. Taste既实现了最基本的基 于用户的和基于内容的推荐算法,同时也提供了扩展接口,使用户可以方便的定义和实现自己的推荐算法. 同时,Taste不仅仅只适用于Java应用程序,它 可以作为内部服务器的一个组件以HTTP和Web Service的形式向外界提供推荐的逻辑.

Amazon.com的推荐:从商品到商品的协同过滤

- 小和尚 - 互联网的那点事
以下全文翻译的PDF点此下载. Amazon.com 的推荐. 推荐算法以其在电子商务网站的用途而著称1,它们利用有关一个顾客的兴趣作为输入,来产生一个推荐商品的列表. 很多应用仅仅使用顾客购买并明确表示代表其兴趣的商品,但它们也可以利用其他属性,包括已浏览的商品、人口统计特征数据、主题兴趣,以及偏爱的艺术家.

基于综合兴趣度的协同过滤推荐算法

- - IT技术博客大学习
标签:   兴趣   协同过滤   推荐. 电子商务推荐系统最大的优点在于它能收集用户的兴趣资料和个人信息,根据用户兴趣偏好主动为用户做出个性化推荐. 推荐技术指的是如何找出用户感兴趣的商品并列出推荐清单,在用户信息获取差别不大的情况下,推荐技术成为决定一个推荐系统性能的关键,其中推荐算法是推荐技术的核心[1].

协同过滤推荐系统的那些不足点

- - 标点符
类目(种类)推荐杂很多情境下行不通,因为有太多的产品属性,而每个属性(比如价钱,颜色,风格,面料,等等)在不同的时候对于消费者的重要程度都是不一样的. 但是协同过滤推荐系统也不是那么完美无缺,他或多或少的会有那么一些问题~. 协同过滤的精度主要取决于用户数据的多少. 如果一个系统有很多用户的历史数据,他就能更好的对用户的喜欢做出预测.