旅游推荐系统(基于用户的协同过滤recommendation.py)

推荐算法页面recommendation.py

python 复制代码
import django
# 导入Django模块,用于初始化Django环境

os.environ.setdefault('DJANGO_SETTINGS_MODULE','去哪儿旅游数据分析推荐系统.settings')
# 设置环境变量,指定Django项目的配置文件路径
# 'DJANGO_SETTINGS_MODULE'是Django识别的环境变量名
# 告诉Django使用哪个配置文件来加载项目设置

django.setup()
# 初始化Django环境
# 这行代码让Django加载配置文件、连接数据库、准备ORM
# 之后才能使用Django的模型(如TravelInfo)来查询数据库

from app.models import TravelInfo
# 从app应用中导入TravelInfo模型类
# TravelInfo对应数据库中的景点信息表,包含景点名称、评论等数据

# 以下是被注释掉的示例数据,展示了用户评分数据的格式
# user_ratings = {
#     "Edward": {"南山文化旅游区": 5},  # 用户Edward给南山文化旅游区打了5分
#     "EdwardD": {"南山文化旅游区": 5, "三亚蜈支洲岛旅游区": 2},  # 用户EdwardD有两个评分
#     "newEdward"  # 新用户,还没有评分
# }

# ============================================================================

def getUser_ratings():
    # 定义函数:从数据库中获取用户评分数据
    # 返回值是一个字典,格式为 {用户ID: {景点名称: 评分, ...}, ...}
    
    user_ratings = {}
    # 初始化一个空字典,用于存储所有用户的评分数据
    
    for travel in TravelInfo.objects.all():
        # 遍历数据库中的所有景点记录
        # TravelInfo.objects.all() 返回所有景点对象的查询集
        
        comments = json.loads(travel.comments)
        # 将当前景点的comments字段从JSON字符串解析为Python列表
        # travel.comments 在数据库中是JSON字符串,存储了该景点的所有用户评论
        # 例如: '[{"userId":1,"content":"很好","score":5}, ...]'
        
        for com in comments:
            # 遍历当前景点的每一条评论
            # com是一个字典,包含评论的详细信息
            
            try:
                com['userId']
                # 尝试访问评论中的'userId'字段
                # 这行代码本身没有赋值,只是用来检查字段是否存在
            except:
                continue
                # 如果评论中没有'userId'字段(比如爬取的评论中没有用户ID)
                # 则跳过这条评论,不进行处理
            
            if user_ratings.get(com['userId'],-1) == -1:
                # 检查这个用户是否已经在user_ratings字典中
                # user_ratings.get(key, default) 如果key存在返回对应的值,否则返回default
                # 这里返回-1表示用户不存在
                
                user_ratings[com['userId']] = {travel.title: com['score']}
                # 如果用户不存在,创建新条目
                # 键是用户ID,值是一个字典,包含当前景点名称和评分
                # travel.title是景点名称,com['score']是评分
            else:
                user_ratings[com['userId']][travel.title] = com['score']
                # 如果用户已存在,在用户的评分字典中添加当前景点的评分
                # 格式如: user_ratings[1]["故宫"] = 5
    
    return user_ratings
    # 返回构建好的用户评分字典

# ============================================================================

