目录
1. 基础知识
协同过滤(Collaborative Filtering, CF)是一种广泛应用于推荐系统中的算法,它通过分析和利用用户与物品之间的交互信息来发现用户可能感兴趣的内容。协同过滤主要分为两种类型:用户基于的协同过滤(User-based Collaborative Filtering)和物品基于的协同过滤(Item-based Collaborative Filtering)。
用户基于的协同过滤(User-based CF)
用户基于的协同过滤算法的基本思想是:找到与目标用户兴趣相似的其他用户,然后将这些相似用户喜欢的物品推荐给目标用户。
步骤:
- 收集用户数据:收集用户的历史行为数据,如评分、点击、购买等。
- 计算用户相似度:通过用户的历史行为数据计算用户之间的相似度。常用的相似度计算方法有余弦相似度、皮尔逊相关系数、Jaccard相似度等。
- 生成推荐:根据用户相似度和相似用户的喜好,为目标用户生成推荐列表。通常,会选择与目标用户最相似的N个用户,然后将这些用户喜欢的、但目标用户尚未接触的物品推荐给目标用户。
物品基于的协同过滤(Item-based CF)
物品基于的协同过滤算法的基本思想是:分析用户的历史行为数据,找出与目标物品相似的其他物品,然后将这些相似物品推荐给喜欢目标物品的用户。
步骤:
- 收集用户数据:同样需要收集用户的历史行为数据。
- 计算物品相似度:通过用户的历史行为数据计算物品之间的相似度。常用的方法包括余弦相似度、皮尔逊相关系数等。
- 生成推荐:对于用户喜欢的物品,找到与该物品相似的其他物品,并将这些相似物品推荐给该用户。
优缺点
优点:
- 自动化:不需要人工干预,可以自动发现用户的潜在兴趣。
- 个性化:能够为用户提供个性化的推荐。
- 广泛性:可以应用于各种类型的数据和场景。
缺点:
- 冷启动问题:对于新用户或新物品,由于缺乏历史数据,难以进行有效的推荐。
- 稀疏性问题:用户与物品之间的交互数据通常非常稀疏,导致相似度计算不准确。
- 扩展性问题:随着用户和物品数量的增加,计算量和存储量都会急剧增加。
实际应用
协同过滤算法在电子商务(如Amazon的商品推荐)、在线视频(如Netflix的电影推荐)、社交媒体(如Facebook的好友推荐)等领域都有广泛的应用。随着大数据和机器学习技术的发展,协同过滤算法也在不断演进和优化,以应对更复杂的数据和更高的性能要求。
2. 项目功能实战
/**
* 协同算法(按收藏推荐)
*/
@RequestMapping("/autoSort2")
public R autoSort2(@RequestParam Map<String, Object> params,BingxiangxinxiEntity bingxiangxinxi, HttpServletRequest request){
String userId = request.getSession().getAttribute("userId").toString();
String inteltypeColumn = "pinpai";
List<StoreupEntity> storeups = storeupService.selectList(new EntityWrapper<StoreupEntity>().eq("type", 1).eq("userid", userId).eq("tablename", "bingxiangxinxi").orderBy("addtime", false));
List<String> inteltypes = new ArrayList<String>();
Integer limit = params.get("limit")==null?10:Integer.parseInt(params.get("limit").toString());
List<BingxiangxinxiEntity> bingxiangxinxiList = new ArrayList<BingxiangxinxiEntity>();
//去重
if(storeups!=null && storeups.size()>0) {
for(StoreupEntity s : storeups) {
bingxiangxinxiList.addAll(bingxiangxinxiService.selectList(new EntityWrapper<BingxiangxinxiEntity>().eq(inteltypeColumn, s.getInteltype())));
}
}
EntityWrapper<BingxiangxinxiEntity> ew = new EntityWrapper<BingxiangxinxiEntity>();
params.put("sort", "id");
params.put("order", "desc");
PageUtils page = bingxiangxinxiService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, bingxiangxinxi), params), params));
List<BingxiangxinxiEntity> pageList = (List<BingxiangxinxiEntity>)page.getList();
if(bingxiangxinxiList.size()<limit) {
int toAddNum = (limit-bingxiangxinxiList.size())<=pageList.size()?(limit-bingxiangxinxiList.size()):pageList.size();
for(BingxiangxinxiEntity o1 : pageList) {
boolean addFlag = true;
for(BingxiangxinxiEntity o2 : bingxiangxinxiList) {
if(o1.getId().intValue()==o2.getId().intValue()) {
addFlag = false;
break;
}
}
if(addFlag) {
bingxiangxinxiList.add(o1);
if(--toAddNum==0) break;
}
}
} else if(bingxiangxinxiList.size()>limit) {
bingxiangxinxiList = bingxiangxinxiList.subList(0, limit);
}
page.setList(bingxiangxinxiList);
return R.ok().put("data", page);
}
这段代码实现了一个基于用户收藏行为的协同推荐算法(或类似功能),但它混合了多种数据处理和筛选逻辑。下面是对这段代码的详细解释:
- 获取用户ID和初始化变量:
String userId = request.getSession().getAttribute("userId").toString();
:从HTTP会话中获取当前用户的ID,并将其转换为字符串。String inteltypeColumn = "pinpai";
:定义了一个变量,它主要用于后续查询条件。
- 获取用户收藏的数据:
- 通过
storeupService.selectList(...)
方法查询用户收藏的数据(StoreupEntity
对象列表),这里筛选了类型为1、用户ID为当前用户、且表名为bingxiangxinxi
的记录,并按addtime
降序排列。
- 通过
- 初始化变量和限制条件:
- 初始化了一个空的
inteltypes
列表 - 从请求参数中获取
limit
值(表示结果数量限制),如果没有提供则默认为10。
- 初始化了一个空的
- 根据用户收藏的品牌获取相关信息:
- 遍历
storeups
列表,对于每个收藏项(这里假设inteltype
表示品牌),使用bingxiangxinxiService.selectList(...)
方法查询与该品牌相关的BingxiangxinxiEntity
对象列表,并将这些列表添加到bingxiangxinxiList
中。这里可能存在重复数据,因为不同的收藏项可能指向相同的品牌。
- 遍历
- 设置分页和排序参数:
- 创建一个
EntityWrapper<BingxiangxinxiEntity>
对象用于构建查询条件 - 向
params
中添加了分页排序的参数,
- 创建一个
- 执行分页查询:
- 使用
bingxiangxinxiService.queryPage(...)
方法执行分页查询,这里使用了MPUtil
工具类来处理查询条件、排序和分页逻辑。查询结果存储在PageUtils
对象中,并从中提取出分页列表pageList
。
- 使用
- 合并结果并去重:
- 如果
bingxiangxinxiList
的大小小于limit
,则从pageList
中选取额外的记录添加到bingxiangxinxiList
中,直到达到limit
限制或pageList
中的记录被全部添加。在添加过程中,通过比较ID来避免重复添加相同的记录。
- 如果
- 总结:
- 这段代码的主要目的是根据用户的收藏行为(这里是品牌)来推荐相关的
BingxiangxinxiEntity
对象。它首先根据用户的收藏获取相关的品牌,然后根据这些品牌查询相关信息,并通过分页和去重逻辑来限制最终推荐列表的大小。然而,代码中存在一些潜在的优化点,比如直接使用数据库查询来避免内存中的去重操作,以及更清晰地处理PageUtils
和MPUtil
等工具类的使用。
- 这段代码的主要目的是根据用户的收藏行为(这里是品牌)来推荐相关的