协同过滤推荐算法(java原生JDK实现-附源码地址)
协同过滤算法
皮尔逊相关度评价
我们选择使用皮尔逊相关度评价来计算多用户与多商品的关系计算。下 面是5个用户对5件商品的评分表。我们通过这些评分计算出商品间的相 关度。
2.2 寻找相似的用户
通过计算5个用户对5件商品的评分我们获得了用户间的相似度数 据。这里可以看到用户A&B, C&D, C&E和D&E之间相似度较高 。下一步, 我们可以依照相似度对用户进行商品推荐。
用户行为 评分 投票 转发
保存书签
类型 显式 显式
特征
作用
整数量化的偏好,可能的取值是 [0, n];n 一般取值为 5 或者是 10
通过用户对物品的评分,可以精确的得到用户的偏好
布尔量化的偏好,取值是 0 或 1
通过用户对物品的投票,可以较精确的得到用户的偏好
显式 布尔量化的偏好,取值是 0 或 1
2.2 寻找相似的用户 (User CF)
我们模拟了5个用户对两件商品的评分, 来说明如何通过用户对不同商品 的态度和偏好寻找相似的用户。在示例中, 5个用户分别对两件商品进行 了评分。这里的分值可能表示真实的购买, 也可以是用户对商品不同行为 的量化指标。例如, 浏览商品的次数, 向朋友推荐商品, 收藏, 分享, 或评 论等等。这些行为都可以表示用户对商品的态度和偏好程度。
点击流
隐式
一组用户的点击,用户对物品感兴趣,需要 进行分析,得到偏好
用户的点击一定程度上反映了用户的注意力,所以它也可以从一定程度上反映用户的喜好。
页面停留时间
隐式
一组时间信息,噪音大,需要进行去噪,分 析,得到偏好
用户的页面停留时间一定程度上反映了用户的注意力和喜好,但噪音偏大,不好利用。
购买
推荐算法:协同过滤算法的介绍
推荐算法:协同过滤算法的介绍⼀、什么是推荐算法互联⽹的出现和普及给⽤户带来了⼤量的信息,满⾜了⽤户在信息时代对信息的需求,但随着⽹络的迅速发展⽽带来的⽹上信息量的⼤幅增长,使得⽤户在⾯对⼤量信息时⽆法从中获得对⾃⼰真正有⽤的那部分信息,对信息的使⽤效率反⽽降低了,这就是所谓的信息超载(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代码引言:在当今互联网时代,个性化推荐系统已经成为了各大电商平台和社交媒体的重要组成部分。
协同过滤算法是个性化推荐系统中常用的一种算法,其主要思想是通过分析用户的历史行为,找到与当前用户最相似的其他用户或物品,从而给用户推荐相关的信息或商品。
本文将介绍基于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实现
【推荐算法】协同过滤算法——基于⽤户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_基于用户的协同过滤推荐算法实现原理及实现代码
分级加权打分算法java_基于⽤户的协同过滤推荐算法实现原理及实现代码基于⽤户的协同过滤推荐算法实现原理及实现代码1. 基于⽤户的协同过滤推荐算法实现原理传统的基于⽤户(User-Based)的协同过滤推荐算法实现原理分四个步骤:1、根据⽤户历史⾏为信息构建⽤户-项⽬评分矩阵,⽤户历史⾏为信息包括项⽬评分、浏览历史、收藏历史、喜好标签等,本⽂以单⼀的项⽬评分为例,后期介绍其他⾏为信息和混合⾏为信息,⽤户-项⽬评分矩阵如表1所⽰:项⽬1项⽬2项⽬3⽤户A15⽤户B34⽤户C32表1 ⽤户-项⽬评分矩阵注:⽤户A对项⽬1的评分是1分,⽤户A对项⽬2没有评分。
2、根据⽤户-项⽬评分矩阵计算⽤户之间的相似度。
计算相似度常⽤的⽅法有余弦算法、修正余弦算法、⽪尔森算法等等(后期我们会将相似度算法展开讲解,这⾥以余弦算法为例)。
余弦算法公式如图1所⽰:图1 余弦算法公式注:表⽰⽤户u的评分集合(也就是矩阵中的⼀⾏评分数据),表⽰⽤户v的评分集合,i表⽰项⽬,表⽰⽤户u对项⽬1的评分乘以⽤户v对项⽬1的评分加上⽤户u对项⽬2的评分乘以⽤户v对项⽬2的评分……先相加再相乘直到最后⼀个项⽬,表⽰⽤户u对项⽬1的评分的平⽅加上⽤户u对项⽬2的评分的平⽅加上……先平⽅再相加直到最后⼀个项⽬然后得到的值取平⽅根,平⽅根乘以⽤户v的平⽅根。
3、根据⽤户之间的相似度得到⽬标⽤户的最近邻居KNN。
KNN的筛选常⽤的有两种⽅式,⼀种是设置相似度阀值(给定⼀个相似度的下限,⼤于下限的相似度为最近邻居),⼀种是根据与⽬标⽤户相似度的⾼低来选择前N个最近邻居(本次以前N个为例,后期会详细对⽐讲解两者)。
相似度排序可⽤经典冒泡排序法。
4、预测项⽬评分并进⾏推荐。
最常⽤的预测公式如图2所⽰:图2 预测评分公式注:该公式实际上是相似度和评分的加权平均数。
表⽰⽤户u对项⽬i的预测评分,n是最近邻集合,v是任意⼀个最近邻居,表⽰最近邻v和⽬标⽤户u的相似度乘以最近邻v对项⽬i的评分。
大量数据的协同过滤算法
大量数据的协同过滤算法协同过滤算法(Collaborative Filtering)是一种常用的推荐算法,通过分析用户的历史行为、偏好和兴趣,来预测和推荐用户可能感兴趣的物品或者内容。
随着互联网的发展和大数据时代的到来,协同过滤算法在个性化推荐系统中得到广泛应用。
大量数据的协同过滤算法有两种常见的方法:基于用户的协同过滤算法和基于物品的协同过滤算法。
1. 基于用户的协同过滤算法:基于用户的协同过滤算法(User-Based Collaborative Filtering)是最早被提出的协同过滤算法之一,它的核心思想是通过计算用户之间的相似度,为目标用户推荐与其有共同兴趣的物品。
算法的步骤如下:- 构建用户-物品矩阵,矩阵中的每一个元素表示用户对物品的评分。
- 计算用户之间的相似度,常用的相似度计算方法有余弦相似度、皮尔逊相关系数等。
- 根据用户之间的相似度,预测目标用户对未评分物品的评分。
- 根据预测的评分,为目标用户推荐评分较高的物品。
2. 基于物品的协同过滤算法:基于物品的协同过滤算法(Item-Based Collaborative Filtering)是相较于基于用户的协同过滤算法的一种改进方法。
它的核心思想是通过计算物品之间的相似度,为目标用户推荐与其喜欢的物品相似的物品。
算法的步骤如下:- 构建用户-物品矩阵,矩阵中的每一个元素表示用户对物品的评分。
- 计算物品之间的相似度,常用的相似度计算方法有余弦相似度、皮尔逊相关系数等。
- 根据物品之间的相似度,预测目标用户对未评分物品的评分。
- 根据预测的评分,为目标用户推荐评分较高的物品。
尽管基于用户的协同过滤算法和基于物品的协同过滤算法在具体实现上有所不同,但它们的核心思想是相似的:通过分析用户或物品之间的相似度,来预测用户对未评分物品的评分,从而实现个性化推荐。
然而,在大量数据的情况下,传统的协同过滤算法存在一些问题:1. 稀疏性问题:在大量数据的情况下,用户对物品的评分往往是非常稀疏的,即用户只对少数物品进行了评分。
实现推荐系统:基于内容和协同过滤的算法
实现推荐系统:基于内容和协同过滤的算法推荐系统是一种通过分析用户的行为数据、个人化需求和兴趣,为用户提供个性化推荐的算法系统。
基于内容和协同过滤是推荐系统中常用的两种算法方式。
基于内容的推荐算法主要是根据物品(如商品、文章、音乐等)的内容特征,来进行相似度计算和推荐。
该算法首先对物品进行特征提取,例如对文章可以提取关键词,对商品可以提取商品属性。
然后通过计算物品间的相似度,为用户推荐与其历史兴趣相似的物品。
这种算法的优点是可以解决冷启动问题,即对于新用户或新物品,依然可以进行推荐。
缺点是需要人工进行特征提取,并且可能存在特征间相关性较低的问题。
协同过滤算法则是根据用户行为数据,来挖掘用户之间的相似度和物品之间的相似度,从而进行推荐。
协同过滤算法分为基于用户和基于物品的方法。
基于用户的协同过滤算法通过计算用户间的相似度,为用户推荐与其相似用户感兴趣的物品。
基于物品的协同过滤算法则通过计算物品间的相似度,为用户推荐与其历史兴趣相似的物品。
优点是可以自动学习用户兴趣和物品间关系,缺点是存在冷启动问题,如新用户或新物品的推荐。
基于内容和协同过滤的推荐系统结合了两种算法的优点,可以提高推荐系统的准确性和覆盖率。
首先,基于内容的推荐算法可以解决冷启动问题,为新用户和新物品提供推荐。
其次,协同过滤算法可以根据用户的历史行为数据,挖掘用户间的相似度和物品间的相似度,为用户提供个性化的推荐。
最后,基于内容和协同过滤算法的结合可以充分利用用户行为数据和物品内容特征,提高推荐系统的推荐效果。
基于内容和协同过滤的推荐系统的实现步骤如下:1.数据收集与预处理:收集用户行为数据和物品内容数据。
对用户行为数据进行预处理,如去除重复数据、处理缺失值等。
对物品内容数据进行特征提取,如提取关键词、商品属性等。
2.特征表示:将用户行为数据和物品内容数据转化为特征向量表示。
对于用户行为数据,可以使用one-hot编码等方式表示用户对不同物品的行为。
基于物品的协同过滤算法代码详细
基于物品的协同过滤算法1. 简介基于物品的协同过滤算法(Item-based Collaborative Filtering)是一种推荐系统算法,用于向用户推荐与他们已经喜欢的物品相似的其他物品。
它通过分析用户的历史行为数据,寻找物品之间的相似性,从而为用户提供个性化的推荐。
2. 算法原理基于物品的协同过滤算法的核心思想是,如果一个用户喜欢物品A,而物品B与A相似,那么这个用户也很可能喜欢物品B。
具体而言,算法通过以下步骤实现:2.1 数据预处理首先,需要从用户的历史行为数据中构建一个物品-用户矩阵。
矩阵的行表示物品,列表示用户,矩阵中的每个元素表示用户对物品的评分或行为。
2.2 计算物品之间的相似度接下来,需要计算物品之间的相似度。
常用的相似度计算方法包括余弦相似度、皮尔逊相关系数等。
计算物品相似度的过程可以使用并行计算来提高效率。
2.3 生成推荐列表对于每个用户,根据他们的历史行为和物品之间的相似度,可以计算出他们对未评分物品的感兴趣程度。
根据感兴趣程度排序,生成推荐列表。
3. 算法实现下面是基于物品的协同过滤算法的伪代码实现:Input:- 用户-物品矩阵 R- 物品之间的相似度矩阵 SOutput:- 推荐列表 Rec对于每个用户 u in R:对于每个未评分的物品 i in R[u]:对于每个与物品 i 相似的物品 j:如果物品 j 未被用户 u 评分:计算用户 u 对物品 j 的感兴趣程度根据感兴趣程度排序,生成推荐列表 Rec[u]4. 算法优缺点基于物品的协同过滤算法具有以下优点: - 算法简单易懂,实现容易。
- 推荐结果具有较好的准确性和可解释性。
- 算法能够处理冷启动问题,即对于新加入的物品可以通过与已有物品的相似度来进行推荐。
然而,该算法也存在一些缺点: - 计算物品之间的相似度需要消耗较大的计算资源,特别是在数据规模较大时。
- 算法对于稀疏数据的处理效果较差,即当用户对物品的评分较少时,推荐结果可能不够准确。
基于协同过滤算法的推荐系统实现
基于协同过滤算法的推荐系统实现近年来,随着大数据技术的普及和发展,推荐系统已经成为了互联网公司中的重要应用之一。
同时,随着用户数量的不断增长和网站内容的丰富多彩,如何为用户提供更加个性化、精准的推荐服务,也成为了互联网公司亟待解决的问题。
为了解决这个问题,协同过滤算法成为了推荐系统领域的热门算法之一。
协同过滤算法是指通过挖掘用户行为数据,从而发现用户之间存在的关系,然后根据这个关系为用户进行个性化的推荐。
其核心思想是基于用户历史行为或兴趣,推荐与其兴趣相似的其他物品。
协同过滤算法是一种基于数据的推荐方法,没有考虑商品、用户自身的其他特征,仅仅通过用户历史行为,共现关系、或用户对物品反馈等信息来推荐相关物品。
协同过滤算法分为两种基本类型:基于用户的协同过滤算法和基于物品的协同过滤算法。
基于用户的协同过滤算法基于用户的协同过滤算法通过寻找用户之间的相似性,来为一个用户推荐其他用户喜欢的物品。
这种算法的核心思想是,如果两个用户之间在对一些物品的喜好有较高的相似性,那么他们在未来可能对其他物品的喜好也有类似的倾向。
为了计算用户之间的相似性,常用的方法是使用皮尔逊相关系数或余弦相似度等指标。
基于用户的协同过滤算法优点在于,它比较简单和易于实现。
但是,当用户数量和物品数量比较大时,会面临计算复杂度高和存储空间大的问题。
而且,这种算法也无法解决冷启动问题。
基于物品的协同过滤算法基于物品的协同过滤算法则是通过分析物品之间的相似性,来为一个用户推荐与他最近浏览的或者评价过的物品相似的其他物品。
这种算法的核心思想是,如果物品之间有较高的相似性,那么它们的用户喜欢的特征应该也是相似的。
基于物品的协同过滤算法优点在于,它减少了对用户相似性计算的需求,同时也可以面对新用户进行推荐。
但是其缺点在于,物品数量比较大时,计算时空复杂度依然很高。
为了更加高效、准确地推荐物品,一些推荐系统会同时运用基于用户和基于物品的协同过滤算法,从而获得更好的推荐效果。
协同过滤推荐算法(java原生JDK实现-附源码地址)
}
public void setItemId(String itemId) { this、itemId = itemId;
}
public String getItemGeoHash() {
return itemGeoHash;
}
public void setItemGeoHash(String itemGeoHash) { this、itemGeoHash = itemGeoHash;
基于用户的协同过滤推荐算法通过寻找与目标用户具有相似评分的邻居用 户,通过查找邻居用户喜欢的项目,推测目标用户也具有相同的喜好。基于用户的 协同过滤推荐算法基本思想就是:根据用户-项目评分矩阵查找当前用户的最近 邻居,利用最近邻居的评分来预测当前用户对项目的预测值,将评分最高的 N 个项 目推荐给用户,其中的项目可理解为系统处理的商品。其算法流程图如下图 1 所 示。
构建最近邻居集
最近邻居集 Neighor(u)中包含的就是与目标用户具有相同爱好的其 她用户。为选取邻居用户,我们首先计算目标用户 u 与其她用户 v 的相似 度 sim(u,v),再选择相似度最大的 k 个用户。用户相似度可理解为用户之 间的信任值或推荐权重。通常,sim(u,v)∈[1,1]。用户相似度为 1 表示两个 用户互相的推荐权重很大。如果为-1,表示两个用户的由于兴趣相差很大, 因此互相的推荐权重很小。
开始
项目评分 矩阵
得到目标用户访问过的项目 集合Icol(u)
输入k值
计算集合Icol(u)中每个项目与 其他项目相似度
选择相似度最高的k个项目作 为候选集合
计算候选集中所有项目的预测 评分
推荐预测评分最高的N个项目
结束
协同过滤推荐算法(java 原生 JDK 实现-附源码地址)
基于协同过滤的推荐算法JavaScript实现
userId是一个字符串或数字,是生成个性化推荐所面向的用户ID
n是正整数,是取相似度最高的前n个商品,这个值不固定,目前大网站的数据是10最准确
const result = recommendGoodsService.getGoodsGrade(userId, goodsId)
// result是返回的结果,是一个一维数组:[goodsId1, goodsId2......],是goodsId最相似的前n个商品的id列表
-------以下是源码--------
const _ = require('lodash') // 基于用户推荐 const RecommendUserService = class RecommendUserService { /** * 构造方法 * @param {*倒查表所有数据组成的数组} data * @param {*用户ID} userId * @param {*相似度最高的前n个} n */ constructor(data, userId, n) { this.data = data erId = userId this.n = n // 相似度的分子 this.top = undefined // 相似度的分母 this.bottom = undefined // 记录除用户自身外,其他所有用户的ID
userId是一个字符串或数字,是生成个性化推荐所面向的用户ID
n是正整数,是取相似度最高的前n个用户,这个值不固定,目前大网站的据是10最准确
协同过滤算法参考代码
协同过滤算法参考代码代码有问题,运⾏出错,寻找解决办法,是不是数据集的错误呢?#include<iostream>#include<queue>#include<cmath>#include<cassert>#include<cstdlib>#include<fstream>#include<sstream>#include<vector>#include<algorithm>using namespace std;const int ITERM_SIZE=1682;const int USER_SIZE=943;const int V=15; //ITERM的最近邻居数const int S=10; //USER的最近邻居数struct MyPair{int id;double value;MyPair(int i=0,double v=0):id(i),value(v){}};struct cmp{bool operator() (const MyPair & obj1,const MyPair & obj2)const{return obj1.value < obj2.value;}};double rate[USER_SIZE][ITERM_SIZE]; //评分矩阵MyPair nbi[ITERM_SIZE][V]; //存放每个ITERM的最近邻居MyPair nbu[USER_SIZE][S]; //存放每个USER的最近邻居double rate_avg[USER_SIZE]; //每个⽤户的平均评分//从⽂件中读⼊评分矩阵int readRate(string filename){ifstream ifs;ifs.open(filename.c_str());if(!ifs){cerr<<"error:unable to open input file "<<filename<<endl;return -1;}string line;while(getline(ifs,line)){string str1,str2,str3;istringstream strstm(line);strstm>>str1>>str2>>str3;int userid=atoi(str1.c_str());int itermid=atoi(str2.c_str());double rating=atof(str3.c_str());rate[userid-1][itermid-1]=rating;//line.clear();}ifs.close();return 0;}//计算每个⽤户的平均评分void getAvgRate(){for(int i=0;i<USER_SIZE;++i){for(int j=0;j<ITERM_SIZE;++j)sum+=rate[i][j];rate_avg[i]=sum/ITERM_SIZE;}}//计算两个向量的⽪尔森相关系数double getSim(const vector<double> &vec1,const vector<double> &vec2){ int len=vec1.size();assert(len==vec2.size());double sum1=0;double sum2=0;double sum1_1=0;double sum2_2=0;double sum=0;for(int i=0;i<len;i++){sum+=vec1[i]*vec2[i];sum1+=vec1[i];sum2+=vec2[i];sum1_1+=vec1[i]*vec1[i];sum2_2+=vec2[i]*vec2[i];}double ex=sum1/len;double ey=sum2/len;double ex2=sum1_1/len;double ey2=sum2_2/len;double exy=sum/len;double sdx=sqrt(ex2-ex*ex);double sdy=sqrt(ey2-ey*ey);assert(sdx!=0 && sdy!=0);double sim=(exy-ex*ey)/(sdx*sdy);return sim;}//计算每个ITERM的最近邻void getNBI(){for(int i=0;i<ITERM_SIZE;++i){vector<double> vec1;priority_queue<MyPair,vector<MyPair>,cmp> neighbour;for(int k=0;k<USER_SIZE;k++)vec1.push_back(rate[k][i]);for(int j=0;j<ITERM_SIZE;j++){if(i==j)continue;vector<double> vec2;for(int k=0;k<USER_SIZE;k++)vec2.push_back(rate[k][j]);double sim=getSim(vec1,vec2);MyPair p(j,sim);neighbour.push(p);}for(int n=0;n<V;++n){nbi[i][n]=neighbour.top();neighbour.pop();}}}//预测⽤户对未评分项⽬的评分值double getPredict(const vector<double> &user,int index){double sum1=0;double sum2=0;for(int i=0;i<V;++i){int neib_index=nbi[index][i].id;double neib_sim=nbi[index][i].value;sum1+=neib_sim*user[neib_index];sum2+=fabs(neib_sim);return sum1/sum2;}//计算两个⽤户的相似度double getUserSim(const vector<double> &user1,const vector<double> &user2){ vector<double> vec1;vector<double> vec2;int len=user1.size();assert(len==user2.size());for(int i=0;i<len;++i){if(user1[i]!=0 || user2[i]!=0){if(user1[i]!=0)vec1.push_back(user1[i]);elsevec1.push_back(getPredict(user1,i));if(user2[i]!=0)vec2.push_back(user2[i]);elsevec2.push_back(getPredict(user2,i));}}return getSim(vec1,vec2);}//计算每个USER的最近邻void getNBU(){for(int i=0;i<USER_SIZE;++i){vector<double> user1;priority_queue<MyPair,vector<MyPair>,cmp> neighbour;for(int k=0;k<ITERM_SIZE;++k)user1.push_back(rate[i][k]);for(int j=0;j<USER_SIZE;++j){if(j==i)continue;vector<double> user2;for(int k=0;k<ITERM_SIZE;++k)user2.push_back(rate[j][k]);double sim=getUserSim(user1,user2);MyPair p(j,sim);neighbour.push(p);}for(int m=0;m<S;++m){nbu[i][m]=neighbour.top();neighbour.pop();}}}//产⽣推荐,预测某⽤户对某项⽬的评分double predictRate(int user,int iterm){double sum1=0;double sum2=0;for(int i=0;i<S;++i){int neib_index=nbu[user][i].id;double neib_sim=nbu[user][i].value;sum1+=neib_sim*(rate[neib_index][iterm]-rate_avg[neib_index]);sum2+=fabs(neib_sim);}return rate_avg[user]+sum1/sum2;}//测试int main(){//string file="/home/orisun/DataSet/movie-lens-100k/u.data";string file="E:\\C++programs1\\ml-100k\\ml-100k\\u.data";if(readRate(file)!=0){return -1;getAvgRate();getNBI();getNBU();while(1){cout<<"please input user index and iterm index which you want predict"<<endl; int user,iterm;cin>>user>>iterm;cout<<predictRate(user,iterm)<<endl;}return 0;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
协同过滤推荐算法(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();。