协同过滤推荐算法(java原生JDK实现-附源码地址)
- 格式:docx
- 大小:159.82 KB
- 文档页数:23
推荐算法:协同过滤算法的介绍⼀、什么是推荐算法互联⽹的出现和普及给⽤户带来了⼤量的信息,满⾜了⽤户在信息时代对信息的需求,但随着⽹络的迅速发展⽽带来的⽹上信息量的⼤幅增长,使得⽤户在⾯对⼤量信息时⽆法从中获得对⾃⼰真正有⽤的那部分信息,对信息的使⽤效率反⽽降低了,这就是所谓的信息超载(informationoverload)问题。
解决信息超载问题的⼀个办法是推荐系统。
推荐系统,就是通过分析⽤户的⾏为,兴趣偏好,进⾏个性化计算,由系统发现⽤户的兴趣点,最终将⽤户感兴趣的信息、产品等推荐给⽤户的个性化信息推荐系统。
推荐系统不仅能为⽤户提供个性化的服务,还能和⽤户之间建⽴密切关系,让⽤户对推荐产⽣依赖。
推荐系统现已⼴泛应⽤于很多领域,其中最典型并具有良好的发展和应⽤前景的领域就是电⼦商务领域。
⼆、什么是协同过滤协同过滤,CF (Collaborative Filtering)是推荐系统中的⼀种推荐算法。
主要有两个基本的算法:基于⽤户的协同过滤( user-based CF) 和基于项⽬的协同过滤( item-based CF )1)基于⽤户的协同过滤推荐机制机制原理:基于⽤户对物品的偏好找到相邻邻居⽤户,然后将邻居⽤户喜欢的推荐给当前⽤户。
它的基本假设是:喜欢类似物品的⽤户可能有相同或者相似的偏好。
上图⽰意出基于⽤户的协同过滤推荐机制的基本原理:假设⽤户A喜欢物品A,物品 C,⽤户B 喜欢物品B,⽤户C喜欢物品A,物品C和物品 D;从这些⽤户的历史喜好信息中,我们可以发现⽤户A和⽤户C的偏好是⽐较类似的,同时⽤户C还喜欢物品D,那么我们可以推断⽤户A可能也喜欢物品D,因此可以将物品D推荐给⽤户A。
2)基于项⽬的协同过滤推荐机制机制原理:根据所有⽤户对物品或者信息的偏好,发现物品和物品之间的相似度,然后根据⽤户的历史偏好信息,将类似的物品推荐给⽤户。
上图⽰意出基于项⽬的协同过滤推荐机制的基本原理:对于物品A,根据所有⽤户的历史偏好,喜欢物品A 的⽤户都喜欢物品C,得出物品A 和物品C ⽐较相似,⽽⽤户C 喜欢物品A,那么可以推断出⽤户C 可能也喜欢物品C。
基于项目协同过滤算法java代码基于项目协同过滤算法Java代码引言:在当今互联网时代,个性化推荐系统已经成为了各大电商平台和社交媒体的重要组成部分。
协同过滤算法是个性化推荐系统中常用的一种算法,其主要思想是通过分析用户的历史行为,找到与当前用户最相似的其他用户或物品,从而给用户推荐相关的信息或商品。
本文将介绍基于Java代码实现的项目协同过滤算法。
一、协同过滤算法简介协同过滤算法是一种基于用户或物品之间相似度的推荐算法,其核心思想是“物以类聚、人以群分”。
协同过滤算法分为基于用户的协同过滤和基于物品的协同过滤两种方式。
1. 基于用户的协同过滤算法基于用户的协同过滤算法主要通过计算用户之间的相似度来进行推荐。
首先,需要构建用户-物品评分矩阵,矩阵中的每个元素表示用户对物品的评分。
然后,通过计算用户之间的相似度,找到与当前用户最相似的若干用户。
最后,根据这些相似用户的评分情况,推荐给当前用户未评分的物品。
2. 基于物品的协同过滤算法基于物品的协同过滤算法主要通过计算物品之间的相似度来进行推荐。
同样地,首先需要构建用户-物品评分矩阵。
然后,通过计算物品之间的相似度,找到与当前物品最相似的若干物品。
最后,根据用户的历史评分情况,推荐与当前物品最相似的其他物品。
二、项目协同过滤算法Java代码实现下面是一个基于用户的协同过滤算法的Java代码示例:```javaimport java.util.HashMap;import java.util.Map;public class UserBasedCF {// 用户-物品评分矩阵private static Map<String, Map<String, Integer>> userItemMatrix = new HashMap<>();// 用户之间的相似度矩阵private static Map<String, Map<String, Double>> userSimilarityMatrix = new HashMap<>();// 获取用户之间的相似度private static double getUserSimilarity(String user1, String user2) {// 根据用户-物品评分矩阵计算用户之间的相似度// ...return similarity;}// 为用户进行推荐public static Map<String, Double> recommend(String user) {Map<String, Double> recommendations = new HashMap<>();Map<String, Integer> items = userItemMatrix.get(user);for (String item : items.keySet()) {for (String otherUser : userItemMatrix.keySet()) {if (!otherUser.equals(user)) {double similarity = getUserSimilarity(user, otherUser);int rating = userItemMatrix.get(otherUser).getOrDefault(item, 0);recommendations.put(item, recommendations.getOrDefault(item, 0.0) + similarity * rating);}}}return recommendations;}public static void main(String[] args) {// 构建用户-物品评分矩阵// ...// 为指定用户进行推荐String user = "user1";Map<String, Double> recommendations = recommend(user);// 输出推荐结果for (Map.Entry<String, Double> entry : recommendations.entrySet()) {System.out.println("Item: " + entry.getKey() + ", Score: " + entry.getValue());}}}```三、实现原理解析以上代码实现了基于用户的协同过滤算法。
推荐系统的协同过滤算法一、引言随着互联网的普及和发展,人们接触到的信息越来越丰富。
在海量信息中,如何找到适合自己的内容,成为了人们关注的焦点。
推荐系统就是为了解决这个问题而被广泛应用的一种技术。
推荐系统的主要任务是根据用户的历史行为和兴趣爱好,向用户推荐最可能感兴趣的内容,从而提高用户的满意度。
协同过滤算法是推荐系统中应用最广泛的算法之一。
协同过滤算法的主要思想是根据用户历史行为中的相似度关系,推荐给用户相似的内容。
本文将介绍协同过滤算法的原理、分类以及常见的实现方式,帮助读者更好地理解和应用该算法。
二、协同过滤算法原理协同过滤算法的核心思想是根据用户历史行为中的相似度关系,推荐给用户相似的内容。
协同过滤算法可以分为两类:基于用户的协同过滤算法和基于物品的协同过滤算法。
基于用户的协同过滤算法是指根据用户历史喜好的相似度来预测用户对其未看过的内容是否感兴趣。
例如,在电影推荐系统中,可以通过用户对电影的评分行为来构成用户的历史行为数据,根据用户历史行为的相似度以及已看电影的评分情况,预测用户对其他电影的评分。
基于物品的协同过滤算法是指根据内容相似性来预测用户对其未看过的内容是否感兴趣。
例如,在电影推荐系统中,可以构建电影与电影之间的相似性关系,根据用户历史行为中已经看过电影的评分情况,预测用户对其他电影的评分。
三、基于用户的协同过滤算法基于用户的协同过滤算法是通过用户历史行为的相似度来预测用户对未知内容的评分。
其中,用户历史行为可以包括用户看过的电影、听过的歌曲、浏览过的网页等,具体实现方式有以下几种。
1. 基于用户的相似度基于用户的相似度是指通过计算用户历史行为之间的相似度,来预测用户对未知内容的评分。
例如,在电影推荐系统中,可以先计算用户之间的相似度,然后根据相似度高的用户的评分预测目标用户对未知电影的评分。
计算用户之间的相似度通常采用余弦相似度,计算公式如下:$similarity(u_i,u_j)=\frac{\sum_{k=1}^np_{ik}p_{jk}}{\sqrt{\sum _{k=1}^np_{ik}^2}\sqrt{\sum_{k=1}^np_{jk}^2}}$其中,$p_{ik}$表示用户$i$对物品$k$的评分,$n$表示物品总数。
基于协同过滤的推荐算法与代码实现什么是协同过滤?协同过滤是利用集体智慧的一个典型方法。
要理解什么是协同过滤(Collaborative Filtering, 简称CF),首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最近有什么好看的电影推荐,而我们一般更倾向于从口味比较类似的朋友那里得到推荐。
这就是协同过滤的核心思想。
协同过滤一般是在海量的用户中发掘出一小部分和你品位比较类似的,在协同过滤中,这些用户成为邻居,然后根据他们喜欢的其他东西组织成一个排序的目录作为推荐给你。
当然其中有一个核心的问题:如何确定一个用户是不是和你有相似的品位?如何将邻居们的喜好组织成一个排序的目录?简单来说:1. 和你兴趣合得来的朋友喜欢的,你也很有可能喜欢;2. 喜欢一件东西A,而另一件东西B 与这件十分相似,就很有可能喜欢B;3. 大家都比较满意的,人人都追着抢的,我也就很有可能喜欢。
三者均反映在协同过滤的评级(rating)或者群体过滤(social filtering)这种行为特性上。
深入协同过滤的核心首先,要实现协同过滤,需要一下几个步骤:1. 收集用户偏好2. 找到相似的用户或物品3. 计算推荐(1)收集用户偏好要从用户的行为和偏好中发现规律,并基于此给予推荐,如何收集用户的偏好信息成为系统推荐效果最基础的决定因素。
用户有很多方式向系统提供自己的偏好信息,而且不同的应用也可能大不相同,下面举例进行介绍:以上列举的用户行为都是比较通用的,推荐引擎设计人员可以根据自己应用的特点添加特殊的用户行为,并用他们表示用户对物品的喜好。
在一般应用中,我们提取的用户行为一般都多于一种,关于如何组合这些不同的用户行为,基本上有以下两种方式:将不同的行为分组:一般可以分为“查看”和“购买”等等,然后基于不同的行为,计算不同的用户/物品相似度。
类似于当当网或者Amazon 给出的“购买了该图书的人还购买了...”,“查看了图书的人还查看了...”根据不同行为反映用户喜好的程度将它们进行加权,得到用户对于物品的总体喜好。
【推荐算法】协同过滤算法——基于⽤户Java实现只是简单谢了⼀个Demo,先贴上GitHub地址。
基本概念就不过多介绍了,相信能看明⽩的都了解。
如果想了解相关推荐先做好知识储备:1.什么事推荐算法2.什么是基于邻域的推荐算法笔者选⽤的是GroupLens的MoviesLens数据传送门数据集处理此处截取数据 UserId + MovieId 作为隐反馈数据。
个⼈的实现⽅式并不是很好,之后再考虑优化,如果有好的想法欢迎⼩纸条。
基本设置项⽬结构如下:/project/analyzer --推荐分析-CollaborativeFileringanalyzer/bean --数据元组-BasicBean-HabitsBean/input --输⼊设置-ReaderFormat/recommender --推荐功能-UserRecommender⾸先思路是截取MovieLens数据,转化为格式化的书籍格式。
MovieLens数据基本格式为| user id | item id | rating | timestamp |读取后的数据为表结构,实际可以⽤ Map 或者⼆维数组进⾏存储。
考虑到之后转化的问题,决定⽤⼆维数组。
设置BasicBean⽤于存储表结构中的⾏,主要设置List < String >⽤于存储⼀⾏数据中的单项数据/*** A row of data sets describes in witch the parameters are included.** @author wqd* 2016/01/18*/public class BasicBean {private List<String> parameters;// private int num;private boolean tableHead;///Default constructor,the row set n floders and is or not a table headpublic BasicBean(boolean head) {parameters = new ArrayList<String>();this.tableHead = head;}//Default constructor,the row set table head and how much the row//set is defined by the variable parameters,it isn't a table headpublic BasicBean(String... strings) {this(false, strings);}//Default constructor,the row set table head and how much the row//set is defined by the variable parameters and is or not a table headpublic BasicBean(boolean head, String... strings) {parameters = new ArrayList<String>();for(String string : strings) {parameters.add(string);}// this.num = parameters.size();this.tableHead = head;}public int add(String param) {parameters.add(param);return this.getSize();}//replace a parameter value pointed to a new value//If success,return true.If not,return false.public boolean set(int index, String param) {if(index < this.getSize())parameters.set(index, param);elsereturn false;return true;}//Get the head.If it has table head,return ture.//If not,return flase;public boolean isHead() {return tableHead;}//Override toString()public String toString() {StringBuilder str = new StringBuilder(" ");int len = 1;for (String string : parameters) {str.append("\t|" + string);if(len++ % 20 == 0)str.append("\n");}return str.toString();}//Get number of parameterspublic int getSize() {return parameters.size();}//Get arraypublic List<String> getArray() {return this.parameters;}//Get ID of a setpublic int getId() {return this.getInt(0);}public String getString(int index) {return parameters.get(index);}public int getInt(int index) {return Integer.valueOf(parameters.get(index));}public boolean getBoolean(int index) {return Boolean.valueOf(parameters.get(index));}public float getFloat(int index) {return Float.valueOf(parameters.get(index));}}在原数据读取之后,数据处理的话效率还是⽐较差,冗余字段⽐较多,因为⼀个⽤户会对多个电影反馈数据。
推荐系统是一种根据用户的兴趣和行为数据来推荐个性化信息的技术。
协同过滤算法是其中一种重要的推荐算法,它通过对用户行为的比较与分析,找出与当前用户兴趣相似的其他用户或物品,从而实现个性化推荐。
首先,协同过滤算法可以分为基于用户的协同过滤和基于物品的协同过滤两种形式。
基于用户的协同过滤是通过计算不同用户之间的相似度来进行推荐,而基于物品的协同过滤则是通过计算不同物品之间的相似度来进行推荐。
其次,协同过滤算法的核心是相似度计算。
在基于用户的协同过滤中,可以使用余弦相似度或皮尔逊相似度等方法来度量用户之间的相似程度。
而在基于物品的协同过滤中,可以使用Jaccard相似度或余弦相似度等方法来度量物品之间的相似程度。
进一步地,相似度计算完成后,可以利用相似度矩阵来计算用户对未评分物品的喜好程度。
基于用户的协同过滤可以通过加权求和的方法,将相似用户对未评分物品的评分进行预测。
而基于物品的协同过滤可以通过计算用户已评分物品与未评分物品的相似度加权平均,得到用户对未评分物品的预测评分。
此外,协同过滤算法还存在一些问题,如数据稀疏性和冷启动问题。
数据稀疏性指的是用户评分数据的稀疏性,导致无法计算出准确的相似度。
冷启动问题指的是对于新用户或新物品没有足够的历史数据进行推荐。
为了解决这些问题,可以采用一些改进的协同过滤算法。
例如,可以利用社交网络数据或用户标签数据来增强用户的相似度计算。
此外,可以引入内容过滤来解决冷启动问题,将用户的个人信息和物品的内容进行匹配,进行推荐。
总而言之,协同过滤算法是推荐系统中一种重要的个性化推荐算法。
通过对用户行为的比较与分析,找出与当前用户兴趣相似的其他用户或物品,从而实现个性化推荐。
虽然协同过滤算法存在一些问题,但可以通过改进的方法来解决。
未来,随着数据采集和处理技术的不断发展,协同过滤算法也将得到进一步的优化和应用。
基于协同过滤算法实现选课推荐系统1.系统功能1、⽤户账户管理2、学⽣个⼈信息的查看与修改3、学⽣的⽹上选课与课程的评分4、教师个⼈信息的查看与修改5、教师对学⽣课程评价结果的查看6、管理员对学⽣信息与教师信息的查看与添加7、管理员对课程的增删改查8、管理员对课程评价结果的统计与删除。
9、根据学⽣对课程评分的⾼低,在学⽣选课时进⾏推荐。
2、推荐算法的实现思路欧⽒距离相似性度量在数学中,欧⼏⾥得距离或欧⼏⾥得度量是欧⼏⾥得空间中两点间“普通”(即直线)距离。
使⽤这个距离,欧⽒空间成为度量空间。
相关联的范数称为欧⼏⾥得范数。
⼆维空间的公式基于⽤户的协同过滤算法基于⼀个这样的假设“跟你喜好相似的⼈喜欢的东西你也很有可能喜欢。
”所以基于⽤户的协同过滤主要的任务就是找出⽤户的最近邻居,从⽽根据最近邻居的喜好做出未知项的评分预测。
这种算法主要分为3个步骤:1. ⽤户评分可以分为显性评分和隐形评分两种。
显性评分就是直接给项⽬评分(例如⽤户对电影评分),隐形评分就是通过评价或是购买的⾏为给项⽬评分(例如淘宝上购买东西或者评论)。
2. 寻找最近邻居这⼀步就是寻找与你距离最近的⽤户,测算距离⼀般采⽤以下三种算法:余弦定理相似性度量、欧⽒距离相似度度量和杰卡德相似性度量。
后⾯的demo会以欧⽒距离相似度度量进⾏说明。
3. 推荐产⽣了最近邻居集合后,就根据这个集合对未知项进⾏评分预测。
把评分最⾼的N个项推荐给⽤户。
这种算法存在性能上的瓶颈,当⽤户数越来越多的时候,寻找最近邻居的复杂度也会⼤幅度的增长。
参考:package cn.ltysyn.task;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import java.util.ArrayList;import java.util.Collections;import parator;import java.util.HashMap;import java.util.List;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.annotation.Scheduled;import ponent;import cn.ltysyn.bean.Course;import cn.ltysyn.bean.Student;import cn.ltysyn.service.ICourseService;import cn.ltysyn.service.IElectiveService;import cn.ltysyn.service.IRecommendService;import cn.ltysyn.service.IStudentService;@Componentpublic class MyCFRecomment {//获取学⽣编号@Autowiredprivate IStudentService studentService;//获取课程信息@Autowiredprivate ICourseService courseService;//获取评分的信息@Autowiredprivate IElectiveService electiveService;@Autowiredprivate IRecommendService iRecommendService;// //创建⽤户信息// //private List<Integer> stuList = new ArrayList<Integer>();// private static int[] stuArr = {1,2,3};// //创建课程信息// private static int[] couArr = {10,20,30};// //创建评分的集合(学⽣ id ,分数集合)// private static Map<Integer,List<CourtsGoal>> goalMap = new HashMap<Integer, List<CourtsGoal>>();@Scheduled(cron = "0 0/10 * * * ?")public void recommend() {//获取到所有的学⽣List<Student> selectAllStudent = studentService.selectAllStudent();//获取所有的课程//获取评分信息根据学⽣id 和课程id 获取评分信息if(selectAllStudent.size()!=0) {Map<Integer,List<CourtsGoal>> goalMap = new HashMap<Integer, List<CourtsGoal>>();List<Integer> stuList = new ArrayList<Integer>();List<Course> selectAllCourse = (List<Course>) courseService.selectAllCourse();for(Student stu:selectAllStudent) {List<CourtsGoal> courtsGoals = new ArrayList<CourtsGoal>();for(Course cou:selectAllCourse) {CourtsGoal courtsGoal = new CourtsGoal();Integer goal = electiveService.selectByStuAndCourseId(stu.getStuId(),cou.getCourseId());courtsGoal.setCourtsId(cou.getCourseId());courtsGoal.setGoal(goal);courtsGoals.add(courtsGoal);}//获取到学⽣与课程评分的关系数据goalMap.put(stu.getStuId(), courtsGoals);stuList.add(stu.getStuId());}System.out.println(goalMap);//System.out.println(selectAllCourse);//计算⽤户相似度Map<Integer,List<List<Object>>> dataMap = calcUserSimilarity(stuList.toArray(),goalMap);//计算课程的推荐度Map<Integer, List<Object>> recommendCourse = calcRecommendCourse(dataMap,goalMap);//处理推荐电影列表Map<Integer, List<Object>> handleRecommendCourse = handleRecommendCourse(recommendCourse,goalMap);//删除所有推荐列表信息delectAllRecommendCourse();//保存推荐列表信息saveRecommendCourse(handleRecommendCourse);//删除重复的推荐信息//repeatRecomendCourse();}else {}}private void repeatRecomendCourse() {// TODO Auto-generated method stubiRecommendService.repeatRecomendCourse();}private void delectAllRecommendCourse() {// TODO Auto-generated method stubiRecommendService.delectAllRecommendCourse();}private void saveRecommendCourse(Map<Integer, List<Object>> handleRecommendCourse) {// TODO Auto-generated method stubiRecommendService.saveRecommendCourse(handleRecommendCourse);}/** public static void main(String[] args) { System.out.println(goalMap);* //计算⽤户相似度 Map<Integer,List<List<Object>>> dataMap =* calcUserSimilarity(stuArr,goalMap); //计算课程的推荐度 Map<Integer, List<Object>>* recommendCourse = calcRecommendCourse(dataMap,goalMap); //处理推荐电影列表* handleRecommendCourse(recommendCourse,goalMap); }*/private static Map<Integer, List<Object>> handleRecommendCourse(Map<Integer, List<Object>> recommendCourse,Map<Integer,List<CourtsGoal>> goalMap) { Map<Integer, List<Object>> handleRecommendCourse = new HashMap<Integer, List<Object>>();for(Map.Entry<Integer,List<Object>> reco:recommendCourse.entrySet()) {//拿到推荐列表List<Object> re_l = reco.getValue();List<Object> handleCourse = new ArrayList<Object>();for(Object obj:re_l) {List<CourtsGoal> list = goalMap.get(reco.getKey());for(CourtsGoal c_goal:list) {if(Integer.parseInt(obj.toString())==c_goal.getCourtsId()) {if(c_goal.getGoal()==0) {handleCourse.add(c_goal.getCourtsId());}}}}handleRecommendCourse.put(reco.getKey(), handleCourse);}System.out.println("最终推荐列表"+handleRecommendCourse);return handleRecommendCourse;}/** 计算⽤户相似度* 返回最相近的两个*/public static Map<Integer,List<List<Object>>> calcUserSimilarity(Object[] stuArr_p,Map<Integer,List<CourtsGoal>> goalMap_p) {//similarityUsers=new ArrayList();//遍历学⽣求出当前学⽣与其他学⽣的相似度//相似⽤户集合Map<Integer,List<List<Object>>> dataMap = new HashMap<Integer, List<List<Object>>>();for(Object stu:stuArr_p) {//取两个相似的List<List<Object>> similarityUsers= new ArrayList();List<List<Object>> userSimilaritys=new ArrayList<List<Object>>();//遍历goalMap_pfor(Map.Entry<Integer,List<CourtsGoal>> goal:goalMap_p.entrySet()) {//如果当前的学⽣和存储的 key相等则跳过if(stu.toString().equals(goal.getKey().toString())) {continue;}List<Object> userSimilarity=new ArrayList<Object>();//记录当前的学⽣编号userSimilarity.add(goal.getKey());userSimilarity.add(calcTwoUserSimilarity(goal.getValue(),goalMap_p.get((Integer)stu)));userSimilaritys.add(userSimilarity);}sortCollection(userSimilaritys);System.out.println("与"+stu+"的相似度为:"+userSimilaritys);similarityUsers.add(userSimilaritys.get(0));similarityUsers.add(userSimilaritys.get(1));dataMap.put((Integer)stu, similarityUsers);}System.out.println(dataMap);//表⽰该学⽣与其他两个学⽣的相似度为多少return dataMap;}/*** 获取全部推荐课程,计算平均课程推荐度*/private static Map<Integer,List<Object>> calcRecommendCourse(Map<Integer,List<List<Object>>> dataMap,Map<Integer,List<CourtsGoal>> goalMap){Map<Integer,List<List<Object>>> cf_map = new HashMap<Integer, List<List<Object>>>();//存储没有课程的总的推荐分数Map<Integer,Double> cf_sumRate = new HashMap<Integer, Double>();//遍历dataMap 分别拿到不同的学⽣推荐的课程for(Map.Entry<Integer,List<List<Object>>> data:dataMap.entrySet()) {double recommdRate=0,sumRate=0;//拿到的是哪个⽤户第⼀个//data.getValue().get(0).get(0);//拿到该⽤户的相识度值第⼀个double xs_1 = Double.parseDouble(data.getValue().get(0).get(1).toString());//拿到的是哪个⽤户第⼆个//data.getValue().get(1).get(0);//拿到该⽤户的相识度值第⼆个double xs_2 = Double.parseDouble(data.getValue().get(1).get(1).toString());List<CourtsGoal> list_1 = goalMap.get(data.getValue().get(0).get(0));List<CourtsGoal> list_2 = goalMap.get(data.getValue().get(1).get(0));if(list_1.size()==list_2.size()) {List<List<Object>> recommendCourts = new ArrayList<List<Object>>();for(int i=0;i<list_1.size();i++) {List<Object> recommendCourt=new ArrayList();recommdRate = list_1.get(i).getGoal() * xs_1 + list_2.get(i).getGoal() * xs_2;//添加课程recommendCourt.add(list_1.get(i).getCourtsId());//添加该课程推荐度recommendCourt.add(recommdRate);//被推荐的⽤户、课程、课程的推荐度//System.err.println("⽤户"+data.getKey()+"课程"+list_1.get(i)+":"+recommdRate);recommendCourts.add(recommendCourt);sumRate+=recommdRate;}cf_map.put(data.getKey(), recommendCourts);cf_sumRate.put(data.getKey(), sumRate);}//for(CourtsGoal cGoal:list_1) {//System.out.println("给⽤户"+data.getKey()+"推荐的⽤户是:"+data.getValue().get(0).get(0)+"相似值是:"+data.getValue().get(0).get(1)+"课程信息"+cGoal.getCourtsId()+"评分"+cGoal.getGoal()); //}}System.err.println(cf_map);System.out.println(cf_sumRate);//当前集合存放的是给 key 推荐的课程集合Map<Integer,List<Object>> target_map = new HashMap<Integer, List<Object>>();for(Map.Entry<Integer,List<List<Object>>> cf_d:cf_map.entrySet()) {List<Object> targetRecommendCourts = new ArrayList<Object>();for(List<Object> obj:cf_d.getValue()) {if(Double.parseDouble(obj.get(1).toString()) > cf_sumRate.get(cf_d.getKey())/cf_d.getValue().size()){ //⼤于平均推荐度的商品才有可能被推荐targetRecommendCourts.add(obj.get(0));}}target_map.put(cf_d.getKey(), targetRecommendCourts);}System.out.println("最终:"+target_map);return target_map;}/*** 根据⽤户数据,计算⽤户相似度(欧⽒距离)* @param user1Stars 其他⽤户评价分数* @param user2Starts 当前⽤户评价的分数* @return*/private static double calcTwoUserSimilarity(List<CourtsGoal> user1Stars,List<CourtsGoal> user2Starts){ float sum=0;for(int i=0;i<user1Stars.size();i++){sum+=Math.pow(user1Stars.get(i).getGoal()-user2Starts.get(i).getGoal(),2);//平⽅}return Math.sqrt(sum);//开⽅}/*** 集合排序* @param list*/private static void sortCollection(List<List<Object>> list){Collections.sort(list, new Comparator<List<Object>>() {@Overridepublic int compare(List<Object> o1, List<Object> o2) {if(Double.valueOf(o1.get(1).toString()) > Double.valueOf(o2.get(1).toString())){return 1;}else if(Double.valueOf(o1.get(1).toString()) < Double.valueOf(o2.get(1).toString())){return -1;}else{return 0;}}});}}系统功能截图等。
基于协同过滤的网页推荐系统设计与实现随着互联网的快速发展,网页的数量与日俱增,用户在大量的网页中寻找自己感兴趣的内容变得困难起来。
因此推荐系统成为了解决这一问题的有效方式。
推荐系统可以根据用户的历史行为,为用户推荐更符合他们兴趣的网页。
其中基于协同过滤的推荐算法是被广泛使用的一种,本文将基于这一算法,探讨如何建立一个高效的网页推荐系统。
一、协同过滤算法协同过滤算法能够发现用户之间的相似性,基于用户的历史行为来预测用户的未来行为。
常见的协同过滤算法包括用户-物品协同过滤和物品-物品协同过滤。
用户-物品协同过滤是通过对用户的历史行为和他们的偏好进行分析,并寻找与之相似的其他用户,来为用户建议他们可能感兴趣的网页。
物品-物品协同过滤则是通过找到与用户已经喜欢的网页相关联的其他网页,并将这些信息进行汇总,直接为用户推荐相似的内容。
二、建立基于协同过滤推荐系统的步骤1. 数据收集与清洗建立一个好的推荐系统需要有足够多的数据。
数据来源可以是用户行为记录,包括用户浏览记录、购买行为、评分记录等。
这些数据需要进行清洗和去重后,才能够被使用。
2. 数据存储系统需要将清洗后的数据存储到数据库中,以便于后续计算使用。
常用的数据存储包括MySQL,MongoDB等。
3. 特征提取在数据存储之后,需要对数据进行深入的分析,以确定不同用户行为之间的相似性,以便于进行推荐。
这个过程叫做特征提取。
特征提取可以采用多余数据分析工具,比如说Python中的numpy和pandas等。
一般而言,我们会提取出几个比较重要的特征,比如点击次数、购买次数等,并综合使用这些特征来为用户推荐网页。
4. 计算相似性在确定了用户的兴趣指向后,我们需要寻找和他们行为相似的其他用户/网页。
这一步通常是用来计算相似性。
我们可以利用相关性分析法来计算用户和网页之间的相似性。
使得推荐的网页很可能与用户已经看过的网页存在一定的相关性,从而提高了推荐的准确度。
实现推荐系统:基于内容和协同过滤的算法推荐系统在当今的电子商务和社交媒体等平台上扮演着重要的角色。
它能够帮助用户快速发现自己感兴趣的内容和产品,提高用户体验和平台的粘性,同时也为平台的营销和推广带来了很大的价值。
基于内容和协同过滤的算法是目前主流的推荐系统算法,本文将深入探讨这两种算法的原理、特点和应用,并对它们进行比较和分析。
一、推荐系统概述推荐系统是一种利用算法为用户推荐商品、内容或者服务的系统。
通过分析用户的历史行为和兴趣,推荐系统能够为用户提供个性化、精准的推荐,帮助用户发现新的内容和产品,从而提高用户满意度和消费转化率。
推荐系统主要分为两种类型:基于内容的推荐和协同过滤的推荐。
基于内容的推荐是根据用户对商品或内容的历史喜好,从中挖掘出共同的特性和属性,然后为用户推荐具有相似特性和属性的商品或内容。
而协同过滤的推荐则是通过分析大量用户行为数据,找出具有相似行为模式的用户群体,然后将这些用户喜欢的商品或内容推荐给目标用户。
二、基于内容的推荐算法1.原理基于内容的推荐算法是根据商品或内容的特征和属性,为用户推荐具有相似特征和属性的商品或内容。
它不依赖于用户行为数据,而是直接对商品或内容进行分析和比较,从中挖掘出共同的特性和属性。
2.特点基于内容的推荐算法具有以下特点:(1)理解性强:算法能够直接理解商品或内容的特征和属性,为用户提供符合其兴趣的推荐。
(2)推荐精准:由于推荐是基于商品或内容的特征和属性,所以推荐结果往往更加精准,满足用户的个性化需求。
(3)新颖性差:基于内容的推荐算法往往不会给用户推荐过于新颖或偏离用户兴趣的商品或内容。
3.应用基于内容的推荐算法在电子商务、新闻资讯和社交媒体等平台上有着广泛的应用。
比如,亚马逊的商品推荐、今日头条的新闻推荐、豆瓣的图书推荐等,都是基于内容的推荐算法实现的。
三、协同过滤的推荐算法1.原理协同过滤的推荐算法是根据用户行为数据,找出具有相似行为模式的用户群体,然后将这些用户喜欢的商品或内容推荐给目标用户。
协同过滤推荐算法(java原生JDK实现-附源码地址)一、项目需求1.需求链接https:///getStart/information.htm?raceId=2315222.需求内容训练数据包含了抽样出来的一定量用户在一个月时间(11.18~12.18)之内的移动端行为数据(D),评分数据是这些用户在这个一个月之后的一天(12.19)对商品子集(P)的购买数据。
参赛者要使用训练数据建立推荐模型,并输出用户在接下来一天对商品子集购买行为的预测结果。
评分数据格式具体计算公式如下:参赛者完成用户对商品子集的购买预测之后,需要将结果放入指定格式的数据表(非分区表)中,要求结果表名为:tianchi_mobile_recommendation_predict.csv,且以utf-8格式编码;包含user_id 和item_id两列(均为string类型),要求去除重复。
例如:评估指标比赛采用经典的精确度(precision)、召回率(recall)和F1值作为评估指标。
具体计算公式如下:其中PredictionSet为算法预测的购买数据集合,ReferenceSet为真实的答案购买数据集合。
我们以F1值作为最终的唯一评测标准。
二、协同过滤推荐算法原理及实现流程1.基于用户的协同过滤推荐算法基于用户的协同过滤推荐算法通过寻找与目标用户具有相似评分的邻居用户,通过查找邻居用户喜欢的项目,推测目标用户也具有相同的喜好。
基于用户的协同过滤推荐算法基本思想是:根据用户-项目评分矩阵查找当前用户的最近邻居,利用最近邻居的评分来预测当前用户对项目的预测值,将评分最高的N 个项目推荐给用户,其中的项目可理解为系统处理的商品。
其算法流程图如下图1所示。
基于用户的协同过滤推荐算法流程为:●构建用户项目评分矩阵R={r1,r2……r m},T:m×n的用户评分矩阵,其中r={r i,1,r i,2,……,r i,n}为用户U i的评分向量,R i,j代表用户U i对项目I j的评分。
●计算用户相似度基于用户的协同过滤推荐算法,需查找与目标用户相似的用户。
衡量用户之间的相似性需要计算每个用户的评分与其他用户评分的相似度,即评分矩阵中的用户评分记录。
每个用户对项目的评分可以看作是一个n维的评分向量。
使用评分向量计算目标用户U i与其他用户U j之间的相似度sim(i,j),通常计算用户相似度的方法有三种:余弦相似度、修正的余弦相似度和皮尔森相关系数。
●构建最近邻居集最近邻居集Neighor(u)中包含的是与目标用户具有相同爱好的其他用户。
为选取邻居用户,我们首先计算目标用户u 与其他用户v的相似度sim(u,v),再选择相似度最大的k个用户。
用户相似度可理解为用户之间的信任值或推荐权重。
通常,sim(u,v)∈[1,1]。
用户相似度为1表示两个用户互相的推荐权重很大。
如果为-1,表示两个用户的由于兴趣相差很大,因此互相的推荐权重很小。
● 预测评分计算用户a 对项目i 的预测评分 p(a,i)为邻居用户对该项目评分的加权评分值。
显然,不同用户对于目标用户的影响程度不同,所以在计算预测评分时,不同用户有不同的权重。
计算时,我们选择用户相似度作为用户的权重因子,计算公式如下:p(a,i)=⎺R i +(R b ,i −⎺R b )×sim (a,b)b∈Neighor (u ) |sim (a,b)|b∈Neighor (1)基于用户的协同过滤推荐算法实现步骤为: ● 实时统计user 对item 的打分,从而生成user-item表(即构建用户-项目评分矩阵);● 计算各个user 之间的相似度,从而生成user-user的得分表,并进行排序; ● 对每一user 的item 集合排序;● 针对预推荐的user ,在user-user 的得分表中选择与该用户最相似的N 个用户,并在user-item 表中选择这N 个用户中已排序好的item 集合中的topM ; ● 此时的N*M 个商品即为该用户推荐的商品集。
2. 基于项目的协同过滤推荐算法基于项目的协同过滤推荐算法依据用户-项目评分矩阵通过计算项目之间的评分相似性来衡量项目评分相似性,找到与目标项目最相似的n 个项目作为最近邻居集。
然后通过对目标项目的相似邻居赋予一定的权重来预测当前项目的评分,再将得到的最终预测评分按序排列,将评分最高的N 个项目推荐给当前用户,其中的项目可理解为系统处理的商品。
其算法流程如下图2所示。
基于项目的协同过滤推荐算法流程为:首先,读取目标用户的评分记录集合I u ;然后计算项目i 与I u 中其他项目的相似度,选取k 个最近邻居;根据评分相似度计算公式计算候选集中所有项目的预测评分;最后选取预测评分最高的N 个项目推荐给用户。
基于项目的协同过滤推荐算法预测评分与其他用户评分的加权评分值相关,不同的历史评分项目与当前项目i 的相关度有差异,所以在进行计算时,不同的项目有不同的权重。
评分预测函数p(u,i),以项目相似度作为项目的权重因子,得到的评分公式如下:p(u,i)=⎺R u +(R u ,j −⎺R u )×sim (i,j)j ∈I u |sim (i,j)|j ∈I u (2)基于项目的协同过滤推荐算法实现步骤为: ● 实时统计user 对item 的打分,从而生成user-item表(即构建用户-项目评分矩阵);● 计算各个item 之间的相似度,从而生成item-item的得分表,并进行排序; ● 对每一user 的item 集合排序;● 针对预推荐的user ,在该用户已选择的item 集合中,根据item-item表选择与已选item最相似的N个item;此时的N个商品即为该用户推荐的商品集。
3.基于用户的协同过滤推荐算法与基于项目的协同过滤推荐算法比较基于用户的协同过滤推荐算法:可以帮助用户发现新的商品,但需要较复杂的在线计算,需要处理新用户的问题。
基于项目的协同过滤推荐算法:准确性好,表现稳定可控,便于离线计算,但推荐结果的多样性会差一些,一般不会带给用户惊喜性。
三、项目实现针对移动推荐,我们选择使用基于用户的协同过滤推荐算法来进行实现。
1.数据模型及其实体类用户行为数据:(user.csv)user_id,item_id,behavior_type,user_geohash,item_category,time10001082,285259775,1,97lk14c,4076,2014-12-08 1810001082,4368907,1,,5503,2014-12-12 1210001082,4368907,1,,5503,2014-12-12 1210001082,53616768,1,,9762,2014-12-02 1510001082,151466952,1,,5232,2014-12-12 1110001082,53616768,4,,9762,2014-12-02 1510001082,290088061,1,,5503,2014-12-12 1210001082,298397524,1,,10894,2014-12-12 1210001082,32104252,1,,6513,2014-12-12 1210001082,323339743,1,,10894,2014-12-12 12商品信息:(item.csv)item_id,item_geohash,item_category100002303,,3368100003592,,7995100006838,,12630100008089,,7791100012750,,9614100014072,,1032100014463,,9023100019387,,3064100023812,,6700package entity;publicclass Item {private String itemId;private String itemGeoHash;private String itemCategory;public String getItemId() {return itemId;}publicvoid setItemId(String itemId) {this.itemId = itemId;}public String getItemGeoHash() {return itemGeoHash;}publicvoid setItemGeoHash(String itemGeoHash) { this.itemGeoHash = itemGeoHash;}public String getItemCategory() {return itemCategory;}publicvoid setItemCategory(String itemCategory) { this.itemCategory = itemCategory;}}package entity;publicclass Score implements Comparable<Score> { private String userId; // 用户标识private String itemId; // 商品标识privatedouble score;public String getUserId() {return userId;}publicvoid setUserId(String userId) {erId = userId;}public String getItemId() {return itemId;}publicvoid setItemId(String itemId) {this.itemId = itemId;}publicdouble getScore() {return score;}publicvoid setScore(double score) {this.score = score;}@Overridepublicint compareTo(Score o) {if ((this.score - o.score) < 0) {return 1;}elseif ((this.score - o.score) > 0) {return -1;}else {return 0;}}}package entity;publicclass User implements Comparable<User> {private String userId; // 用户标识private String itemId; // 商品标识privateint behaviorType; // 用户对商品的行为类型,可以为空,包括浏览、收藏、加购物车、购买,对应取值分别是1、2、3、4.private String userGeoHash; // 用户位置的空间标识private// 商品分类标识private String time; // 行为时间privateint count;privatedouble weight; // 权重public String getUserId() {return userId;}publicvoid setUserId(String userId) {erId = userId;}public String getItemId() {return itemId;}publicvoid setItemId(String itemId) {this.itemId = itemId;}publicint getBehaviorType() {return behaviorType;}publicvoid setBehaviorType(int behaviorType) {this.behaviorType = behaviorType;}public String getUserGeoHash() {return userGeoHash;}publicvoid setUserGeoHash(String userGeoHash) {erGeoHash = userGeoHash;}public String getItemCategory() {return itemCategory;}publicvoid setItemCategory(String itemCategory) {this.itemCategory = itemCategory;}public String getTime() {return time;}publicvoid setTime(String time) {this.time = time;}publicint getCount() {return count;}publicvoid setCount(int count) {this.count = count;}publicdouble getWeight() {return weight;}publicvoid setWeight(double weight) {this.weight = weight;}@Overridepublicint compareTo(User o) {return (int)((-1) * (this.weight - o.weight));}}2.工具类文件处理工具:package util;public class FileTool {public static FileReader fr=null;public static BufferedReader br=null;public static String line=null;public static FileOutputStream fos1 = null,fos2 = null,fos3 = null; public static PrintStream ps1 = null,ps2 = null,ps3 = null;public static int count = 0;/*** 初始化写文件器(单一指针)* */public static void initWriter1(String writePath) {try {fos1 = new FileOutputStream(writePath);ps1 = new PrintStream(fos1);} catch (FileNotFoundException e) {e.printStackTrace();}}/*** 关闭文件器(单一指针)* */public static void closeRedaer() {try {br.close();fr.close();} catch (IOException e) {e.printStackTrace();}}/*** 关闭文件器(单一指针)* */public static void closeWriter1() {try {ps1.close();fos1.close();} catch (IOException e) {e.printStackTrace();}}/*** 初始化写文件器(双指针)* */public static void initWriter2(String writePath1,String writePath2) { try {fos1 = new FileOutputStream(writePath1);ps1 = new PrintStream(fos1);fos2 = new FileOutputStream(writePath2);ps2 = new PrintStream(fos2);} catch (FileNotFoundException e) {e.printStackTrace();}}/*** 关闭文件器(双指针)* */public static void closeWriter2() {try {ps1.close();fos1.close();ps2.close();fos2.close();} catch (IOException e) {e.printStackTrace();}}/*** 初始化写文件器(三指针)* */public static void initWriter3(String writePath1,String writePath2,String writePath3) { try {fos1 = new FileOutputStream(writePath1);ps1 = new PrintStream(fos1);fos2 = new FileOutputStream(writePath2);ps2 = new PrintStream(fos2);fos3 = new FileOutputStream(writePath3);ps3 = new PrintStream(fos3);} catch (FileNotFoundException e) {e.printStackTrace();}}/*** 关闭文件器(三指针)* */public static void closeWriter3() {try {ps1.close();fos1.close();ps2.close();fos2.close();ps3.close();fos3.close();} catch (IOException e) {e.printStackTrace();}}public static List readFileOne(String path,boolean isTitle,String token,String pattern) throws Exception {List<Object> ret = new ArrayList<Object>();fr = new FileReader(path);br = new BufferedReader(fr);int count = 0,i = 0;if (isTitle) {line = br.readLine();count++;}while((line = br.readLine()) != null){String[] strArr = line.split(token);switch (pattern) {case "item":ret.add(ParseTool.parseItem(strArr));break;case "user":ret.add(ParseTool.parseUser(strArr));break;case "score":ret.add(ParseTool.parseScore(strArr));default:ret.add(line);break;}count++;if (count/100000 == 1) {i++;System.out.println(100000*i);count = 0;}}closeRedaer();return ret;}public static void makeSampleData(String inputPath,boolean isTitle,String outputPath,int threshold) throws Exception {fr = new FileReader(inputPath);br = new BufferedReader(fr);initWriter1(outputPath);if (isTitle) {line = br.readLine();}int count = 0;while((line = br.readLine()) != null){ps1.println(line);count++;if (count == threshold) {break;}}closeRedaer();}public static List<String>traverseFolder(String dir) {File file = new File(dir);String[] fileList = null;if (file.exists()) {fileList = file.list();}List<String> list = new ArrayList<String>();for(String path : fileList){list.add(path);}return list;}public static Map<String, List<Score>>loadScoreMap(String path,boolean isTitle,String token) throws Exception {fr = new FileReader(path);br = new BufferedReader(fr);if (isTitle) {line = br.readLine();}Map<String, List<Score>> scoreMap = new HashMap<String, List<Score>>();while((line = br.readLine()) != null){String[] arr = line.split(token);Score score = ParseTool.parseScore(arr);List<Score> temp = new ArrayList<Score>();if (scoreMap.containsKey(score.getUserId())) {temp = scoreMap.get(score.getUserId());}temp.add(score);scoreMap.put(score.getUserId(), temp);}closeRedaer();return scoreMap;}public static Map<String, List<String>>loadPredictData(String path,boolean isTitle,String token) throws Exception {fr = new FileReader(path);br = new BufferedReader(fr);if (isTitle) {line = br.readLine();}Map<String, List<String>> map = new HashMap<String, List<String>>();while((line = br.readLine()) != null){String[] arr = line.split(token);String userId = arr[0];String itemId = arr[1];List<String> temp = new ArrayList<String>();if (map.containsKey(userId)) {temp = map.get(userId);}temp.add(itemId);map.put(userId, temp);count++;}closeRedaer();return map;}public static Map<String, List<String>>loadTestData(Map<String, List<String>> predictMap, String dir, boolean isTitle, String token) throws Exception {List<String> fileList = traverseFolder(dir);Set<String> predictKeySet = predictMap.keySet();Map<String, List<String>> testMap = new HashMap<String, List<String>>();for(String predictKey : predictKeySet){if (fileList.contains(predictKey)) {List<String> itemList = loadTestData(dir + predictKey, isTitle, token);testMap.put(predictKey, itemList);}}return testMap;}public static List<String>loadTestData(String path, boolean isTitle, String token) throws Exception {fr = new FileReader(path);br = new BufferedReader(fr);if (isTitle) {line = br.readLine();}List<String> list = new ArrayList<String>();Set<String> set = new HashSet<String>();while((line = br.readLine()) != null){String[] arr = line.split(token);set.add(arr[1]);count++;}closeRedaer();for(String item : set){list.add(item);}return list;}public static Map<String, Double> loadUser_ItemData(String path,boolean isTitle,String token) throws Exception {fr = new FileReader(path);br = new BufferedReader(fr);if (isTitle) {line = br.readLine();}Map<String, Double> map = new HashMap<String, Double>();while((line = br.readLine()) != null){String[] arr = line.split(token);String itemId = arr[1];double score = Double.valueOf(arr[2]);if(map.containsKey(itemId)){double temp = map.get(itemId);if (temp > score) {score = temp;}}map.put(itemId, score);}closeRedaer();return map;}public static Map<String, Set<String>>loadTestUser(String path,boolean isTitle,String token) throws Exception {fr = new FileReader(path);br = new BufferedReader(fr);int count = 0,i = 0;if (isTitle) {line = br.readLine();count++;}Map<String, Set<String>> map = new HashMap<String, Set<String>>();while((line = br.readLine()) != null){String[] arr = line.split(token);String userId = arr[0];String itemId = arr[1];Set<String> set = new HashSet<String>();if (map.containsKey(userId)) {set = map.get(userId);set.add(itemId);}map.put(userId, set);count++;if (count/100000 == 1) {i++;System.out.println(100000*i);count = 0;}}closeRedaer();return map;}}解析工具:package util;public class ParseTool {//判断是否为数字public static boolean isNumber(String str) {int i,n;n = str.length();for(i = 0;i < n;i++){if (!Character.isDigit(str.charAt(i))) {return false;}}return true;}public static Item parseItem(String[] contents) {Item item = new Item();if (contents[0] != null && !contents[0].isEmpty()) {item.setItemId(contents[0].trim());}if (contents[1] != null && !contents[1].isEmpty()) {item.setItemGeoHash(contents[1].trim());}if (contents[2] != null && !contents[2].isEmpty()) {item.setItemCategory(contents[2].trim());}return item;}public static User parseUser(String[] contents) {User user = new User();int n = contents.length;if (contents[0] != null && !contents[0].isEmpty()) {user.setUserId(contents[0].trim());}if (contents[1] != null && !contents[1].isEmpty()) {user.setItemId(contents[1].trim());}/*// 2.调用CountFileTest需放开,其它需注释if (contents[2] != null && !contents[2].isEmpty()) {user.setBehaviorType(Integer.valueOf(contents[2].trim()));}// 2.调用CountFileTest需放开,其它需注释if (contents[n-1] != null && !contents[n-1].isEmpty()) {user.setCount(Integer.valueOf(contents[n-1].trim()));}*/// 3.调用PredictTest需放开,其它需注释if (contents[n-1] != null && !contents[n-1].isEmpty()) {user.setWeight(Double.valueOf(contents[n-1].trim()));}/*// 1.调用SpliteFileAndMakeScoreTable需放开,其它需注释if (contents[3] != null && !contents[3].isEmpty()) {user.setUserGeoHash(contents[3].trim());}if (contents[4] != null && !contents[4].isEmpty()) {user.setItemCategory(contents[4].trim());}if (contents[5] != null && !contents[5].isEmpty()) {user.setTime(contents[5].trim());}*/return user;}public static Score parseScore(String[] contents) {Score score = new Score();if (contents[0] != null && !contents[0].isEmpty()) {score.setUserId(contents[0].trim());}if (contents[1] != null && !contents[1].isEmpty()) {score.setItemId(contents[1].trim());}if (contents[2] != null && !contents[2].isEmpty()) {score.setScore(Double.parseDouble(contents[2].trim()));}return score;}}3.数据处理模块:package service;public class DataProcess {public static final double[] w = {0,10,20,30};public static void output(Map<String, Map<String, List<User>>> userMap,String outputPath) { for(Entry<String, Map<String, List<User>>> entry : userMap.entrySet()){FileTool.initWriter1(outputPath + entry.getKey());Map<String, List<User>> temp = entry.getValue();for(Entry<String, List<User>> tempEntry : temp.entrySet()){List<User> users = tempEntry.getValue();int count = users.size();for(User user : users){FileTool.ps1.print(user.getUserId() + "\t");FileTool.ps1.print(user.getItemId() + "\t");FileTool.ps1.print(user.getBehaviorType() + "\t");//FileTool.ps1.print(user.getUserGeoHash() + "\t");//FileTool.ps1.print(user.getItemCategory() + "\t");//FileTool.ps1.print(user.getTime() + "\t");FileTool.ps1.print(count + "\n");}}}FileTool.closeWriter1();}public static void output(Map<String, Map<String, Double>> scoreTable, String outputPath, Set<String> userSet, Set<String> itemSet, String token) {FileTool.initWriter1(outputPath);for(String itemId: itemSet){FileTool.ps1.print(token + itemId);}FileTool.ps1.println();for(String userId : userSet){FileTool.ps1.print(userId + token);Map<String, Double> itemMap = scoreTable.get(userId);for(String itemId: itemSet){if(itemMap.containsKey(itemId)){FileTool.ps1.print(itemMap.get(itemId));}else {//FileTool.ps1.print(0);}FileTool.ps1.print(token);}FileTool.ps1.print("\n");}}public static void outputUser(List<User> userList) {for(User user : userList){FileTool.ps1.println(user.getUserId() + "\t" + user.getItemId() + "\t" + user.getWeight());}}public static void outputScore(List<Score> scoreList) {for(Score score : scoreList){FileTool.ps1.println(score.getUserId() + "\t" + score.getItemId() + "\t" + score.getScore());}}public static void outputRecommendList(Map<String, Set<String>> map) {for(Entry<String, Set<String>> entry : map.entrySet()){String userId = entry.getKey();Set<String> itemSet = entry.getValue();for(String itemId : itemSet){FileTool.ps1.println(userId + "," + itemId);}}}public static void output(Map<String, Set<String>> map) {for(Entry<String, Set<String>> entry : map.entrySet()){String userId = entry.getKey();Set<String> set = entry.getValue();for(String itemId : set){FileTool.ps1.println(userId + "\t" + itemId);}}}public static Map<String, Map<String, List<User>>> mapByUser(List<User>userList,Set<String> userSet,Set<String> itemSet) {Map<String, Map<String, List<User>>> userMap = new HashMap<>();for(User user: userList){Map<String, List<User>> tempMap = new HashMap<String, List<User>>();List<User> tempList = new ArrayList<User>();if (!userMap.containsKey(user.getUserId())) {}else {tempMap = userMap.get(user.getUserId());if (!tempMap.containsKey(user.getItemId())) {}else {tempList = tempMap.get(user.getItemId());}}tempList.add(user);tempMap.put(user.getItemId(), tempList);userMap.put(user.getUserId(), tempMap);userSet.add(user.getUserId());itemSet.add(user.getItemId());}return userMap;}public static Map<String, Map<String, Double>>makeScoreTable(Map<String, Map<String, List<User>>> userMap) {Map<String, Map<String, Double>> scoreTable = new HashMap<String, Map<String,Double>>();for(Entry<String, Map<String, List<User>>> userEntry : userMap.entrySet()){Map<String, List<User>> itemMap = userEntry.getValue();String userId = userEntry.getKey();Map<String, Double> itemScoreMap = new HashMap<String, Double>();for(Entry<String, List<User>> itemEntry : itemMap.entrySet()){String itemId = itemEntry.getKey();List<User> users = itemEntry.getValue();double weight = 0.0;int maxType = 0;for(User user : users){if (user.getBehaviorType() > maxType) {maxType = user.getBehaviorType();}}int count = users.size();if (maxType != 0) {weight += w[maxType-1];}weight += count;itemScoreMap.put(itemId, weight);}scoreTable.put(userId, itemScoreMap);}return scoreTable;}public static double calculateWeight(int behaviorType, int count) {double weight = w[behaviorType-1] + count;return weight;}public static List<User> reduceUserByItem(List<User> userList) {List<User> list = new ArrayList<User>();Map<String, User> userMap = new LinkedHashMap<String, User>();for(User user : userList){String itemId = user.getItemId();if (!userMap.containsKey(itemId)) {double weight = calculateWeight(user.getBehaviorType(), user.getCount());user.setWeight(weight);userMap.put(itemId, user);list.add(user);}else {User temp = userMap.get(itemId);if (temp.getBehaviorType() < user.getBehaviorType()) {double weight = calculateWeight(user.getBehaviorType(), user.getCount());user.setWeight(weight);userMap.put(itemId, user);list.add(user);}}}userMap.clear();return list;}public static void sortScoreMap(Map<String, List<Score>> scoreMap) {Set<String> userSet = scoreMap.keySet();for(String userId : userSet){List<Score> temp = scoreMap.get(userId);Collections.sort(temp);scoreMap.put(userId, temp);}}public static Map<String, Set<String>>predict(Map<String, List<Score>> scoreMap, List<String> fileNameList, String userDir,int topNUser,int topNItem) throws Exception {Map<String, Set<String>> recommendList = new HashMap<String, Set<String>>();for(Entry<String, List<Score>> entry : scoreMap.entrySet()){String userId1 = entry.getKey();List<Score> list = entry.getValue();int countUser = 0;Set<String> predictItemSet = new LinkedHashSet<String>();for(Score score : list){String userId2 = score.getItemId();if(fileNameList.contains(userId2)){List<User> userList = FileTool.readFileOne(userDir + userId2, false, "\t", "user");int countItem = 0;for(User user : userList){predictItemSet.add(user.getItemId());countItem++;if (countItem == topNItem) {break;}}countUser++;}if (countUser == topNUser) {break;}}recommendList.put(userId1, predictItemSet);}return recommendList;}public static void prediction(Map<String, List<String>> predictMap,int predictN, Map<String, List<String>> referenceMap, int refN) {int count = 0;for(Entry<String, List<String>> predictEntity : predictMap.entrySet()){String userId = predictEntity.getKey();if (referenceMap.containsKey(userId)) {List<String> predictList = predictEntity.getValue();for(String itemId : predictList){if (referenceMap.get(userId).contains(itemId)) {count++;}}}}double precision = (1.0 * count / predictN) * 100;double recall = (1.0 * count / refN) * 100;double f1 = (2 * precision * recall)/(precision + recall);System.out.println("precision="+precision+",recall="+recall+",f1="+f1);}}4.计算模块package service;public class CalculateSimilarity {public static double EuclidDist(Map<String, Double> userMap1,Map<String, Double> userMap2, Set<String> userSet,Set<String> itemSet) {double sum = 0;for (String itemId : itemSet) {double score1 = 0.0;double score2 = 0.0;if (userMap1.containsKey(itemId) && userMap2.containsKey(itemId)) {score1 = userMap1.get(itemId);score2 = userMap2.get(itemId);} else if (userMap1.containsKey(itemId)) {score1 = userMap1.get(itemId);} else if (userMap2.containsKey(itemId)) {score2 = userMap2.get(itemId);}double temp = Math.pow((score1 - score2), 2);sum += temp;}sum = Math.sqrt(sum);return sum;}public static double CosineDist(Map<String, Double> userMap1,Map<String, Double> userMap2, Set<String> userSet,Set<String> itemSet) {double dist = 0;double numerator = 0; // 分子double denominator1 = 0; // 分母double denominator2 = 0; // 分母for (String itemId : itemSet) {double score1 = 0.0;double score2 = 0.0;if (userMap1.containsKey(itemId) && userMap2.containsKey(itemId)) {numerator++;score1 = userMap1.get(itemId);score2 = userMap2.get(itemId);} else if (userMap1.containsKey(itemId)) {score1 = userMap1.get(itemId);} else if (userMap2.containsKey(itemId)) {score2 = userMap2.get(itemId);}denominator1 += Math.pow(score1, 2);denominator2 += Math.pow(score2, 2);}dist = ((1.0 * numerator) / (Math.sqrt(denominator1) * Math.sqrt(denominator2)));return dist;}public static double execute(Map<String, Double> userMap1,Map<String, Double> userMap2,Set<String> userSet,Set<String> itemSet) {double dist = EuclidDist(userMap1, userMap2, userSet, itemSet);double userScore = 1.0 / (1.0 + dist);// double userScore = CosineDist(userMap1, userMap2, userSet, itemSet);return userScore;}//由于数据已经量化处理并进行脱敏处理,因此这里选用欧式距离计算相似度即可public static void execute(String userId,Map<String, Map<String, Double>> scoreTable,Set<String> userSet, Set<String> itemSet) {for (Entry<String, Map<String, Double>>userEntry : scoreTable.entrySet()) {String userId2 = userEntry.getKey();Map<String, Double> userMap2 = userEntry.getValue();double dist = EuclidDist(scoreTable.get(userId), userMap2, userSet, itemSet);double userScore = 1.0 / (1.0 + dist);// double userScore = CosineDist(userMap1, userMap2, userSet, itemSet);FileTool.ps1.println(userId + "\t" + userId2 + "\t" + userScore);}}public static void execute(Map<String, Map<String, Double>> scoreTable,Set<String> userSet, Set<String> itemSet) {List<Score> similarList = new ArrayList<Score>();for (Entry<String, Map<String, Double>> userEntry1 : scoreTable.entrySet()) {String userId = userEntry1.getKey();execute(userId, scoreTable, userSet, itemSet);}}}5.脚本生成userset和itemset:package script;public class MakeSet {public static void main(String[] args) throws Exception {String inputDir = args[0];String outputDir = args[1];Set<String> userSet = new HashSet<String>();Set<String> itemSet = new HashSet<String>();List<String> pathList = FileTool.traverseFolder(inputDir);for(String path : pathList){String inputPath = inputDir + path;List<User> list = FileTool.readFileOne(inputPath, false, "\t", "user");for(User user : list){userSet.add(user.getUserId());itemSet.add(user.getItemId());}}FileTool.initWriter1(outputDir+"userSet");for(String userId : userSet){FileTool.ps1.println(userId);}FileTool.closeWriter1();FileTool.initWriter1(outputDir+"itemSet");for(String itemId : itemSet){FileTool.ps1.println(itemId);}FileTool.closeWriter1();}}map文件构建user-item评分矩阵并计算user间的相似度生成user-user的得分表:package script;public class SpliteFileAndMakeScoreTable {public static void main(String[] args) throws Exception {//String inputDir = "data/fresh_comp_offline/";//String outputDir = "data/fresh_comp_offline/sample/";//String inputDir = "data/fresh_comp_offline/sample/";//String outputDir = "data/fresh_comp_offline/sample/out/";String inputDir = args[0];String outputDir = args[1];//String userPath = inputDir + "tianchi_fresh_comp_train_user.csv";String userPath = inputDir + args[2];String outputPath = args[3];//String outputPath = outputDir + "user.csv";//FileTool.makeSampleData(userPath, true, outputPath, 10000);//List<Object> itemList = FileTool.readFileOne(itemPath, true, ",", "item");//List<User> userList = FileTool.readFileOne(userPath, false, ",", "user");List<User> userList = FileTool.readFileOne(userPath, false, ",", "user");Set<String> userSet = new HashSet<String>();Set<String> itemSet = new HashSet<String>();Map<String, Map<String, List<User>>> userMap = DataProcess.mapByUser(userList,userSet,itemSet);userList.clear();DataProcess.output(userMap, outputDir);//生成userToItem的打分表Map<String, Map<String, Double>> scoreTable = DataProcess.makeScoreTable(userMap);//DataProcess.output(scoreTable, outputDir + "scoreTable.csv" , userSet, itemSet, ",");userMap.clear();FileTool.initWriter1(outputPath);CalculateSimilarity.execute(scoreTable, userSet, itemSet);FileTool.closeWriter1();。