首页/新闻资讯/正文详情

基于Python的商品推荐系统毕设:从协同过滤到Flask Web服务实战

发布时间:2026/9/28 1:40:53 来源:云帆数科 栏目:资讯中心
基于Python的商品推荐系统毕设:从协同过滤到Flask Web服务实战
简介这份毕业设计资源是一套基于Python的商品推荐系统完整源码面向计算机科学专业毕业生及希望实践推荐算法的学习者帮助其完成从数据预处理到系统部署的全流程开发。压缩包共216个文件约91.74MB以83个png与63个jpg界面截图、26个py脚本、14个html页面及9个js、6个css等前端资源为主另含sqlite3数据库与少量xml配置覆盖数据清洗、模型训练、评估与Web展示等模块。目前已有296人学习下载。项目涵盖协同过滤、基于内容的推荐及深度学习模型实现配套数据预处理、特征工程、模型训练与评估脚本并附README说明运行方式。通过阅读源码读者可掌握用户行为日志处理、相似度计算、评价指标应用及API接口集成等技能适合作为毕业设计参考或推荐系统入门实战材料。1. 商品推荐系统毕设从协同过滤到可演示的Web服务很多同学拿到「基于Python的商品推荐系统」这个毕设题目时第一反应是去搜免费python源码大全找到一个能跑的脚本改改就交差。但真正答辩时被问到「你的推荐算法怎么处理冷启动」「为什么用这个相似度公式而不是余弦」就答不上来了。这个题目的核心不是写一个能出结果的脚本而是构建一条从数据到算法再到可交互界面的完整链路让评委看到你理解推荐系统的每个环节。适合正在做计算机毕业设计、大数据毕业设计选题的同学也适合想通过一个完整项目入门python数据分析与可视化的初学者。接下来我会按实际落地顺序把数据准备、算法选型、Web服务搭建和避坑经验全部拆开讲清楚。2. 数据从哪来、怎么洗推荐系统的地基2.1 公开数据集选型与下载后的第一轮清洗商品推荐系统最常用的公开数据集是MovieLens和Amazon Reviews。MovieLens的好处是自带用户-物品-评分三列结构量级从100K到25M都有适合毕设演示。Amazon Reviews更贴近真实商品场景但需要自己处理JSON嵌套格式。我一般会选MovieLens 100K作为起步因为它的数据干净、文档全答辩时也好解释。下载后第一件事不是直接喂给算法而是做一轮基础清洗。核心检查三件事评分是否有缺失、用户和物品的ID是否连续、时间戳格式是否统一。import pandas as pd # 读取MovieLens 100K的ratings文件 ratings pd.read_csv(u.data, sep\t, names[user_id, item_id, rating, timestamp]) # 检查缺失值 print(ratings.isnull().sum()) # 检查评分分布确认没有异常值 print(ratings[rating].describe()) # 过滤掉评分次数少于5次的用户和物品降低稀疏度 user_counts ratings[user_id].value_counts() item_counts ratings[item_id].value_counts() ratings ratings[ratings[user_id].isin(user_counts[user_counts 5].index)] ratings ratings[ratings[item_id].isin(item_counts[item_counts 5].index)] print(f清洗后剩余记录数{len(ratings)})这段代码的逻辑是先确认数据没有空值再通过describe看评分范围是否在预期内MovieLens是1-5分最后过滤掉交互过少的用户和物品。参数 5这个阈值不是固定的如果你的数据集本身很稀疏可以降到3如果数据量大可以提到10。过滤后记录数会减少但推荐质量会提升因为协同过滤对长尾数据本身就不擅长。2.2 构建用户-物品评分矩阵的两种方式清洗完数据后需要把它转成算法能吃的矩阵格式。常见做法有两种一种是pivot成稠密矩阵适合数据量小的情况另一种是保留稀疏格式用scipy的csr_matrix。import numpy as np from scipy.sparse import csr_matrix # 方式一pivot成稠密矩阵适合用户和物品都不超过几千的情况 dense_matrix ratings.pivot(indexuser_id, columnsitem_id, valuesrating).fillna(0) print(f稠密矩阵形状{dense_matrix.shape}) # 方式二构建稀疏矩阵推荐内存占用小 user_ids ratings[user_id].astype(category) item_ids ratings[item_id].astype(category) sparse_matrix csr_matrix( (ratings[rating].values, (user_ids.cat.codes, item_ids.cat.codes)) ) print(f稀疏矩阵形状{sparse_matrix.shape}非零元素{sparse_matrix.nnz})稠密矩阵的好处是直观可以直接用pandas操作但缺点是当用户数×物品数很大时内存会爆。稀疏矩阵只存非零值适合真实场景。参数方面fillna(0)表示未评分的物品用0填充这在后续计算相似度时需要注意——0不代表用户真的打了0分而是缺失。我一般会在计算相似度时用mask把缺失位置排除掉而不是简单地把0当评分。注意如果用稠密矩阵一定要确认内存够用。一个10000×10000的float64矩阵就是800MB很容易把笔记本跑崩。3. 推荐算法选型协同过滤、矩阵分解还是深度学习3.1 基于物品的协同过滤最适合毕设起步的方案协同过滤分UserCF和ItemCF两种。UserCF是找相似用户ItemCF是找相似物品。对于商品推荐场景ItemCF更稳定因为物品的相似度变化比用户兴趣变化慢。而且ItemCF的可解释性强——「因为你买了A所以推荐相似的B」答辩时好讲。核心步骤是计算物品之间的相似度矩阵然后根据用户历史评分加权预测。from sklearn.metrics.pairwise import cosine_similarity # 转置成物品-用户矩阵 item_user_matrix sparse_matrix.T # 计算物品间余弦相似度 item_similarity cosine_similarity(item_user_matrix) print(f相似度矩阵形状{item_similarity.shape}) def recommend_item_cf(user_id, item_similarity, ratings, top_n10): 基于物品协同过滤的推荐函数 # 获取用户已评分的物品 user_rated ratings[ratings[user_id] user_id] if user_rated.empty: return [] # 对每个已评分物品找相似物品并加权 scores {} for _, row in user_rated.iterrows(): item_idx row[item_id] rating row[rating] similar_items item_similarity[item_idx] for sim_item_idx, sim_score in enumerate(similar_items): if sim_item_idx not in user_rated[item_id].values: scores[sim_item_idx] scores.get(sim_item_idx, 0) sim_score * rating # 按分数排序返回top_n sorted_items sorted(scores.items(), keylambda x: x[1], reverseTrue) return sorted_items[:top_n]这段代码的关键参数是top_n控制返回推荐数量一般设10-20。相似度计算用余弦相似度因为它在稀疏矩阵上表现稳定。注意scores字典的累加逻辑用户对某物品评分越高相似物品的推荐分数也越高这是加权思想。实际运行时如果物品数量超过几万cosine_similarity会非常慢这时候需要改用近似最近邻如faiss或者只计算top-K相似物品。3.2 矩阵分解SVD作为进阶对比方案如果毕设要求体现「算法对比」可以加一个SVD方案。SVD把用户-物品矩阵分解成用户隐向量和物品隐向量通过隐向量内积预测评分。好处是能处理稀疏数据坏处是可解释性差。from scipy.sparse.linalg import svds # 对稀疏矩阵做SVD分解k是隐向量维度 U, sigma, Vt svds(sparse_matrix, k50) sigma np.diag(sigma) # 预测评分矩阵 predicted_ratings np.dot(np.dot(U, sigma), Vt) def recommend_svd(user_id, predicted_ratings, ratings, top_n10): 基于SVD的推荐函数 user_rated_items ratings[ratings[user_id] user_id][item_id].values user_scores predicted_ratings[user_id] # 排除已评分物品 user_scores[user_rated_items] -np.inf top_items np.argsort(user_scores)[-top_n:][::-1] return top_items参数k50是隐向量维度太小会欠拟合太大会过拟合。一般从20到200之间调可以用交叉验证选最优。SVD的预测结果包含负值这是正常的因为矩阵分解不保证非负。实际使用时可以只取top-N不用关心绝对值。提示SVD在数据量小的时候效果可能不如ItemCF因为隐向量需要足够多的交互数据才能学到有意义的表示。毕设里两个都做对比RMSE和召回率论文里就有东西写了。4. 用Flask把推荐结果变成可演示的Web服务4.1 最小可运行的服务端代码算法跑通后需要一个界面让评委看到推荐结果。Flask是最轻量的选择几十行代码就能搭起来。核心是三个路由首页展示商品列表、推荐接口返回JSON、用户评分提交。from flask import Flask, render_template, request, jsonify import pandas as pd import numpy as np app Flask(__name__) # 加载预计算好的数据和相似度矩阵 ratings pd.read_csv(cleaned_ratings.csv) item_similarity np.load(item_similarity.npy) app.route(/) def index(): 首页展示热门商品 popular_items ratings.groupby(item_id)[rating].mean().sort_values(ascendingFalse).head(20) return render_template(index.html, itemspopular_items.index.tolist()) app.route(/recommend/int:user_id) def recommend(user_id): 推荐接口返回指定用户的推荐列表 # 这里调用前面写的recommend_item_cf函数 recommendations recommend_item_cf(user_id, item_similarity, ratings, top_n10) return jsonify({user_id: user_id, recommendations: [int(i) for i, _ in recommendations]}) app.route(/rate, methods[POST]) def rate(): 评分接口接收用户对新物品的评分 data request.get_json() user_id data[user_id] item_id data[item_id] rating data[rating] # 追加到ratings并保存实际项目应该写数据库 new_row pd.DataFrame({user_id: [user_id], item_id: [item_id], rating: [rating]}) new_row.to_csv(cleaned_ratings.csv, modea, headerFalse, indexFalse) return jsonify({status: ok}) if __name__ __main__: app.run(debugTrue, port5000)这段代码的逻辑很直接首页展示热门商品作为兜底推荐推荐接口根据user_id返回个性化结果评分接口让用户能实时反馈。参数port5000是Flask默认端口如果被占用可以改成8080。debugTrue只在开发时用部署时要关掉。4.2 前端模板与交互的最小实现前端不需要太复杂一个表格展示商品、一个按钮触发推荐就够了。用Jinja2模板渲染。!-- templates/index.html -- !DOCTYPE html html head title商品推荐系统/title /head body h1热门商品/h1 ul {% for item in items %} li商品ID: {{ item }} button onclickgetRecommend({{ item }})查看相似推荐/button /li {% endfor %} /ul h2为你推荐/h2 div idrecommendations/div script function getRecommend(itemId) { fetch(/recommend/1) // 这里简化成固定用户1 .then(response response.json()) .then(data { document.getElementById(recommendations).innerText 推荐商品ID: data.recommendations.join(, ); }); } /script /body /html前端逻辑是点击按钮后调用推荐接口把返回的商品ID列表展示出来。实际毕设中可以做得更漂亮比如用ECharts做评分分布图或者用Bootstrap美化表格。但核心交互就是「点击-请求-展示」这个闭环。注意Flask自带的开发服务器不能用于生产环境毕设演示够用但如果要部署到服务器让外网访问需要用gunicorn或uwsgi。5. 避坑与排查毕设答辩前必须检查的5个问题5.1 推荐结果全是热门商品现象不管给哪个用户推荐返回的都是那几个评分最高的商品。原因相似度矩阵计算时没有排除用户已评分的物品或者热门商品因为评分人数多导致相似度普遍偏高。解决在推荐函数里加一行过滤把用户已经评分过的物品从候选集里去掉。另外可以对相似度做归一化或者用TF-IDF加权降低热门物品的权重。5.2 冷启动用户返回空列表现象新用户没有历史评分推荐接口返回空数组。原因协同过滤依赖用户历史行为没有历史就无法计算相似度。解决加一个兜底策略——如果用户评分记录少于3条直接返回热门商品列表。这也是工业界常用的做法叫「非个性化推荐」。5.3 内存溢出导致程序崩溃现象运行相似度计算时程序被系统杀掉或者报MemoryError。原因用了稠密矩阵或者物品数量太大导致相似度矩阵是N×N的。解决改用稀疏矩阵相似度计算只保留top-K。如果物品超过1万考虑用faiss做近似最近邻搜索或者只计算与目标物品最相似的100个。5.4 评分数据追加后推荐结果没变化现象通过接口提交了新评分但再次请求推荐时结果和之前一样。原因相似度矩阵是预计算并保存成npy文件的新评分没有触发重新计算。解决毕设演示可以加一个「重新训练」按钮手动触发相似度矩阵更新。或者改成增量更新但实现复杂度高不建议在毕设里做。5.5 答辩时被问「为什么用余弦相似度」现象评委问相似度公式的选择理由答不上来。原因只抄了代码没理解背后的数学。解决记住一句话——余弦相似度衡量的是方向一致性对评分量纲不敏感。比如用户A打分普遍偏高都是4-5分用户B打分普遍偏低都是1-2分但他们对物品的偏好顺序一致余弦相似度依然会很高。皮尔逊相关系数则会更进一步减去均值消除用户打分偏置。毕设里用余弦就够了但要知道皮尔逊的存在。6. 让推荐结果可解释一个加分技巧答辩时如果能把推荐理由展示出来会比只返回商品ID高一个档次。ItemCF天然支持这个——因为你知道是哪个已评分物品贡献了推荐分数。def recommend_with_reason(user_id, item_similarity, ratings, top_n10): 带推荐理由的ItemCF user_rated ratings[ratings[user_id] user_id] scores {} reasons {} for _, row in user_rated.iterrows(): item_idx row[item_id] rating row[rating] similar_items item_similarity[item_idx] for sim_item_idx, sim_score in enumerate(similar_items): if sim_item_idx not in user_rated[item_id].values: scores[sim_item_idx] scores.get(sim_item_idx, 0) sim_score * rating # 记录贡献最大的来源物品 if sim_item_idx not in reasons or sim_score reasons[sim_item_idx][1]: reasons[sim_item_idx] (item_idx, sim_score) sorted_items sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_n] result [] for item_id, score in sorted_items: source_item, sim reasons[item_id] result.append({ item_id: item_id, score: round(score, 2), reason: f因为你评分了商品{source_item}相似度{sim:.2f} }) return result这段代码在计算分数的同时记录了每个推荐物品的「主要贡献来源」。返回结果里带上reason字段前端展示时就能写「因为你喜欢A所以推荐B」。参数方面reasons字典存的是贡献最大的那个来源物品也可以改成存top-3来源展示更丰富。我自己的习惯是毕设代码里凡是能加解释的地方都加上因为答辩老师不一定懂推荐算法但他们能看懂「因为…所以…」的逻辑。这个技巧花不了多少时间但能让你的系统从「能跑」变成「能讲」。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

