package com;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Test;
/**
* ItemCF 基于物品的协同过滤算法
* 和用户历史上感兴趣的物品越相似的物品,越有可能在用户的推荐列表中获得比较高的排名
* 格式化输入——>获取用户物品倒排表——>获取每个电影的评论用户数——>计算相似度矩阵——>预测评分——>推荐结果
*/
@SuppressWarnings("resource")
public class MovieRecommend
{
private static Collection<UserContent> list=new ArrayList<UserContent>();
private static Map<String,Integer> movieMap=new LinkedHashMap<String,Integer>();//统计电影总数
private static Map<String,ArrayList<String>> userMap=new LinkedHashMap<String,ArrayList<String>>();//存放用户-评过分的电影
private static Map<String,Integer> movieUserMap=new LinkedHashMap<String,Integer>();//存放每个电影的用户数量
private static Map<String,Double> similaryMap=new LinkedHashMap<String, Double>();//存放相似度
private static Map<String,Double> resultMap=new LinkedHashMap<String, Double>();//存放推荐结果
/**
* 对数据预处理,将评分信息存入集合
*/
public ArrayList<UserContent> readData() throws IOException{
BufferedReader read=new BufferedReader(new FileReader("C:/Users/zzd/Desktop/ml-100k/u.data"));
String str;
while((str=read.readLine())!=null){
String[] split = str.split("\t");//只获取文件中的前三个数据
UserContent uc=new UserContent();
uc.setUserId(split[0]);
uc.setMovieId(split[1]);
uc.setScore(split[2]);
list.add(uc);
}
return (ArrayList<UserContent>)list;
}
/**
* 计算电影间的相似度矩阵
*/
public int[][] movieSimilarty(ArrayList<UserContent> list){
/**
* 获取用户-电影倒排表
*/
for(int i=0;i<list.size();i++){//map中不允许存放重复数据,利用这个特点计算出共有多少部电影
UserContent uc=(UserContent) list.get(i);
String movieId = uc.getMovieId();
movieMap.put(movieId, 1);
String userId = uc.getUserId();
if(userMap.containsKey(userId)){//集合中存在userId
ArrayList<String> movieList=userMap.get(userId);;//获取之前的list 每个用户评过分的电影
if(movieList!=null&&!movieList.contains(movieId)){//电影不存在
movieList.add(movieId);
userMap.remove(userId);//乱序的
userMap.put(userId, movieList);
}
}else{//集合中不存在userId
ArrayList<String> movieList1=new ArrayList<String>();
movieList1.add(movieId);
userMap.put(userId, movieList1);
}
}
/***
* 统计每个电影被多少用户评分过
*/
int movieCount=movieMap.size();//电影总数
int movie[][]=new int[movieCount][movieCount];//相似度矩阵
for(Entry<String, ArrayList<String>> e:userMap.entrySet()){
ArrayList<String> movieList = (ArrayList<String>)e.getValue();
for(int i=0;i<movieList.size();i++){
String movieId = movieList.get(i);
if(movieUserMap.containsKey(movieId)){//如果存在
int count=movieUserMap.get(movieId).intValue()+1;
movieUserMap.remove(movieId);
movieUserMap.put(movieId, count);
}else{//不存在
movieUserMap.put(movieId, 1);
}
}
}
/***
* 构建矩阵
*/
/*不用排序了,因为数据中电影id是从0-1682连续的,若是不连续的要排序
//获取所有movieId,并排序,与二维数组的下标对应
int movieId[]=new int[movieCount];
int i=0;
for(Entry<String, Integer> e:movieMap.entrySet()){
movieId[i++]=Integer.parseInt(e.getKey());
}
Arrays.sort(movieId);//排序
for (int j : movieId) {
System.out.println(j);
}*/
for(Entry<String,ArrayList<String>> e:userMap.entrySet()){//遍历建立矩阵
ArrayList<String> movieList = e.getValue();
int movieId[]=new int[movieCount];//存放电影Id
int n=0;
for(int i=0;i<movieList.size();i++){//将电影Id放到数组里
movieId[n++]=Integer.parseInt(movieList.get(i));
}
//对同一个用户评分的任意两个电影,矩阵中都+1
if(movieId.length>1){//至少要有两个电影
for(int i=0;i<movieId.length-1;i++){
for(int j=i+1;j<movieId.length;j++){
if(movieId[i]!=0&&movieId[j]!=0){
movie[movieId[i]-1][movieId[j]-1]+=1;
movie[movieId[j]-1][movieId[i]-1]+=1;
}
}
}
}
}
/**
* 测试
*/
/*System.out.println("电影总数:"+movieCount); //test1
System.out.println("每个用户评过分的电影");
for(Entry<String, ArrayList<String>> e:userMap.entrySet()){ //test2
System.out.print(e.getKey()+":\t[");
ArrayList<String> list2 = (ArrayList<String>)e.getValue();
for(int i=0;i<list2.size();i++){
System.out.print(list2.get(i)+",");
}
System.out.println("]");
}
System.out.println("每个电影的用户数");
for(Entry<String,Integer> e:movieUserMap.entrySet()){ //test3
System.out.println(e.getKey()+": "+e.getValue()+"人");
}
System.out.println("所有电影:");//test4
for(Entry e:movieMap.entrySet()){
System.out.print(e.getKey()+" ");
}
System.out.println();
System.out.println("相似度矩阵");
for(int i=0;i<movie.length;i++){//test5
for(int j=0;j<movie.length;j++){
System.out.print(movie[i][j]+" ");
}
System.out.println();
}
*/
return movie;
}
/**
* 计算推荐结果
* 对一个用户推荐,选取k个相似度最接近的,排序后推荐前n个
*/
public void result(int movie[][],String userId,int k,int n){
/**
*预测用户对其他未评过分的电影的喜爱程度
*遍历电影集合
*/
for(Entry<String ,Integer> e:movieMap.entrySet()){
String movieId=e.getKey();
ArrayList<String> list = userMap.get(userId);//用户评过分的电影集合
if(list.contains(movieId)){
continue;
}else{//对未评过分的电影预测评分
//计算相似度
// System.out.println("推荐电影:"+movieId);
for(int i=0;i<movieMap.size();i++){
if(list.contains(String.valueOf(i+1))){//该用户必须包含被推荐电影的相似电影
int sum=movie[i][Integer.parseInt(movieId)-1];
int count=movieUserMap.get(movieId);
int count1=movieUserMap.get(String.valueOf(i+1));
if(sum==0||count==0||count1==0){
continue;
}
double similary=((double)sum)/Math.sqrt((double)(count*count1));//最终相似度
similaryMap.put(String.valueOf(i+1), similary);
// System.out.println(movieId+"和电影"+(i+1)+"的相似度为:"+similary);
}
}
//排序 选取k个和该电影相似度最高的(因为相似度不高的参与运算会不准确!)
//用二维数组,对value排序,第一行放相似度,第二行放与之对应的电影id
double similarySort[][]=new double[2][movieMap.size()];
int i=0;
for(Entry<String,Double> e1:similaryMap.entrySet()){//存进数组
double similary=e1.getValue();
int movieId1=Integer.parseInt(e1.getKey());
similarySort[0][i]=similary;
similarySort[1][i++]=movieId1;
}
for(int i1=0;i1<movieMap.size()-1;i1++){//对相似度排序,电影id也跟着交换
for(int j1=i1+1;j1<movieMap.size();j1++){
if(similarySort[0][i1]<similarySort[0][j1]){
double t;
t=similarySort[0][i1];
similarySort[0][i1]=similarySort[0][j1];
similarySort[0][j1]=t;
int t1;
t1=(int) similarySort[1][i1];
similarySort[1][i1]=similarySort[1][j1];
similarySort[1][j1]=t1;
}
}
}
//计算用户对某电影的评分
double recommend=0;
//从排序后的数�
没有合适的资源?快使用搜索试试~ 我知道了~
基于物品的协同过滤.zip
共17个文件
prefs:3个
java:3个
class:3个
需积分: 5 0 下载量 88 浏览量
2024-05-19
21:56:30
上传
评论
收藏 14KB ZIP 举报
温馨提示
协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。
资源推荐
资源详情
资源评论
收起资源包目录
基于物品的协同过滤.zip (17个子文件)
content
Recommend
.classpath 996B
.settings
org.eclipse.jdt.core.prefs 238B
org.eclipse.core.resources.prefs 115B
org.eclipse.m2e.core.prefs 86B
pom.xml 747B
src
test
java
com
Test.java 830B
main
java
com
MovieRecommend.java 10KB
UserContent.java 513B
target
classes
META-INF
MANIFEST.MF 99B
maven
BigData
Recommend
pom.properties 236B
pom.xml 747B
com
UserContent.class 898B
MovieRecommend.class 7KB
test-classes
com
Test.class 2KB
.project 538B
.gitattributes 378B
.gitignore 649B
共 17 条
- 1
资源评论
生瓜蛋子
- 粉丝: 3840
- 资源: 6140
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- TC8301.SOP-8封装 单通道直流马达驱动器 深圳市可芯电子有限公司.pdf
- win7calc.7z win7计算器
- 1719296385116.jpg
- untitled.7z
- anaconda anaconda anaconda
- 2009年3月二级C语言笔试真题及答案选择题.pdf
- Easy Minimap System MT - GPS, Minimap, Worldmap
- fontconfig-2.13.0-4.3.el7.x86-64.rpm
- FM5888C SOT23-5 USB专用充电端口控制器 深圳市可芯电子有限公司.pdf
- Stable Diffusion 商业变现与绘画大模型多场景实战完结12章
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功