Collaborative Filtering Resources

本文深入解析了协作过滤算法的核心概念、实现方式及在推荐系统中的广泛应用,包括研究软件、数据集、文献综述等关键内容。通过分析不同算法的优缺点,为读者提供了一站式的协作过滤算法学习指南。

Generally, collaborative filtering (CF) is any algorithm that filters information for a user based on a collection of user profiles. Users having similar profiles may share similar interests. For a user, information can be filtered in/out regarding to the behaviors of his or her similar users.

Users profiles can be collected either explicitly or implicitly. One can explicitly ask users to rate what they have used/purchased. Such a profile is filled explicitly by the users ratings. An implicit profile is based on passive observation and contains users historic interaction data.

The most common usage of CF is to make recommendation. That's why collaborative filtering is strongly correlated to recommender system in literature, although CF is only one of the methods for recommender system.

In this page, I collected some useful online materials for collaborative filtering research.


Content

Research Software

Data Sets

Explicit Rating Data Sets:

Implicit Rating Data Sets:

  • Audioscrobblers Music Play-list Data-sets.The Audioscrobbler dataset collects the play-lists of the users in a one-line community (http://www.audioscrobbler.com/) by using a plug-in in the users' media players such as Winamp, iTunes, XMMS etc. The plug-ins send the title and artist of every song users play to the Audioscrobbler server, which updates the user's musical profile with the new songs. In the database, the user's profile is recorded as a form of co-occurrence pair like {userID,itemID} pair. The pair means a user {userID} has played a/ song {itemID}. The dataset can be obtained at http://www.audioscrobbler.com/data/
  • AOL Web search query: http://www.gregsadetsky.com/aol-data/

Collaborative Filtering Bibliography
1. Pure Collaborative Filtering
Memory-based
Relevance Models
Latent Class Models
Matrix Factorization
Clustering
Transitive Associations
Trust Inference
Perception-based
  • Online ranking/collaborative filtering using the perception algorithm (2003).
2. Combining Content-based and Collaborative Filtering
3. Distributed Collaborative Filtering
4. Other issues

Related Information Retrieval Papers

In general, collaborative filtering is formulated as a self-contained problem, apart from classic approaches for text retrieval, e.g. RSJ models and language models. However, the collaborative filtering problem can be treated as a prediction problem - a prediction of the relevance between user and item (see user-item relevance models). Under this veiw, the instant benefits are gained from the current advances in these text retrieval models. We found the following papers are pretty interesting and are related to the collaborative filtering problem.


Related Machine Learning Papers
# python/collaborative_filtering.py import sys import json import pandas as pd from sklearn.metrics.pairwise import cosine_similarity def main(): # 读取输入参数 if len(sys.argv) < 2: print("Usage: python collaborative_filtering.py <user_id>") sys.exit(1) target_user_id = int(sys.argv[1]) # 读取输入数据 with open('resources/temp/input.json', 'r', encoding='utf-8') as f: data = json.load(f) df = pd.DataFrame(data) if df.empty: with open('resources/temp/output.json', 'w') as f: json.dump([], f) return # 构建 用户-商品 矩阵 user_item_matrix = df.pivot(index='userId', columns='productId', values='count').fillna(0) # 计算商品相似度(Item-Based) item_similarity = cosine_similarity(user_item_matrix.T) item_sim_df = pd.DataFrame(item_similarity, index=user_item_matrix.columns, columns=user_item_matrix.columns) # 推荐逻辑 if target_user_id not in user_item_matrix.index: recommendations = [] else: user_ratings = user_item_matrix.loc[target_user_id] bought_items = user_ratings[user_ratings > 0].index scores = pd.Series(0, index=item_sim_df.index) for item in bought_items: scores += item_sim_df[item] * user_ratings[item] # 过滤已购买 + 排序取 Top 5 rec_list = scores.drop(bought_items).sort_values(ascending=False).head(5).index.tolist() recommendations = [int(pid) for pid in rec_list] # 写出结果 with open('resources/temp/output.json', 'w', encoding='utf-8') as f: json.dump(recommendations, f, ensure_ascii=False) if __name__ == "__main__": main() 加注释
10-17
package com.shop.jieyou.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.shop.jieyou.common.Result; import com.shop.jieyou.entity.UserItem; import com.shop.jieyou.service.PythonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 花卉相关接口控制器 * 提供三大功能: * 1. 获取中国十大名花数据(来自爬虫或缓存) * 2. 手动刷新花卉数据(强制重新爬取) * 3. 基于用户行为的花卉推荐(调用Python协同过滤脚本) */ @RestController @CrossOrigin(origins = "*") // 允许所有域访问,用于前端开发调试(生产环境建议限制域名) @RequestMapping("/api") public class FlowerController { @Autowired private PythonService pythonService; // 注入业务服务层,处理数据获取与推荐逻辑 /** * 接口:GET /api/flowers * 功能:获取“中国十大名花”数据列表 * 数据来源:可能来自数据库、Redis 缓存 或 调用 Python 爬虫脚本 * * @return Result<List<Map<String, Object>>> 返回包含花卉信息的成功响应 */ @GetMapping("/flowers") public Result<List<Map<String, Object>>> getTopTenFlowers() { try { // 调用服务层获取花卉数据(内部可能带缓存机制) List<Map<String, Object>> flowers = pythonService.getFlowers(); return Result.success(flowers); // 成功返回数据 } catch (Exception e) { // 捕获异常并统一返回错误码和消息,避免暴露堆栈给前端 return Result.error("500", "获取花卉数据失败:" + e.getMessage()); } } /** * 接口:POST /api/flowers/refresh * 功能:强制刷新花卉数据缓存,触发重新爬取 * 使用场景:管理员手动更新数据时调用 * * @return Result<Map<String, Object>> 返回刷新结果信息 */ @PostMapping("/flowers/refresh") public Result<Map<String, Object>> refreshData() { try { // TODO: 如果实现了 clearCache 方法,请取消注释并调用 // pythonService.clearCache(); // 清除旧缓存,下次 getFlowers 将重新爬取 // 重新获取最新数据(假设此时会触发爬虫) List<Map<String, Object>> flowers = pythonService.getFlowers(); // 构造返回信息 Map<String, Object> data = new HashMap<>(); data.put("message", "数据已刷新"); data.put("count", flowers.size()); return Result.success(data); } catch (Exception e) { return Result.error("500", "刷新失败:" + e.getMessage()); } } // ========== 推荐系统相关常量定义 ========== /** * 输入文件路径:Java 将用户-商品行为数据写入此 JSON 文件供 Python 脚本读取 * 注意:src/main/resources 是编译后打包进 jar 的资源目录,不适合运行时写入! * 建议改为外部路径如 "./data/input.json" */ private static final String INPUT_PATH = "src/main/resources/scripts/input.json"; /** * 输出文件路径:Python 脚本将推荐结果写入此文件,Java 再读取返回给前端 */ private static final String OUTPUT_PATH = "src/main/resources/scripts/output.json"; /** * Python 协同过滤脚本路径 * 注意:resources 目录下的 .py 文件在打包后无法直接作为可执行脚本运行 * 更佳做法是将脚本放在项目外部或使用 ProcessBuilder 启动独立服务 */ private static final String PYTHON_SCRIPT = "src/main/resources/scripts/collaborative.py"; /** * 接口:GET /api/recommend?userId=123 * 功能:为指定用户生成个性化花卉推荐列表 * 实现方式:Java 查询数据库 → 写入 JSON 文件 → 调用 Python 脚本计算 → 读取结果返回 * * @param userId 用户ID,必填参数 * @return Result<JsonNode> 推荐的商品ID数组(如 [101, 105, 108]) */ @GetMapping("/recommend") public Result recommendFlowers(@RequestParam("userId") Long userId) { try { // 1. 从数据库查询用户-商品交互记录(例如购买、浏览次数) List<UserItem> matrix = pythonService.getUserItemMatrix(); // 2. 使用 Jackson 将数据序列化为 JSON 并写入文件 ObjectMapper mapper = new ObjectMapper(); File inputFile = new File(INPUT_PATH); // ✅ 增强健壮性:确保父目录存在 if (!inputFile.getParentFile().exists()) { inputFile.getParentFile().mkdirs(); // 自动创建 scripts 目录 } mapper.writeValue(inputFile, matrix); // 3. 调用 Python 协同过滤脚本 ProcessBuilder pb = new ProcessBuilder("python", PYTHON_SCRIPT, String.valueOf(userId)); pb.redirectErrorStream(true); // 合并标准输出和错误流,便于捕获日志 Process process = pb.start(); // 等待脚本执行完成 int exitCode = process.waitFor(); if (exitCode != 0) { // Python 脚本执行失败 return Result.error("error", "Python script failed with exit code: " + exitCode); } // 4. 读取 Python 输出的推荐结果 File outputFile = new File(OUTPUT_PATH); if (!outputFile.exists()) { return Result.error("error", "Python script did not generate output file."); } JsonNode result = mapper.readTree(outputFile); // 成功返回推荐结果 return Result.success(result); } catch (Exception e) { // 统一异常处理,返回标准化错误格式 e.printStackTrace(); // 开发期打印堆栈,生产环境应使用日志框架 return Result.error("500", "推荐生成失败:" + e.getMessage()); } } } # -*- coding: utf-8 -*- """ 协同过滤推荐系统脚本(基于物品的协同过滤) 功能:读取用户-商品行为数据,计算商品相似度,为指定用户生成推荐列表 输入:通过命令行传入用户ID,从JSON文件读取用户购买行为数据 输出:将推荐的商品ID列表写入输出JSON文件 """ import sys # 用于获取命令行参数 import json # 用于读写 JSON 格式的数据文件 import pandas as pd # 数据处理库,用于构建矩阵和分析 from sklearn.metrics.pairwise import cosine_similarity # 计算余弦相似度 def main(): """ 主函数:执行完整的推荐流程 步骤: 1. 获取目标用户ID 2. 读取用户-商品交互数据 3. 构建用户-商品评分矩阵 4. 计算商品之间的相似度(Item-Based) 5. 为目标用户生成推荐商品列表 6. 将结果写入输出文件 """ # ========== 第一步:获取命令行传入的用户ID ========== if len(sys.argv) < 2: print("错误:未提供用户ID") print("用法示例:python collaborative_filtering.py <user_id>") sys.exit(1) # 参数不足则退出程序 try: target_user_id = int(sys.argv[1]) # 获取第一个命令行参数作为用户ID except ValueError: print("错误:用户ID必须是一个整数") sys.exit(1) # ========== 第二步:从JSON文件加载用户-商品行为数据 ========== input_file_path = 'src/main/resources/scripts/input.json' # 输入文件路径(由Spring Boot生成) try: with open(input_file_path, 'r', encoding='utf-8') as f: data = json.load(f) # 加载JSON数据为Python列表 except FileNotFoundError: print(f"错误:找不到输入文件 {input_file_path}") sys.exit(1) except json.JSONDecodeError as e: print(f"错误:JSON解析失败:{e}") sys.exit(1) # 将数据转换为 Pandas DataFrame df = pd.DataFrame(data) # 如果没有数据,直接返回空推荐 if df.empty: print("警告:输入数据为空,无法进行推荐") with open('src/main/resources/scripts/output.json', 'w', encoding='utf-8') as f: json.dump([], f) # 输出空列表 return # ========== 第三步:构建用户-商品交互矩阵 ========== # 行:用户(userId),列:商品(productId),值:购买次数(count) # fillna(0):将缺失值(未购买)补为0 user_item_matrix = df.pivot(index='userId', columns='productId', values='count').fillna(0) print(f"用户-商品矩阵形状:{user_item_matrix.shape}") # ========== 第四步:计算商品之间的相似度(Item-Based 协同过滤)========== # 使用余弦相似度衡量两个商品被相同用户购买的模式是否相似 # .T 表示转置:把商品变为行,用户变为列,便于计算商品间相似性 item_similarity = cosine_similarity(user_item_matrix.T) # 得到相似度矩阵(二维数组) # 将相似度数组转为DataFrame,方便按商品ID索引 item_sim_df = pd.DataFrame( item_similarity, index=user_item_matrix.columns, # 商品ID作为行索引 columns=user_item_matrix.columns # 商品ID作为列索引 ) # ========== 第五步:为指定用户生成推荐列表 ========== if target_user_id not in user_item_matrix.index: # 用户不存在于训练数据中(新用户),无法推荐 print(f"警告:用户 {target_user_id} 无历史行为数据,返回空推荐(冷启动)") recommendations = [] else: # 获取该用户的购买记录 user_ratings = user_item_matrix.loc[target_user_id] # Series: productId -> count # 找出该用户已购买的商品 bought_items = user_ratings[user_ratings > 0].index # 已购商品ID列表 # 初始化一个Series用于累计每个商品的推荐得分 scores = pd.Series(0, index=item_sim_df.index) # 初始全为0 # 对每一个用户买过的商品,将其相似商品的得分加权累加 for item in bought_items: # item_sim_df[item]: 当前商品与其他所有商品的相似度 # user_ratings[item]: 用户对该商品的“兴趣强度”(可用购买次数表示) scores += item_sim_df[item] * user_ratings[item] # 过滤掉用户已经买过的商品 candidate_scores = scores.drop(bought_items, errors='ignore') # 按得分降序排列,取前5个最相似且未购买的商品 top_recommendations = candidate_scores.sort_values(ascending=False).head(5) # 提取商品ID并转为整数列表 rec_list = top_recommendations.index.tolist() recommendations = [int(pid) for pid in rec_list] print(f"为用户 {target_user_id} 推荐商品: {recommendations}") # ========== 第六步:将推荐结果写入输出文件 ========== output_file_path = 'resources/temp/output.json' try: with open(output_file_path, 'w', encoding='utf-8') as f: json.dump(recommendations, f, ensure_ascii=False, indent=2) # 格式化保存 print("推荐结果已成功写入输出文件") except Exception as e: print(f"错误:无法写入输出文件 {output_file_path}: {e}") sys.exit(1) # 程序入口点 if __name__ == "__main__": """ 当脚本被直接运行时(而非被导入),执行 main() 函数 示例运行命令: python collaborative_filtering.py 123 """ main() # -*- coding: utf-8 -*- """ 协同过滤推荐系统脚本(基于物品的协同过滤) 功能:读取用户-商品行为数据,计算商品相似度,为指定用户生成推荐列表 输入:通过命令行传入用户ID,从JSON文件读取用户购买行为数据 输出:将推荐的商品ID列表写入输出JSON文件 """ import sys # 用于获取命令行参数 import json # 用于读写 JSON 格式的数据文件 import pandas as pd # 数据处理库,用于构建矩阵和分析 from sklearn.metrics.pairwise import cosine_similarity # 计算余弦相似度 def main(): """ 主函数:执行完整的推荐流程 步骤: 1. 获取目标用户ID 2. 读取用户-商品交互数据 3. 构建用户-商品评分矩阵 4. 计算商品之间的相似度(Item-Based) 5. 为目标用户生成推荐商品列表 6. 将结果写入输出文件 """ # ========== 第一步:获取命令行传入的用户ID ========== if len(sys.argv) < 2: print("错误:未提供用户ID") print("用法示例:python collaborative_filtering.py <user_id>") sys.exit(1) # 参数不足则退出程序 try: target_user_id = int(sys.argv[1]) # 获取第一个命令行参数作为用户ID except ValueError: print("错误:用户ID必须是一个整数") sys.exit(1) # ========== 第二步:从JSON文件加载用户-商品行为数据 ========== input_file_path = 'src/main/resources/scripts/input.json' # 输入文件路径(由Spring Boot生成) try: with open(input_file_path, 'r', encoding='utf-8') as f: data = json.load(f) # 加载JSON数据为Python列表 except FileNotFoundError: print(f"错误:找不到输入文件 {input_file_path}") sys.exit(1) except json.JSONDecodeError as e: print(f"错误:JSON解析失败:{e}") sys.exit(1) # 将数据转换为 Pandas DataFrame df = pd.DataFrame(data) # 如果没有数据,直接返回空推荐 if df.empty: print("警告:输入数据为空,无法进行推荐") with open('src/main/resources/scripts/output.json', 'w', encoding='utf-8') as f: json.dump([], f) # 输出空列表 return # ========== 第三步:构建用户-商品交互矩阵 ========== # 行:用户(userId),列:商品(productId),值:购买次数(count) # fillna(0):将缺失值(未购买)补为0 user_item_matrix = df.pivot(index='userId', columns='productId', values='count').fillna(0) print(f"用户-商品矩阵形状:{user_item_matrix.shape}") # ========== 第四步:计算商品之间的相似度(Item-Based 协同过滤)========== # 使用余弦相似度衡量两个商品被相同用户购买的模式是否相似 # .T 表示转置:把商品变为行,用户变为列,便于计算商品间相似性 item_similarity = cosine_similarity(user_item_matrix.T) # 得到相似度矩阵(二维数组) # 将相似度数组转为DataFrame,方便按商品ID索引 item_sim_df = pd.DataFrame( item_similarity, index=user_item_matrix.columns, # 商品ID作为行索引 columns=user_item_matrix.columns # 商品ID作为列索引 ) # ========== 第五步:为指定用户生成推荐列表 ========== if target_user_id not in user_item_matrix.index: # 用户不存在于训练数据中(新用户),无法推荐 print(f"警告:用户 {target_user_id} 无历史行为数据,返回空推荐(冷启动)") recommendations = [] else: # 获取该用户的购买记录 user_ratings = user_item_matrix.loc[target_user_id] # Series: productId -> count # 找出该用户已购买的商品 bought_items = user_ratings[user_ratings > 0].index # 已购商品ID列表 # 初始化一个Series用于累计每个商品的推荐得分 scores = pd.Series(0, index=item_sim_df.index) # 初始全为0 # 对每一个用户买过的商品,将其相似商品的得分加权累加 for item in bought_items: # item_sim_df[item]: 当前商品与其他所有商品的相似度 # user_ratings[item]: 用户对该商品的“兴趣强度”(可用购买次数表示) scores += item_sim_df[item] * user_ratings[item] # 过滤掉用户已经买过的商品 candidate_scores = scores.drop(bought_items, errors='ignore') # 按得分降序排列,取前5个最相似且未购买的商品 top_recommendations = candidate_scores.sort_values(ascending=False).head(5) # 提取商品ID并转为整数列表 rec_list = top_recommendations.index.tolist() recommendations = [int(pid) for pid in rec_list] print(f"为用户 {target_user_id} 推荐商品: {recommendations}") # ========== 第六步:将推荐结果写入输出文件 ========== output_file_path = 'resources/temp/output.json' try: with open(output_file_path, 'w', encoding='utf-8') as f: json.dump(recommendations, f, ensure_ascii=False, indent=2) # 格式化保存 print("推荐结果已成功写入输出文件") except Exception as e: print(f"错误:无法写入输出文件 {output_file_path}: {e}") sys.exit(1) # 程序入口点 if __name__ == "__main__": """ 当脚本被直接运行时(而非被导入),执行 main() 函数 示例运行命令: python collaborative_filtering.py 123 """ main()
最新发布
10-17
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值