入侵检测源码复现:KDD99数据集与CNN模型评估指南
入侵检测源码复现:KDD99数据集与CNN模型评估指南

简介:这份基于Python机器学习的网络入侵检测系统源码,源自个人毕业设计项目,评审分达到98分,所有代码均经过严格调试可正常运行,主要面向计算机、自动化等相关专业的学生或从业者,尤其适合用作期末课程设计… · 2026/9/28 1:40:53

EDA版本管理实战:从嘉立创/立创版本陷阱到稳定交付
EDA版本管理实战:从嘉立创/立创版本陷阱到稳定交付

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:40:53

KiCAD+ngspice入门指南:用分压电路跑通SPICE仿真全流程
KiCAD+ngspice入门指南:用分压电路跑通SPICE仿真全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 1:40:53

DDR5 2N模式与1N模式详解:原理、切换与实战验证
DDR5 2N模式与1N模式详解:原理、切换与实战验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:11

VisionMaster与PLC触发方式选型:IO硬触发、Modbus软触发与TCP触发实战
VisionMaster与PLC触发方式选型:IO硬触发、Modbus软触发与TCP触发实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:11

Pixhawk V5与V6X引脚分布避坑指南:从炸机案例到载板设计实战
Pixhawk V5与V6X引脚分布避坑指南:从炸机案例到载板设计实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:10

ESP32S3开发板刷小智AI固件,打造多语言语音助手实战指南
ESP32S3开发板刷小智AI固件,打造多语言语音助手实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:10

YOLOv5+DeepSORT车辆跟踪系统:违停/逆行检测与车流量统计
YOLOv5+DeepSORT车辆跟踪系统:违停/逆行检测与车流量统计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:09

逻辑器件输出电阻对串联电阻设计与LED限流功耗的影响
逻辑器件输出电阻对串联电阻设计与LED限流功耗的影响

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/28 2:11:03

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

制作网页比较方便的软件怎么选?一文搞懂避坑指南
制作网页比较方便的软件怎么选?一文搞懂避坑指南

制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量

婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略

济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码