ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python协同过滤电影推荐系统源码:毕设直接跑通

Python协同过滤电影推荐系统源码:毕设直接跑通 简介这份资源是Python基于协同过滤推荐算法的电影推荐系统完整源码包面向计算机相关专业正在做毕业设计的学生以及需要项目实战练习的学习者也可直接用作课程设计或期末大作业。项目经过严格调试下载即用能帮助读者省去从零搭建推荐系统的时间成本。压缩包共1197个文件约76.75MB其中22个py文件承载协同过滤核心算法与业务逻辑14个html、12个js与8个css构成前端交互界面4个csv与1个sqlite3、1个sql提供用户评分和电影数据支撑另有大量jpg图片用于页面展示。目前已有147人学习下载。读者可获得一套可直接运行的完整项目涵盖数据加载、相似度计算、推荐结果生成等关键环节并附带全部数据与数据库文件便于理解推荐流程、撰写论文或进行二次开发适合作为推荐算法入门与毕设落地的参考方案。1. 电影推荐系统源码拆包一份能直接跑起来的协同过滤毕设很多同学做毕设时最头疼的不是写代码而是数据对不上、算法跑不通、前端页面空白。这份 Python 基于协同过滤推荐算法的电影推荐系统源码把用户评分数据和电影信息都打包好了解压后改个路径就能跑。它解决的核心问题是用真实的用户-电影评分矩阵通过相似度计算找出兴趣相近的用户或电影再生成推荐列表。适合正在做计算机毕业设计、课程设计或期末大作业的同学也适合想练手推荐算法的开发者。整个项目包含 Bootstrap 前端样式、CSV 数据文件和 Python 后端逻辑结构清晰不是那种只有空壳的模板。2. 协同过滤到底怎么算从评分矩阵到相似度2.1 用户-物品评分矩阵的构建逻辑协同过滤的起点是一张二维表行是用户列是电影格子里是评分。这份源码里的users_resulttable.csv就是这张表。实际工程中用户不可能看完所有电影所以矩阵极其稀疏通常稀疏度在 95% 以上。我一般会先用 pandas 读进来看一眼形状和缺失情况再决定用哪种相似度。常见做法是先把数据转成pivot_table让 user_id 做索引、movie_id 做列、rating 做值。如果直接用原始 CSV 做遍历代码会又慢又容易出错。import pandas as pd # 读取用户评分数据 ratings pd.read_csv(users_resulttable.csv) # 构建用户-电影评分矩阵缺失值填 0 user_movie_matrix ratings.pivot_table( indexuser_id, columnsmovie_id, valuesrating ).fillna(0) print(user_movie_matrix.shape) # 查看矩阵维度 print(user_movie_matrix.head())这段代码的关键在pivot_table的三个参数index指定用户维度columns指定电影维度values指定评分值。fillna(0)把没评过分的格子填成 0表示“无评分”。注意填 0 和填均值是两种策略填 0 会让相似度计算偏向于“都没看过”的用户填均值则更中性。源码里用的是填 0适合数据量不大的毕设场景。2.2 相似度计算余弦、皮尔逊怎么选相似度决定了“谁和谁像”。余弦相似度看的是向量方向皮尔逊看的是线性相关性。在电影推荐里如果用户评分尺度差异大有人习惯打 3 分有人习惯打 5 分皮尔逊更稳。源码里用的是余弦相似度计算快适合稀疏矩阵。我一般会先跑余弦如果推荐结果明显偏向热门电影再换皮尔逊试试。from sklearn.metrics.pairwise import cosine_similarity # 计算用户之间的余弦相似度 user_similarity cosine_similarity(user_movie_matrix) # 转成 DataFrame 方便查看 user_similarity_df pd.DataFrame( user_similarity, indexuser_movie_matrix.index, columnsuser_movie_matrix.index ) # 查看与用户 1 最相似的 5 个用户 similar_users user_similarity_df[1].sort_values(ascendingFalse)[1:6] print(similar_users)cosine_similarity返回的是对称矩阵对角线是 1。sort_values(ascendingFalse)把最相似的用户排前面[1:6]跳过自己取前五个。这里有个坑如果某个用户只评了一部电影他的相似度会异常高或异常低通常要设一个最小评分数量阈值比如至少评过 5 部才参与计算。2.3 生成推荐列表的加权评分法有了相似用户下一步是预测目标用户对没看过的电影的评分。常用公式是预测分 相似用户评分加权平均。权重就是相似度。源码里用的是 Top-N 相似用户而不是全部用户这样能减少噪声。import numpy as np def recommend_movies(user_id, user_movie_matrix, user_similarity_df, top_n10): # 找到该用户没看过的电影 user_ratings user_movie_matrix.loc[user_id] unseen_movies user_ratings[user_ratings 0].index # 取最相似的 20 个用户 similar_users user_similarity_df[user_id].sort_values(ascendingFalse)[1:21] # 加权预测评分 scores {} for movie_id in unseen_movies: weighted_sum 0 similarity_sum 0 for sim_user, similarity in similar_users.items(): rating user_movie_matrix.loc[sim_user, movie_id] if rating 0: weighted_sum similarity * rating similarity_sum similarity if similarity_sum 0: scores[movie_id] weighted_sum / similarity_sum # 按预测分排序返回 Top-N return sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_n] # 给用户 1 推荐 10 部电影 recommendations recommend_movies(1, user_movie_matrix, user_similarity_df) print(recommendations)这段逻辑的核心是weighted_sum / similarity_sum即加权平均。top_n10控制推荐数量[1:21]控制参与预测的相似用户数。参数调大推荐更准但更慢调小速度快但可能漏掉长尾好片。我一般会从 20 开始试看推荐结果里有没有明显不相关的电影。3. 把源码跑起来环境、数据、前端三件事3.1 Python 环境与依赖安装拿到源码包后第一件事不是急着运行而是确认 Python 版本和依赖。这份项目用的是 Python 3.x依赖主要包括 pandas、numpy、scikit-learn、flask或 Django看具体实现。我一般会先建虚拟环境避免污染全局包。# 创建虚拟环境 python -m venv venv # 激活虚拟环境Windows venv\Scripts\activate # 激活虚拟环境macOS/Linux source venv/bin/activate # 安装核心依赖 pip install pandas numpy scikit-learn flask虚拟环境的好处是隔离毕设做完直接删掉文件夹就行。pip install后面跟的包名要按实际requirements.txt来如果源码里有这个文件直接pip install -r requirements.txt更省事。注意scikit-learn 版本不同cosine_similarity的返回值类型可能有差异建议用 0.24 以上。3.2 数据文件字段解读与路径配置源码包里的movie_info.csv和users_resulttable.csv是核心数据。movie_info.csv通常包含 movie_id、title、genres 等字段users_resulttable.csv包含 user_id、movie_id、rating。路径配置是新手最容易翻车的地方代码里写的是相对路径如果你在别的目录下运行就会报FileNotFoundError。import os # 获取当前脚本所在目录 base_dir os.path.dirname(os.path.abspath(__file__)) # 拼接数据文件路径 ratings_path os.path.join(base_dir, users_resulttable.csv) movies_path os.path.join(base_dir, movie_info.csv) # 读取时用绝对路径避免路径错误 ratings pd.read_csv(ratings_path) movies pd.read_csv(movies_path)os.path.abspath(__file__)拿到脚本的绝对路径os.path.join拼接子路径。这样无论从哪个目录启动都能找到数据文件。我见过太多毕设因为路径写死成C:\Users\xxx\Desktop\...而跑不起来的案例换成相对路径加os.path.join就能解决。3.3 前端页面与后端接口的对接这份源码带了 Bootstrap 样式包括bootstrap.css、main.css、star.css等。前端页面通常是一个搜索框加推荐列表后端用 Flask 暴露接口。启动方式一般是python app.py或flask run。启动后访问http://127.0.0.1:5000就能看到页面。from flask import Flask, render_template, request app Flask(__name__) app.route(/) def index(): return render_template(index.html) app.route(/recommend, methods[POST]) def recommend(): user_id int(request.form[user_id]) # 调用推荐函数 recs recommend_movies(user_id, user_movie_matrix, user_similarity_df) return render_template(result.html, recommendationsrecs) if __name__ __main__: app.run(debugTrue)render_template负责渲染 HTMLrequest.form拿表单数据。debugTrue方便调试但上线要关掉。前端样式里的star.css通常用来做星级评分展示headstyle.css控制头部布局。如果页面样式错乱先检查 CSS 文件路径是否正确再看浏览器控制台有没有 404。4. 避坑与排查那些让毕设卡三天的常见问题4.1 现象运行报错“KeyError: user_id”原因CSV 文件里的列名和代码里写的不一致。比如数据里是userId代码里写的是user_id。解决先用print(ratings.columns)看实际列名再统一改成代码里用的名字或者改代码适配数据。4.2 现象推荐结果全是同一部电影原因相似度矩阵计算时某个用户或电影被重复加权或者数据里有一部电影被所有人评了高分。解决检查user_movie_matrix是否有重复列用drop_duplicates去重同时给推荐结果加一个多样性过滤比如同一导演或类型最多推两部。4.3 现象前端页面能打开但推荐按钮没反应原因表单提交路径不对或者后端接口没启动。解决打开浏览器开发者工具看 Network 里 POST 请求是否 404 或 500。如果是 404检查 Flask 路由是否匹配如果是 500看后端控制台报错。4.4 现象数据量一大就内存溢出原因pivot_table生成的矩阵太大稠密矩阵占内存。解决改用稀疏矩阵scipy.sparse或者只取评分数量前 1000 的用户和电影做子集。毕设数据量一般不大但如果你自己换了 MovieLens 20M 数据集就要注意。4.5 现象相似度计算特别慢原因用了双重循环逐对计算。解决用cosine_similarity向量化计算或者用sklearn.metrics.pairwise的pairwise_distances。如果还慢考虑用numpy的矩阵运算替代 pandas 的loc循环。5. 进阶技巧让推荐结果更“像人推的”5.1 用加权相似度替代纯余弦纯余弦相似度对热门电影不公平因为热门电影被很多人评过容易和其他电影相似。我一般会加一个惩罚项相似度除以log(1 共同评分数)。这样共同评分少的电影对相似度会被压低减少噪声。import numpy as np def adjusted_similarity(user_movie_matrix): # 计算共同评分数量矩阵 binary_matrix (user_movie_matrix 0).astype(int) co_rating_count binary_matrix.T.dot(binary_matrix) # 计算余弦相似度 cosine_sim cosine_similarity(user_movie_matrix.T) # 加权调整 adjusted cosine_sim / np.log(1 co_rating_count) return adjustedbinary_matrix.T.dot(binary_matrix)得到电影之间的共同评分人数。np.log(1 co_rating_count)做平滑避免除零。这个调整能让推荐结果更偏向小众但质量高的电影。5.2 混合推荐协同过滤 基于内容纯协同过滤有个硬伤新电影没人评过就永远推不出来。解决办法是混合基于内容的推荐用电影的类型、导演、年份算相似度。源码里的movie_info.csv有 genres 字段可以拆成多热编码。from sklearn.feature_extraction.text import TfidfVectorizer # 把 genres 当成文本处理 tfidf TfidfVectorizer(token_patternr(?u)\b\w\b) genre_matrix tfidf.fit_transform(movies[genres].fillna()) # 计算电影内容相似度 content_similarity cosine_similarity(genre_matrix)TfidfVectorizer把类型字符串转成向量token_pattern匹配单词。这样即使没有评分也能根据类型推荐。实际使用时可以把协同过滤的预测分和内容相似度加权求和权重按场景调我一般设 0.7 和 0.3。5.3 验证推荐效果的三个指标毕设答辩时老师常问“你怎么知道推荐得准”。可以用留一法从每个用户的评分里抽一条藏起来用剩下的训练看推荐列表里有没有这条。指标用命中率HR和归一化折损累计增益NDCG。指标含义计算方式HRK前 K 个推荐里命中隐藏电影的比例命中数 / 用户数NDCGK考虑命中位置的排序质量折损累计增益归一化覆盖率推荐列表里不同电影占比去重电影数 / 总电影数HR 看“有没有推对”NDCG 看“推得靠不靠前”覆盖率看“是不是只推热门”。三个指标一起看才能说明推荐系统不是摆设。5.4 一个我踩过的坑别在测试集上调参刚开始做推荐时我拿全部数据算相似度再拿同一批数据评估结果 HR 高达 0.9答辩时被老师问“你是不是过拟合了”。后来改成先划分训练集和测试集在训练集上算相似度测试集上评估HR 掉到 0.3 但真实可信。从那以后我每次做推荐实验都强制先切分数据再动任何参数。希望帮到你。本文还有配套的精品资源点击获取
返回列表