def user_bases_collaborative_filtering(user_id, user_ratings, top_n=3):
    # 定义基于用户的协同过滤推荐函数
    # 参数说明:
    #   user_id: 目标用户的ID,要为这个用户生成推荐
    #   user_ratings: 所有用户的评分数据,由getUser_ratings()返回
    #   top_n: 选取相似度最高的N个用户,默认值为3
    # 返回值:推荐给目标用户的景点列表
    
    # 获取目标用户的评分数据
    target_user_ratings = user_ratings[user_id]
    # 从所有用户评分字典中取出目标用户的评分数据
    # 格式如: {"故宫": 5, "长城": 4, ...}

    # 初始化一个字典,用于保存其他用户与目标用户的相似度得分
    user_similarity_scores = {}
    # 格式: {其他用户ID: 相似度得分, ...}

    # 将目标用户的评分转化为numpy数组
    target_user_ratings_list = np.array([
        rating for _, rating in target_user_ratings.items()
    ])
    # 列表推导式,提取目标用户对所有景点的评分值
    # target_user_ratings.items() 返回键值对,我们只需要值(评分)
    # 结果如: [5, 4, 0, 3]  (0表示该景点没有评分)
    # np.array() 将列表转换为NumPy数组,便于数学计算

    # 计算目标用户与其他用户之间的相似度得分
    for user, ratings in user_ratings.items():
        # 遍历所有用户及其评分数据
        # user是用户ID,ratings是该用户的评分字典
        
        if user == user_id:
            # 如果是目标用户自己
            continue
            # 跳过,不计算自己与自己的相似度
        
        # 将其他用户的评分转化为numpy数组
        user_ratings_list = np.array([ratings.get(item, 0) for item in target_user_ratings])
        # 重要:这里只考虑目标用户评分过的景点
        # 对于目标用户评分过的每个景点,获取当前用户的评分
        # 如果当前用户没有评分过该景点,用0填充
        # 结果是一个与target_user_ratings_list长度相同的数组
        
        # 计算余弦相似度
        similarity_score = cosine_similarity([user_ratings_list], [target_user_ratings_list])[0][0]
        # cosine_similarity() 是sklearn中的函数,计算两个向量的余弦相似度
        # 参数需要是二维数组,所以用[vector]包装
        # 返回值是一个二维数组,[0][0]取出相似度值
        # 相似度范围[-1,1],越接近1表示越相似
        
        user_similarity_scores[user] = similarity_score
        # 将计算出的相似度存入字典

    # 对用户相似度得分进行降序排序
    sorted_similar_user = sorted(user_similarity_scores.items(), key=lambda x: x[1], reverse=True)
    # user_similarity_scores.items() 返回 [(用户1,相似度1), (用户2,相似度2), ...]
    # sorted() 排序,key=lambda x: x[1] 指定按相似度排序
    # reverse=True 表示降序(相似度高的排前面)
    # 结果如: [('user3', 0.95), ('user5', 0.87), ('user2', 0.76), ...]

    # 选择 TOP N 个相似用户喜欢的景点作为推荐结果
    recommended_items = set()
    # 初始化一个空集合,用于存放推荐的景点
    # 使用集合可以自动去重
    
    for similar_user, _ in sorted_similar_user[:top_n]:
        # 遍历相似度最高的前N个用户
        # sorted_similar_user[:top_n] 取前N个元素
        # similar_user是用户ID,_是相似度(这里不需要)
        
        recommended_items.update(user_ratings[similar_user].keys())
        # 将这个相似用户评分过的所有景点名称加入推荐集合
        # user_ratings[similar_user].keys() 返回该用户评分过的景点名称列表
        # update() 方法将多个元素加入集合

    # 过滤掉目标用户已经评分过的景点
    recommended_items = [item for item in recommended_items if item not in target_user_ratings]
    # 列表推导式,遍历推荐集合中的每个景点
    # 只保留那些不在目标用户评分字典中的景点
    # 因为用户已经评分过的景点不需要再推荐

    return recommended_items
    # 返回最终的推荐景点列表

# ============================================================================

if __name__ == '__main__':
    # Python的特殊用法:当这个文件被直接运行时,执行下面的代码
    # 如果这个文件被其他文件导入,则不执行
    
    user_id = 1
    # 设置目标用户ID为1
    # 在实际系统中,这个ID可能来自当前登录用户
    
    user_ratings = getUser_ratings()
    # 调用getUser_ratings()函数,从数据库获取所有用户的评分数据
    
    recommended_items = user_bases_collaborative_filtering(user_id, user_ratings)
    # 调用协同过滤函数,为user_id生成推荐列表
    # 使用默认的top_n=3

代码功能总结

函数 作用 输入 输出
getUser_ratings 从数据库构建用户-评分矩阵 无(读取数据库) 用户评分字典
user_bases_collaborative_filtering 基于用户的协同过滤推荐 用户ID、评分数据、相似用户数 推荐景点列表

整体流程

  1. 初始化Django环境,连接数据库

  2. 从TravelInfo表的comments字段解析出所有用户的评分

  3. 构建用户-景点评分矩阵

  4. 为目标用户找到最相似的N个用户

  5. 从相似用户喜欢的景点中筛选出目标用户未评过的

  6. 返回推荐列表

相关推荐
沐硕1 小时前
Dietify 智能饮食推荐系统全解析 —— 当协同过滤遇上营养科学,构建你的私人饮食管家
spring boot·python·fastapi·多目标优化·饮食推荐·改进协同过滤
欣然~2 小时前
基于Python的自动化数据采集与语音播报系统设计与实现
python
小付爱coding2 小时前
跟着官网学LangChain【第02章:提示词和消息】
windows·python·langchain
菜鸡儿齐5 小时前
Unsafe方法学习
java·python·学习
老师好,我是刘同学8 小时前
Python执行命令并保存输出到文件
python
啵啵鱼爱吃小猫咪10 小时前
机械臂阻抗控制github项目-mujoco仿真
开发语言·人工智能·python·机器人
MaximusCoder10 小时前
等保测评命令——Centos Linux
linux·运维·经验分享·python·安全·centos
yunyun3212310 小时前
用Python生成艺术:分形与算法绘图
jvm·数据库·python
m0_6625779710 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python