您的位置:首页 > 编程语言 > Java开发

基于用户的协同过滤算法和基于物品的协同过滤算法之java实现

2017-01-25 11:25 435 查看
最近lz在研究推荐系统,对利用基于协同过滤算法来实现推荐非常感兴趣,因此,就自学了这一方面的内容,并且看了《推荐系统实践》一书,对这方面的理解也进了一步。首先协同过滤算法在1992年被提出来,最初的设想是,当你去要看电影时,不知道要看哪一部,此时你可能会去询问你的朋友,关于这方面的问题,因为往往你的朋友在这一方面和你的兴趣相似,所以我们可以通过与你具有相似兴趣的朋友喜欢的电影入手来通过他们来给你推荐相关的电影。因此,这就是协同过滤算法的来源。发展至今,协同过滤算法又分为两个分支,分别是基于用户的协同过滤算法(user-based
cf)和基于物品的协同过滤算法(item-based cf)两类。那么本文研究的是基于用户的协同过滤算法。首先,我们考虑计算用户之间的相似度。比如有基于欧几里得距离的相似度、基于皮尔逊相关系数的相似度等。那么通过计算相似度,就可以得到top
K的相似度中最近的前K个的用户,然后通过根据这些用户所喜爱的电影来推荐给这个用户,这也就是基于用户的协同过滤算法为不同用户来定制个性化的推荐内容的主旨。
基于物品的协同过滤算法于基于用户的协同过滤算法的区别在于,是对物品进行相似度计算,然后再进行推荐。
那么利用apache公司开源的mahout工具可以进行计算。
首先数据集用csv表示,如下图所示:
1,101,5.0

1,102,3.0

1,103,2.5

2,101,2.0

2,102,2.5

2,103,5.0

2,104,2.0

3,101,2.5

3,104,4.0

3,105,4.5

3,107,5.0

4,101,5.0

4,103,3.0

4,104,4.5

4,106,4.0

5,101,4.0

5,102,3.0

5,103,2.0

5,104,4.0

5,105,3.5

5,106,4.0

基于用户的协同过滤算法实现:
package com.sunwangdong;

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;

import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.recommender.*;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class Main
{
final static int NEIGHBORHOOD_NUM = 2;   //用户邻居数量
final static int RECOMMENDER_NUM = 3;    //推荐结果个数

public static void main(String[] args) throws IOException,TasteException
{
// write your code here

String file = "datafile/data.csv";   //数据集,其中第一列表示用户id;第二列表示商品id;第三列表示评分,评分是5分制
DataModel model = new FileDataModel(new File(file));  //基于文件的model,通过文件形式来读入,且此类型所需要读入的数据的格式要求很低,只需要满足每一行是用户id,物品id,用户偏好,且之间用tab或者是逗号隔开即可

//基于用户的协同过滤算法,基于物品的协同过滤算法

UserSimilarity user = new EuclideanDistanceSimilarity(model);  //计算欧式距离,欧式距离来定义相似性,用s=1/(1+d)来表示,范围在[0,1]之间,值越大,表明d越小,距离越近,则表示相似性越大
NearestNUserNeighborhood  neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
//指定用户邻居数量

//构建基于用户的推荐系统
Recommender r = new GenericUserBasedRecommender(model, neighbor, user);

//得到所有用户的id集合
LongPrimitiveIterator iter = model.getUserIDs();

while(iter.hasNext())
{
long uid = iter.nextLong();
List<RecommendedItem> list = r.recommend(uid,RECOMMENDER_NUM);  //获取推荐结果
System.out.printf("uid:%s",uid);
//遍历推荐结果
for(RecommendedItem ritem : list)
{
System.out.printf("(%s,%f)",ritem.getItemID(),ritem.getValue());
}
System.out.println();
}

}
}


接下来是基于物品的协同过滤算法实现:
package com.sunwangdong;

/**
* Created by sunwangdong on 2017/1/24.
*/

import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.common.RandomUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class itemcf
{
final static int NEIGHBORHOOD_NUM = 2;
final static int RECOMMENDER_NUM = 3;
public static void main(String[] args) throws IOException,TasteException
{
RandomUtils.useTestSeed();
String file = "datafile/data.csv";

DataModel model = new FileDataModel(new File(file));

ItemSimilarity item = new EuclideanDistanceSimilarity(model);

Recommender r = new GenericItemBasedRecommender(model,item);

LongPrimitiveIterator iter = model.getUserIDs();

while(iter.hasNext())
{
long uid = iter.nextLong();
List<RecommendedItem> list = r.recommend(uid,RECOMMENDER_NUM);  //获取推荐结果
System.out.printf("uid:%s",uid);
//遍历推荐结果
for(RecommendedItem ritem : list)
{
System.out.printf("(%s,%f)",ritem.getItemID(),ritem.getValue());
}
System.out.println();
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: