ARTICLE DETAIL

资讯详情

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

Python电影推荐系统:基于协同过滤算法的设计与实现

Python电影推荐系统:基于协同过滤算法的设计与实现 简介基于协同过滤推荐算法的电影推荐系统完整毕业设计项目适合计算机、通信、人工智能、自动化等专业学生用于毕业设计或课程设计学习。项目采用Python与Django框架构建涵盖用户登录注册、电影信息管理、协同过滤推荐引擎、评分预测等核心功能代码经过调试且自带数据库脚本可直接部署运行。资源包共726个文件约19.55MB包含164个JavaScript、41个Vue、53个CSS等前端构建文件39个Python源码及编译文件以及2个SQL数据库脚本前后端结构清晰便于二次开发。已有223人在线学习浏览项目答辩评审分达98分具备较高参考价值。对于想掌握推荐系统实现流程、或需要完整毕业设计案例的读者这套源码在算法落地、工程组织与界面交互方面都能提供直观借鉴同时保留了可运行的启动脚本降低环境搭建门槛。1. 为什么毕业设计选电影推荐系统它把算法、数据库和 Web 串成了一条线如果你正在为毕业设计选题发愁又恰好学过 Python那么“python基于协同过滤推荐算法的电影推荐系统源码数据库”这个题目几乎是性价比最高的选择之一。它不像人脸识别那样需要昂贵的 GPU 和深度学习框架也不像电商系统那样只有增删改查、毫无算法含量。它恰好卡在一个黄金位置用到协同过滤这个经典推荐算法需要自己设计用户-电影评分数据库表结构还要用 Flask 或 Django 搭一个能演示的 Web 页面。一套做下来算法、数据库、Web 开发三块能力全部展示在答辩 PPT 上评委问哪个方向你都有话可说。这个系统解决的核心问题很朴素当用户看过的电影有限时怎么从几万部片子里挑出他可能喜欢的几部。协同过滤的思路不是分析电影内容而是利用“其他相似用户的行为”来猜当前用户的喜好。你不需要懂电影的分类、导演或剧本只需要一张用户对电影的评分表算法就能自动找出“和你口味相似的人”然后把那些人看过且打了高分的电影推荐给你。这就是协同过滤最本质的、也是最好向答辩老师解释的逻辑。这篇文章会从数据库表设计讲到相似度计算公式再讲到 Flask 接口和前端页面最后给你一份踩坑清单。整个过程不需要 GPU不需要分布式集群一台普通的笔记本就能跑通。如果你是零基础起步跟着这篇文章走完你得到的不仅是一份能运行的代码更是一套能讲清楚原理的毕业设计答辩素材。2. 设计数据库表结构评分表才是协同过滤的心脏2.1 三张核心表用户表、电影表、评分表任何推荐系统都离不开数据。对于电影推荐这个场景你至少需要三张表。用户表存储用户基本信息电影表存储电影元数据评分表记录用户对电影的评分行为。很多人第一次做的时候会忽略评分表的重要性只把它当成一个普通的关联表这是不对的。协同过滤算法的输入完全来自这张评分表——它必须包含三个字段用户 IDuser_id、电影 IDmovie_id、评分值rating。这三列构成了算法的“用户-物品评分矩阵”。我一般会在 MySQL 中这样建表。用户表相对简单重点在 id 自增主键和唯一用户名CREATE DATABASE IF NOT EXISTS movie_recommend DEFAULT CHARSET utf8mb4; USE movie_recommend; CREATE TABLE users ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB;这里把 username 设为 UNIQUE 是为了防止注册时重复用户名。password 字段建议存哈希值不要存明文。虽然是毕业设计但代码规范一点答辩时能加印象分。created_at 用 TIMESTAMP 类型并且 DEFAULT CURRENT_TIMESTAMP插入数据时不用手动维护时间字段。电影表字段略多一些但也不需要太多。重点要保证 movie_id 是主键title 是电影名。genres 用简单的字符串存储即可比如“Comedy|Romance”多个类型用竖线分隔。这个格式在后面的推荐结果展示中可以方便地拆分。CREATE TABLE movies ( movie_id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(200) NOT NULL, genres VARCHAR(100), release_year YEAR, rating_avg DECIMAL(3,2) DEFAULT 0.00, rating_count INT DEFAULT 0 ) ENGINEInnoDB;rating_avg 和 rating_count 这两个字段很多人会忽略。它们不是协同过滤算法的输入但在推荐结果展示时非常重要——你可以根据评分和热度对候选电影做二次排序。比如协同过滤算出了 100 部候选电影你可以按 rating_avg 排序取前 10或者结合“看过人数超过一定阈值”来过滤掉那些只有极少数人看过的小众冷门片。评分表是核心它其实就是协同过滤算法的数据源。建表语句如下CREATE TABLE ratings ( user_id INT NOT NULL, movie_id INT NOT NULL, rating TINYINT NOT NULL, timestamp INT NOT NULL, PRIMARY KEY (user_id, movie_id), FOREIGN KEY (user_id) REFERENCES users(user_id), FOREIGN KEY (movie_id) REFERENCES movies(movie_id) ) ENGINEInnoDB;这里做两个约束主键是 (user_id, movie_id) 的联合主键防止同一个用户对同一部电影重复评分外键保证评分记录不会指向不存在的用户或电影。字段类型上rating 用 TINYINT 就够了取值一般只有 1 到 5 分。timestamp 用 INT 类型存 Unix 时间戳比 DATETIME 更轻量后续做时间衰减等高级处理时也更灵活。2.2 用 Python 批量导入 MovieLens 数据集自己造数据不现实毕业设计通常用 MovieLens 公开数据集。你可以在网上下载 ml-latest-small.zip解压后有 ratings.csv、movies.csv、tags.csv 和 links.csv 四个文件。对于毕设来说只需要 ratings.csv 和 movies.csv 就够了。ratings.csv 大约 10 万条评分数据覆盖 600 多个用户和 9000 多部电影。这个数据量对于单机 Python 来说是完全没有压力的。下载之后写一个 Python 脚本来导入 MySQL。注意 Python 默认的 csv 模块读取时文件的编码是 UTF-8但 MovieLens 的 CSV 文件是用 UTF-8 编码的直接读就行。import csv import pymysql conn pymysql.connect( hostlocalhost, userroot, password123456, databasemovie_recommend, charsetutf8mb4 ) cursor conn.cursor() # 先导入电影表 with open(movies.csv, r, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: movie_id int(row[movieId]) title row[title] genres row[genres] cursor.execute( INSERT INTO movies (movie_id, title, genres) VALUES (%s, %s, %s), (movie_id, title, genres) ) conn.commit() cursor.close() conn.close() print(电影数据导入完成)导入完成后可以验证一下SELECT COUNT(*) FROM movies如果 movieId 有重复会插入失败。MovieLens 的 movieId 本来就是全局唯一的所以用原始 ID 作为主键没问题。注意在刚才建 movies 表时我把主键定义成了 AUTO_INCREMENT 的 movie_id如果直接使用 MovieLens 的 ID需要把建表语句改成movie_id INT PRIMARY KEY去掉 AUTO_INCREMENT。否则你插入的 ID 和自增 ID 会冲突导致数据错乱。实际导入时要根据数据源来调整建表约束。数据导入是第一个容易翻车的地方。VSCode 中配置 Python 环境时pymysql 可能还没安装。先执行 pip install pymysql再跑导入脚本。如果连接时报 “Access denied for user”大概率是 MySQL root 密码不对或者字符集没配对。3. 协同过滤算法实现基于用户的与基于物品的两条路线对比3.1 两种算法各自的计算逻辑与选型理由协同过滤算法分成两个流派基于用户的协同过滤UserCF和基于物品的协同过滤ItemCF。UserCF 的思想是“人以群分”——找到和目标用户兴趣最相似的一批用户把他们喜欢而目标用户没看过的电影推荐过来。ItemCF 的思想是“物以类聚”——如果两部电影被同一批用户喜欢那这两部电影就被认为是相似的比如《教父》和《美国往事》经常被同一波人打高分那么你看过《教父》系统就把《美国往事》推给你。在实现层面两者的计算过程大体分为三步。第一步构建“用户-物品”矩阵或“物品-用户”倒排表。第二步计算相似度矩阵。第三步根据相似用户或相似物品生成 Top-N 推荐列表。区别只是第二步和第三步的计算对象换了一下UserCF 计算用户与用户之间的相似度再找相似用户看过的电影ItemCF 计算电影与电影之间的相似度再找与用户看过的电影相似的影片。对于百万级以下的数据量我建议用 ItemCF。原因有两条。第一电影的数量远小于用户数量时物品相似度矩阵的维护成本更低。第二 ItemCF 推荐结果的可解释性更强——“因为你喜欢《盗梦空间》所以推荐《星际穿越》”这个理由在答辩时一讲就懂。如果网站用户量达到千万级别物品相似度矩阵也会膨胀得非常厉害那时候就需要用离线计算和定期更新来缓解了。3.2 相似度计算的三种公式余弦、皮尔逊、杰卡德相似度计算是协同过滤的灵魂。最常见的三种公式余弦相似度、皮尔逊相关系数、杰卡德相似系数。余弦相似度的公式是similarity (A·B) / (|A| × |B|)。其中 A 和 B 是两个向量。在电影推荐中这两个向量就是两个用户对所有电影的评分向量。比如用户 1 对三部电影打分为 [5, 3, 0]用户 2 打分为 [4, 3, 0]0 代表没看过。余弦相似度衡量的是这两个向量在方向上的接近程度对评分的绝对值不敏感。也就是说一个用户打分普遍偏高、一个用户打分普遍偏低他们仍然可能相似。皮尔逊相关系数则是对余弦相似度的一种改进。它在计算之前先减去各自的平均分消除用户打分尺度的差异。这个改进在电影推荐场景中很重要因为有的人习惯全打高分有的人习惯全打低分。用余弦相似度算可能把他们误判为不相似而皮尔逊能抓住他们的真实相关性。杰卡德相似系数计算的是交集除以并集。公式是J(A,B) |A∩B| / |A∪B|。它只关心两个用户是否看过同一部电影不关心具体评分多少。通常在数据非常稀疏、评分行为很少时用这个公式比较合适。在实际代码中我不会自己手写矩阵运算而是直接用 pandas 读取评分表并生成透视表import pandas as pd import numpy as np df pd.read_sql_query(SELECT user_id, movie_id, rating FROM ratings, conn) rating_matrix df.pivot_table( indexuser_id, columnsmovie_id, valuesrating ).fillna(0) print(评分矩阵形状:, rating_matrix.shape)这段代码生成的行是用户 ID列是电影 ID值是评分的二维表格。没有评分的位本文还有配套的精品资源点击获取
返回列表