协同过滤算法之基于计算用户之间相似度
三种方法实现:
//余弦相似度
UserSimilarity userSimilarity = new UncenteredCosineSimilarity(dataModel);
//欧几里得相似度
UserSimilarity userSimilarity1 = new EuclideanDistanceSimilarity(dataModel);
//皮尔森相似度
UserSimilarity userSimilarity2 = new PearsonCorrelationSimilarity(dataModel);
流程:
1、数据准备
alice.txt文件:用户ID,物品ID,用户对物品的评分
1,101,5
1,102,3
1,103,4
1,104,4
2,101,3
2,102,1
2,103,2
2,104,3
2,105,3
3,101,4
3,102,3
3,103,4
3,104,3
3,105,5
4,101,3
4,102,3
4,103,1
4,104,5
4,105,4
5,101,1
5,102,5
5,103,5
5,104,2
5,105,1
2、代码实现
pom.xml中导入Hadoop Mahout算法库
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.leboop</groupId>
<artifactId>mahout</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<!-- mahout版本号 -->
<mahout.version>0.13.0</mahout.version>
</properties>
<dependencies>
<!-- mahout -->
<dependency>
<groupId>org.apache.mahout</groupId>
<artifactId>mahout-integration</artifactId>
<version>${mahout.version}</version>
</dependency>
</dependencies>
</project>
推荐程序中,我们使用皮尔森系数计算用户相似度
1、将文件数据转换成数据模型
dataModel = new FileDataModel(new File(filePath));
2、用户相似度定义
//余弦相似度
UserSimilarity userSimilarity = new UncenteredCosineSimilarity(dataModel);
//欧几里得相似度
UserSimilarity userSimilarity1 = new EuclideanDistanceSimilarity(dataModel);
//皮尔森相似度
UserSimilarity userSimilarity2 = new PearsonCorrelationSimilarity(dataModel);
3、定义用户的2最近邻
long[] userN = userNeighborhood.getUserNeighborhood(userID);
4、定义推荐引擎
Recommender recommender = new GenericUserBasedRecommender(dataModel,userNeighborhood,userSimilarity2);
5、可通过通过两个迭代器计算任何两个用户的相似度输出查看
6、获取userID的N-最近邻
long[] userN = userNeighborhood.getUserNeighborhood(userID);
7、获取推荐物品,指定获取个数
List<RecommendedItem> recommendedItems = recommender.recommend(userID,2);
8、可遍历输出物品
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.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.UncenteredCosineSimilarity;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class test {
public static void main(String[]args){
//用户-物品-评分文件路径
String filePath = "E:\\data\\alice.txt";
//数据模型
FileDataModel dataModel = null;
try {
//文件数据转换成数据模型
dataModel = new FileDataModel(new File(filePath));
/*
用户相似度定义
*/
//余弦相似度
UserSimilarity userSimilarity = new UncenteredCosineSimilarity(dataModel);
//欧几里得相似度
UserSimilarity userSimilarity1 = new EuclideanDistanceSimilarity(dataModel);
//皮尔森相似度
UserSimilarity userSimilarity2 = new PearsonCorrelationSimilarity(dataModel);
//定义用户的2最近邻
UserNeighborhood userNeighborhood = new NearestNUserNeighborhood(2,userSimilarity2,dataModel);
//定义推荐引擎
Recommender recommender = new GenericUserBasedRecommender(dataModel,userNeighborhood,userSimilarity2);
//从数据模型中获取所有用户的ID迭代器
LongPrimitiveIterator usersIterator = dataModel.getUserIDs();
//通过迭代器遍历所有用户ID
while(usersIterator.hasNext()){
System.out.println("=======================================");
//用户ID
long userID = usersIterator.nextLong();
//用户ID迭代器
LongPrimitiveIterator otherusersIterator = dataModel.getUserIDs();
//相当于两个for循环,遍历用户ID,计算任何两个用户的相似度
while(otherusersIterator.hasNext()){
Long otherUserID = otherusersIterator.nextLong();
System.out.println("用户 " + userID
+ " 与用户 "+ otherUserID + " 的相似度为 "
+ userSimilarity2.userSimilarity(userID,otherUserID));
}
//userID的N-最近邻
long[] userN = userNeighborhood.getUserNeighborhood(userID);
//用户userID的推荐物品,最多推荐两个
List<RecommendedItem> recommendedItems = recommender.recommend(userID,2);
System.out.println("用户 " + userID + " 的2-最近邻是 " + Arrays.toString(userN));
if(recommendedItems.size()>0){
for (RecommendedItem item : recommendedItems){
System.out.println("推荐的物品 " + item.getItemID()
+ "预测评分是 " + item.getValue());
}
}
else{
System.out.println("无任何物品推荐");
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (TasteException e) {
e.printStackTrace();
}
}
}
输出如下:
=======================================
用户 1 与用户 1 的相似度为 0.9999999999999998
用户 1 与用户 2 的相似度为 0.8528028654224417
用户 1 与用户 3 的相似度为 0.7071067811865475
用户 1 与用户 4 的相似度为 0.0
用户 1 与用户 5 的相似度为 -0.7921180343813393
用户 1 的2-最近邻是 [2, 3]
推荐的物品 105预测评分是 3.9065998
=======================================
用户 2 与用户 1 的相似度为 0.8528028654224417
用户 2 与用户 2 的相似度为 1.0
用户 2 与用户 3 的相似度为 0.4677071733467446
用户 2 与用户 4 的相似度为 0.4899559349388647
用户 2 与用户 5 的相似度为 -0.9001487972234673
用户 2 的2-最近邻是 [1, 4]
无任何物品推荐
=======================================
用户 3 与用户 1 的相似度为 0.7071067811865475
用户 3 与用户 2 的相似度为 0.4677071733467422
用户 3 与用户 3 的相似度为 1.0
用户 3 与用户 4 的相似度为 -0.16116459280507703
用户 3 与用户 5 的相似度为 -0.466569474815843
用户 3 的2-最近邻是 [1, 2]
无任何物品推荐
=======================================
用户 4 与用户 1 的相似度为 0.0
用户 4 与用户 2 的相似度为 0.489955934938866
用户 4 与用户 3 的相似度为 -0.16116459280507558
用户 4 与用户 4 的相似度为 1.0
用户 4 与用户 5 的相似度为 -0.6415029025857746
用户 4 的2-最近邻是 [2, 1]
无任何物品推荐
=======================================
用户 5 与用户 1 的相似度为 -0.7921180343813393
用户 5 与用户 2 的相似度为 -0.9001487972234682
用户 5 与用户 3 的相似度为 -0.466569474815843
用户 5 与用户 4 的相似度为 -0.6415029025857751
用户 5 与用户 5 的相似度为 1.0
用户 5 的2-最近邻是 [3, 4]
无任何物品推荐