一般,电影推荐系统测试数据来源:http://grouplens.org/datasets/movielens/
最近,在研究数据挖掘中的推荐系统,很深奥,还专门买了一本《推荐系统实践》的书,里面讲解的还行吧,凑活!在网上也是看各种博客,各种资料!!
自己也尝试了自己动手实现一下,但是比起Mahout开源项目中的算法效率,我写的效率很低,所以就决定使用Mahout了,虽然Mahout只是封装了一些基本的推荐算法,但是基本上够我用了~~
在这里需要说明一下,推荐算法是一个不断优化,不断提升的循序渐进的过程,是不可能一蹴而就的~~~而且推荐算法的效率要视情况而定,适合你的项目的才是最好的!!
在这里贴出,我用Mahout实现的简单的三个算法:UserCF,ItemCF,SlopeOne
基于用户的协同过滤算法(UserCF)
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
import org.apache.mahout.cf.taste.hadoop.item.RecommenderJob;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.common.FastIDSet;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
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.similarity.PearsonCorrelationSimilarity;//EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.UncenteredCosineSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
/*
*
*
* 基于用户的协同过滤
*
* 利用apache mahout开源项目
*
* 通过基于用户的协同过滤算法,来给用户推荐商品
*
*/
public class UserBaseCFMain {
final static int NEIGHBORHOOD_NUM =3;//邻居数目
final static int RECOMMENDER_NUM = 7;//推荐物品数目
public static void main(String[] args) throws Exception {
String file = "E:\\test2.txt";
DataModel model =new FileDataModel(new File(file));//FileDataModel要求文件数据存储格式(必须用“,”分割):userID,itemID[,preference[,timestamp]]
UserSimilarity user = new PearsonCorrelationSimilarity(model);
NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(NEIGHBORHOOD_NUM, user, model);
Recommender r = new GenericUserBasedRecommender(model, neighbor, user);
LongPrimitiveIterator iter = model.getUserIDs();
while (iter.hasNext()) {
long uid = iter.nextLong();
List 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();
}
}
}
基于物品的协同过滤(ItermCF)
import java.io.File;
import java.util.List;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
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.PearsonCorrelationSimilarity;
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;
/*
*
* 基于物品相似度的推荐引擎
*
*
*/
public class MyItemBasedRecommender {
public static void main(String[] s) throws Exception{
DataModel model = new FileDataModel(new File("E:\\test2.txt"));//构造数据模型,File-based
//DataModel model=new GenericBooleanPrefDataModel(GenericBooleanPrefDataModel.toDataMap(model1));
ItemSimilarity similarity = new PearsonCorrelationSimilarity(model);//计算内容相似度
Recommender recommender = new GenericItemBasedRecommender(model, similarity);//构造推荐引擎
LongPrimitiveIterator iter = model.getUserIDs();
while (iter.hasNext()) {
long uid = iter.nextLong();
List list = recommender.recommend(uid,3);
System.out.printf("uid:%s", uid);
for (RecommendedItem ritem : list) {
System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
}
System.out.println();
}
}
}
SlopeOne
import java.io.File;
import java.util.List;
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.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
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;
/*
* 基于Slop One的推荐引擎
*
* 基于用户和基于内容是最常用最容易理解的两种推荐策略,但在大数据量时,它们的计算量会很大,从而导致推荐效率较差。因此 Mahout 还提供了一种更加轻量级的 CF 推荐策略:Slope One。
Slope One 是有 Daniel Lemire 和 Anna Maclachlan 在 2005 年提出的一种对基于评分的协同过滤推荐引擎的改进方法,下面简单介绍一下它的基本思想。
假设系统对于物品 A,物品 B 和物品 C 的平均评分分别是 3,4 和 4。基于 Slope One 的方法会得到以下规律:
•用户对物品 B 的评分 = 用户对物品 A 的评分 + 1
•用户对物品 B 的评分 = 用户对物品 C 的评分
基于以上的规律,我们可以对用户 A 和用户 B 的打分进行预测:
•对用户 A,他给物品 A 打分 4,那么我们可以推测他对物品 B 的评分是 5,对物品 C 的打分也是 5。
•对用户 B,他给物品 A 打分 2,给物品 C 打分 4,根据第一条规律,我们可以推断他对物品 B 的评分是 3;而根据第二条规律,推断出评分是 4。当出现冲突时,我们可以对各种规则得到的推断进行就平均,所以给出的推断是 3.5。
这就是 Slope One 推荐的基本原理,它将用户的评分之间的关系看作简单的线性关系:
Y = mX + b;
当 m = 1 时就是 Slope One,也就是我们刚刚展示的例子。
*
*
*
*/
public class MySlopeOneRecommender {
public static void main(String[] s) throws Exception{
DataModel model = new FileDataModel(new File("E:\\test2.txt"));//构造数据模型
Recommender recommender = new CachingRecommender(new SlopeOneRecommender(model));//构造推荐引擎
LongPrimitiveIterator iter = model.getUserIDs();
while (iter.hasNext()) {
long uid = iter.nextLong();
List list = recommender.recommend(uid,3);
System.out.printf("uid:%s", uid);
for (RecommendedItem ritem : list) {
System.out.printf("(%s,%f)", ritem.getItemID(), ritem.getValue());
}
System.out.println();
}
}
}
测试数据:
test2.txt部分数据
格式:用户ID,物品ID,评分,时间戳(默认前三项有用,时间戳忽略不计,在这里必须用“,”隔开)
1,1193,5,978300760
1,661,3,978302109
1,914,3,978301968
1,3408,4,978300275
1,2355,5,978824291
1,1197,3,978302268
1,1287,5,978302039
1,2804,5,978300719
1,594,4,978302268
1,919,4,978301368
1,595,5,978824268
1,938,4,978301752
1,2398,4,978302281
1,2918,4,978302124
1,1035,5,978301753
1,2791,4,978302188
1,2687,3,978824268
1,2018,4,978301777
1,3105,5,978301713
1,2797,4,978302039
1,2321,3,978302205
1,720,3,978300760
1,1270,5,978300055
1,527,5,978824195
1,2340,3,978300103
1,48,5,978824351
1,1097,4,978301953
在这里呢,我还没有实现用其他标点分割,也没实现“用户ID,物品ID”存储结构的读取~~请大家谁知道的,留言!
在此呢,我利用上述三种算法实现了一个web版的推荐,下面是截图:
源代码(包含测试数据):http://download.csdn.net/detail/zeq9069/6572319