求Python中基于Yelp评论数据集高效构建推荐系统评分矩阵的方法
高效构建Python推荐系统评分矩阵(MongoDB数据源优化方案)
我来帮你彻底优化这个评分矩阵的构建流程——原代码的核心问题在于频繁的数据库IO和低效的线性查找/去重,这在数据量稍大时会导致性能急剧下降。下面是针对性的优化思路和完整实现代码:
核心优化策略
- 批量查询替代零散IO:把多次循环调用的
find/find_one换成2次批量查询,一次性拉取所有需要的数据到内存处理,彻底减少数据库交互次数。 - 哈希映射提速定位:用字典存储
user_id到行索引、business_id到列索引的映射,实现O(1)时间复杂度的位置定位,替代原代码中O(n)的线性判断。 - 集合自动去重:用Python集合处理用户ID去重,比列表的
if x not in list判断效率提升数倍。 - 批量文件写入:用字符串拼接整行内容后一次性写入,减少磁盘IO次数。
完整优化代码
from pymongo import MongoClient # 假设你已经初始化了MongoDB连接和集合 client = MongoClient("your_mongodb_connection_string") db = client["your_database_name"] colBisnis = db["business"] # 对应原代码中的商家集合 colReview = db["review"] # 对应原代码中的评论集合 def get_business_ids_by_city(city_name): """批量获取目标城市的所有去重商家ID""" # 使用MongoDB的distinct方法直接返回去重结果,无需手动循环判断 return colBisnis.distinct("_id", {"city": city_name}) def get_reviews_and_users(business_ids): """批量获取目标商家的所有评论,并生成用户ID列表和评分映射表""" # 用$in批量查询所有目标商家的评论,避免循环逐个查询 reviews = list(colReview.find({"business_id": {"$in": business_ids}})) # 用集合自动去重用户ID,效率远高于列表判断 user_ids = list({review["user_id"] for review in reviews}) # 构建(user_id, business_id) -> stars的映射字典,方便快速查找评分 review_map = {(review["user_id"], review["business_id"]): review["stars"] for review in reviews} return user_ids, review_map def build_rating_matrix(business_ids, user_ids, review_map): """构建评分矩阵并写入文件""" # 创建商家ID到列索引的映射 biz_to_idx = {biz: idx for idx, biz in enumerate(business_ids)} # 创建用户ID到行索引的映射 user_to_idx = {user: idx for idx, user in enumerate(user_ids)} # 初始化全0矩阵:行数=用户数,列数=商家数 matrix = [[0] * len(business_ids) for _ in range(len(user_ids))] # 批量填充评分:直接通过映射定位矩阵位置,无需查询数据库 for (user_id, biz_id), stars in review_map.items(): row_idx = user_to_idx[user_id] col_idx = biz_to_idx[biz_id] matrix[row_idx][col_idx] = stars # 批量写入文件:用join拼接整行,减少磁盘IO次数 with open("rating_matrix.txt", "w") as f: for row in matrix: # 把每行的数字转为字符串,用|连接,末尾补|并换行 line = "|".join(map(str, row)) + "|\n" f.write(line) def build_city_table(city_name): """整合所有步骤,构建目标城市的评分矩阵""" # 步骤1:获取目标城市的商家ID列表 business_ids = get_business_ids_by_city(city_name) if not business_ids: print(f"未找到{city_name}的商家数据") return # 步骤2:获取评论数据和用户ID列表 user_ids, review_map = get_reviews_and_users(business_ids) if not user_ids: print(f"{city_name}的商家暂无评论数据") return # 步骤3:构建并写入矩阵 build_rating_matrix(business_ids, user_ids, review_map) print(f"{city_name}的评分矩阵已成功生成!") # 执行示例 city_name_var = 'Pointe-Aux-Trembles' build_city_table(city_name_var)
性能提升说明
- 数据库查询次数:原代码的查询次数为
用户数×商家数 + 商家数 + 用户数,优化后仅为2次,彻底消除了最耗时的IO瓶颈。 - 去重效率:集合去重的时间复杂度是O(n),而原代码的列表判断去重是O(n²),数据量越大提升越明显。
- 矩阵填充效率:哈希映射定位的时间复杂度是O(1),替代原代码的O(1)数据库查询(但数据库查询的实际开销远高于内存操作)。
内容的提问来源于stack exchange,提问作者Andre Hrs
相关产品推荐
相关产品推荐

