首页 / 资讯中心 / 文章详情

Python+Django协同过滤商品推荐系统设计与实现

Python+Django协同过滤商品推荐系统设计与实现 ★ FEATURED ARTICLE
1. 项目整体设计与思路拆解每年到毕业季我都会接触到不少做推荐系统方向的同学。这个基于python的协同过滤商品推荐系统从我经手过的多个相似项目来看基本可以定位为一个标准的信息管理系统叠加推荐算法模块的组合型课题。说白了大家想要的不是纯算法研究而是一个能跑、能演示、能写进论文的系统成品同时算法部分又不能太薄弱——否则答辩时老师随便问一个你是怎么算相似度的就把人问住了。1.1 核心需求解析这个课题到底要做什么先把这个题目拆开看。它的关键词有四个维度Django后端框架、Python开发语言、协同过滤推荐算法、商品推荐系统业务场景。这意味着你要交付的不是一个简单的CRUD管理系统而是要让人看到系统里有商品数据能管理之外还能看到用户的行为被记录并被分析、最终产生个性化推荐结果这三个层次。以我实际带过的一个模拟项目X为参考这类系统的典型功能清单大概是这样的用户端注册登录、商品浏览、商品搜索、商品详情、加入购物车、下单、收藏/点赞行为记录、推荐结果页管理端商品分类管理、商品管理、用户管理、订单管理、数据统计算法层基于用户的协同过滤、基于物品的协同过滤、相似度矩阵计算、Top-N推荐生成辅助功能用户行为埋点浏览记录、评分记录、购买记录、推荐结果解释如因为你看过A所以推荐B一份好的开题报告或任务书通常就是围绕这几个模块展开的。如果你的题目描述里只提到了协同过滤商品推荐系统没有细分功能那么以上这份清单就是你搭建设计文档的最佳起点。1.2 技术选型背后的逻辑为什么是Django而不是别的在我经手过的毕设项目里Django出镜率极高这不是偶然。对大多数做毕设的同学来说Django有三个无法拒绝的优势。第一个优势是全家桶式的开发体验。ORM对象关系映射层帮你去掉了大量写SQL的精力Admin后台几乎是免费送的——你只需要在admin.py里注册一下数据模型一个可用的管理后台就出来了这对商品管理、用户管理这类功能来说简直是量身定做。对于不擅长前端或者不想花太多时间在后端管理页面的同学来说这个优势极其致命。第二个优势是模板和静态资源处理的便捷性。商品推荐系统注定要有大量的商品图片、详情页、列表页。Django的模板继承机制配合Bootstrap这类前端框架可以在非常短的时间内拼出一个看起来还算完整的前端页面。我曾经帮一个同学从零搭过一个商品推荐Demo总共用了不到两小时就把首页、商品列表、详情页全部跑通了。第三个优势是Python生态对算法实现的天然支持。协同过滤的核心是计算相似度矩阵、做排序、取Top-N。Python的列表推导式、NumPy的矩阵运算、Pandas的数据处理都是做这些事情的本命工具。你需要做的只是把算法代码写好然后在Django的视图函数里调用它把结果传入模板渲染出来。注意如果你的项目时间非常紧比如只剩两周不要轻易去换Flask或者FastAPI另起炉灶。不是它们不好而是Django的Admin后台和ORM实在能帮你省下太多时间。FastAPI性能确实好但毕设答辩看的是完整度和逻辑自洽技术栈冷门不一定是加分项。1.3 协同过滤选型的为什么基于物品和基于用户的取舍协同过滤算法本身分为两大类基于用户User-Based和基于物品Item-Based还有更进阶的矩阵分解如SVD。作为毕设项目你必须掌握这两个基础算法的区别还要能说出来我为什么用这个不用那个。基于用户的协同过滤核心思路是找相似的人。如果用户A和用户B历史上对一批商品的评分/购买行为高度一致那么A买过而B没买过的商品就有很大概率被推荐给B。这个算法适合用户规模相对较小、用户群体特征明显的场景比如早期的社交网络推荐。基于物品的协同过滤核心思路是找相似的物品。它的出发点是如果大量用户在买了商品X之后又买了商品Y那么X和Y就存在关联关系。比如你在某电商平台看中了一款球鞋页面底部会出现买过这款的用户还看过——背后很可能就是Item-Based协同过滤在起作用。在我接触的毕设项目中我一般建议主推基于物品的协同过滤。原因有两个第一商品数量通常比用户数量更稳定。电商平台每天可能有海量新订单但商品的种类在一定周期内波动不会太大。物品相似度矩阵可以离线计算、定时更新系统压力小这在写系统设计章节时非常加分。第二推荐结果更容易解释。基于物品的协同过滤在给用户推商品时可以带一句因为您浏览过/购买过某商品所以推荐你相关商品。这种解释在论文里、在答辩演示里、在系统截图里都显得非常有理有据。当然这不代表基于用户的算法不需要实现。市面上很多完整的毕设源码会把两种方法都实现出来然后放在同一个推荐服务里做对比测试。这样你在论文里可以多写一个实验对比章节工作量既充实答辩时谈资也多。2. 核心功能模块与数据模型设计这个环节做得好不好直接决定你后续编码是否顺畅。我不建议一上来就写代码先把数据库表设计清楚Django的模型写起来就是填空。2.1 用户行为数据怎么建模Rating是灵魂很多人对推荐系统的数据库设计有一个误区以为有用户表、商品表、订单表就差不多了。这个想法相当危险——因为没有核心的行为数据表你的协同过滤算法就是无水之源、无米之炊。推荐系统的核心资产不是商品信息而是用户行为。所以你必须设计一张能够承载用户对商品的反馈的表我习惯叫它UserRating表或者UserBehavior表。这张表至少要包含以下字段字段名类型说明id自增主键主键user_id外键关联用户表item_id外键关联商品表rating浮点型用户对商品的评分如1-5分behavior_type整型或字符型行为类型浏览/收藏/加购/购买create_time时间戳行为发生时间为什么评分和行为类型要放在同一张表里这是一个实操中总结出来的经验。如果用户只是浏览了商品但没有评分rating可以默认为空或者0如果用户明确打了分那rating就有值。这样一张表既承载了显式反馈评分又承载了隐式反馈浏览/购买行为在做算法时灵活性非常大。比如基于物品的协同过滤一般来说只用购买行为就够了但如果你需要应对用户没有购买记录的情况浏览行为的权重同样能派上用场。商品表的设计也要稍加用心。除了常规的id、名称、类别、价格、库存外我建议额外加一行销量或者热度字段。原因很简单——新建商品没有任何行为数据协同过滤拿它完全没办法这时候就需要靠热度值做冷启动兜底。2.2 用户端与后台管理的功能闭环把数据模型理清之后功能页面就顺理成章了。我按实际的开发优先级给出一份排序这样你安排时间时心里有底。第一优先级用户注册登录、商品列表、商品详情、购物车、订单创建。这一套组合拳打下来你的系统已经从空壳变成了一个能用的商城。第二优先级评分/收藏/加入购物车这些行为操作的埋点。注意这里不只是能操作更重要的是每次操作都要写入UserRating表。我见过不少同学系统的商城功能做得花里胡哨结果后台的实验数据一塌糊涂——因为用户的所有行为根本没有被记录。做推荐系统的Demo行为数据记录才是命根子。第三优先级管理后台的商品管理、用户管理、订单管理和行为数据查看。Django Admin自带CRUD你只需要把数据模型注册进去后台就有了。但建议你稍微定制一下Admin——比如给商品列表加图片预览、给订单列表增加状态筛选操作很简单但答辩演示时观感会好很多。第四优先级推荐结果页和推荐解释。在用户中心的显著位置放一个为你推荐的区块调用算法模块生成商品列表每条推荐带上推荐理由。这一点哪怕做得粗糙效果也比没有强十倍。我常跟同学说的一句话是评分系统和行为记录这两块是推荐系统的心脏。做代码走查时老师大概率会先看你的数据表格再看算法代码。数据表设计得凌乱、行为没有记录算法代码写得再好都会显得根基不稳。2.3 数据模型中的关键代码实现参考既然说到Django我顺手给一份最基础的数据模型参考代码它几乎可以直接复用到你的项目里。from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(max_length64, verbose_name分类名称) parent models.ForeignKey( self, nullTrue, blankTrue, on_deletemodels.CASCADE, verbose_name父级分类 ) class Meta: verbose_name 商品分类 verbose_name_plural verbose_name def __str__(self): return self.name class Item(models.Model): name models.CharField(max_length128, verbose_name商品名称) category models.ForeignKey( Category, on_deletemodels.CASCADE, verbose_name所属分类 ) price models.DecimalField(max_digits10, decimal_places2, verbose_name价格) stock models.IntegerField(default0, verbose_name库存) sales models.IntegerField(default0, verbose_name销量热度) cover_image models.ImageField( upload_toitem_cover/%Y/%m/%d, blankTrue, nullTrue, verbose_name封面图 ) description models.TextField(blankTrue, verbose_name商品描述) created_at models.DateTimeField(auto_now_addTrue, verbose_name上架时间) class Meta: verbose_name 商品信息 verbose_name_plural verbose_name def __str__(self): return self.name class UserRating(models.Model): 用户行为记录表同时承载显式评分与隐式行为。 behavior_type: 1浏览 2收藏 3加购 4购买 5评分 BEHAVIOR_CHOICES ( (1, 浏览), (2, 收藏), (3, 加购), (4, 购买), (5, 评分), ) user models.ForeignKey(User, on_deletemodels.CASCADE, verbose_name用户) item models.ForeignKey(Item, on_deletemodels.CASCADE, verbose_name商品) rating models.FloatField(nullTrue, blankTrue, verbose_name评分) behavior_type models.IntegerField(choicesBEHAVIOR_CHOICES, default1, verbose_name行为类型) create_time models.DateTimeField(auto_now_addTrue, verbose_name发生时间) class Meta: verbose_name 用户行为 verbose_name_plural verbose_name unique_together (user, item, behavior_type) def __str__(self): return f{self.user.username}-{self.item.name}-{self.get_behavior_type_display()}这里有个容易踩的坑如果不对行为表加唯一约束同一个用户对同一件商品反复浏览会产生大量重复记录。算法在做相似度计算时重复数据会无形中放大该商品的权重导致推荐结果失真。所以unique_together这个约束一定要加上。如果还是担心重复浏览会冲掉之前的评分记录可以在视图函数里用get_or_create逻辑做更新。3. 基于物品的协同过滤算法实现算法部分是整套源码里最有含金量的地方。我见过太多同学的代码里算法模块只有不到一百行逻辑还写得糊里糊涂。这一章我按一个写法套路给你完整拆开保证你看完就能在原项目的基础上改出属于自己的版本。3.1 相似度计算方式的选择余弦相似度怎么算协同过滤里计算物品相似度最常用的方式是余弦相似度。打个比方有两个商品A和B我们不去管它们的属性标签只看哪些用户对它们产生过行为。如果对A有行为的用户集合和对B有行为的用户集合高度重合那么A和B就是相似的。余弦相似度的数学公式是similarity(A, B) (A · B) / (||A|| × ||B||)在推荐系统的实际代码里我们通常会构建一个用户-物品评分矩阵。矩阵的行是用户列是物品值是该用户对物品的评分。如果用户没有对物品产生过行为对应的位置就填0。有了这个矩阵每个商品其实就对应一个列向量两个商品之间的余弦相似度就是这两个列向量的余弦夹角。你可能要问为什么不是用欧几里得距离余弦相似度更看重方向上的一致性对评分数值的大小不敏感。比如用户A给商品X打了5分、给商品Y打了4分用户B给X打了1分、给Y打了1分。欧氏距离会认为这两组数据离得远但实际上X和Y仍然可能是相似的用户对X和对Y的态度相对一致。而在实际推荐场景里我们恰恰更关心用户对两个商品的态度是否一致所以余弦相似度是更惯用的选择。如果觉得向量太大不好计算还有两个工程上的常用词可以写在论文里一是物品-物品共现矩阵二是归一化处理。共现矩阵的意思是两个物品同时出现在同一个用户的行为列表里就计一次共现。归一化则是把原始的评分或行为次数压缩到0-1区间防止热门商品过于强势地霸占推荐列表。3.2 核心算法代码参考与解释因为要从数据库里取数据、要做矩阵、要做计算算法的纯Python实现即便在Demo规模下也要注意性能。不过在实际项目里我通常用的是Pandas配合NumPy来写这样代码量少可读性和性能也都过得去。下面这份代码基于用户-物品评分矩阵来生成物品相似度矩阵并返回某用户最感兴趣的Top-N推荐结果。import numpy as np import pandas as pd from django.core.cache import cache def build_user_item_matrix(): 从UserRating表读取行为数据构造成用户-物品评分矩阵。 这里把购买行为记为5分收藏记为3分浏览记为1分评分则直接用评分值。 from .models import UserRating records UserRating.objects.exclude(item__isnullTrue).values( user_id, item_id, rating, behavior_type ) df pd.DataFrame(list(records)) if df.empty: return pd.DataFrame() # 将行为类型转换为权重评分 behavior_weight {1: 1, 2: 3, 3: 4, 4: 5, 5: 0} df[weight] df.apply( lambda row: row[rating] if row[behavior_type] 5 and row[rating] else behavior_weight.get(row[behavior_type], 1), axis1 ) # 同一个用户对同一款商品可能存在多条行为取最大权重 df df.groupby([user_id, item_id], as_indexFalse)[weight].max() # 生成用户-物品透视矩阵空值填0 matrix df.pivot(indexuser_id, columnsitem_id, valuesweight).fillna(0) return matrix def compute_item_similarity(matrix): 基于余弦相似度计算物品相似度矩阵。 matrix: 用户-物品矩阵行是用户列是商品 item_matrix matrix.T # 转置后行是商品列是用户 norm np.sqrt((item_matrix ** 2).sum(axis1)).values.reshape(-1, 1) norm[norm 0] 1e-9 # 防止除零 item_norm item_matrix / norm similarity np.dot(item_norm, item_norm.T) item_ids item_matrix.index.tolist() sim_df pd.DataFrame(similarity, indexitem_ids, columnsitem_ids) return sim_df def recommend_for_user(user_id, top_n10, max_sim_items20): 为指定用户生成Top-N推荐。 策略取该用户行为权重最高的若干商品查找与这些商品最相似的物品 排除用户已经产生过行为的物品按相似度加权得分从高到低排序。 from .models import UserRating, Item matrix build_user_item_matrix() if matrix.empty: # 如果行为数据全空冷启动时按商品销量热度推荐 return Item.objects.order_by(-sales, -created_at)[:top_n] sim_df compute_item_similarity(matrix) # 获取该用户的行为数据 user_records UserRating.objects.filter(user_iduser_id) user_interacted set(user_records.values_list(item_id, flatTrue)) if not user_interacted: return Item.objects.order_by(-sales, -created_at)[:top_n] # 用户已交互物品的评分向量 user_vector matrix.loc[user_id] if user_id in matrix.index else pd.Series(dtypefloat) scores {} for item_id in user_interacted: if item_id not in sim_df.columns: continue weight user_vector.get(item_id, 1) if weight 0: weight 1 similar_items sim_df[item_id].sort_values(ascendingFalse).iloc[1:max_sim_items1] for candidate_id, sim_score in similar_items.items(): if candidate_id in user_interacted: continue scores[candidate_id] scores.get(candidate_id, 0) sim_score * weight if not scores: return Item.objects.order_by(-sales, -created_at)[:top_n] sorted_items sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_n] item_ids [item_id for item_id, _ in sorted_items] return Item.objects.filter(id__initem_ids)这份代码已经是工程化地简化过的版本了但核心思路全都在。有一点需要注意build_user_item_matrix每次推荐都要全量计算一遍矩阵和相似度在Demo里问题不大但如果数据量大了页面响应速度会非常慢。所以我在实际带学生的项目里都会把相似度矩阵的计算结果存到缓存里代码里我引入了Django cache设置一个过期时间比如600秒。这样每个用户的推荐请求只会做一次矩阵乘法而不是每来一个用户就重建一次矩阵。提示如果你在论文里想写为什么选择余弦相似度而不是皮尔逊相关系数最省力的说法是余弦相似度计算简单、易于扩展且对于稀疏评分矩阵的表达效果足够好皮尔逊相关系数需要先对用户评分做均值中心化在用户行为较少的情况下反而容易产生噪声。这个结论写在论文里是非常稳妥的。3.3 冷启动问题的处理和答辩话术几乎所有做推荐系统毕设的同学都躲不开评审老师的一个问题系统刚上线用户没有行为记录你的推荐怎么做这个问题在答辩提纲里基本属于必问题。如果你没有准备现场很容易卡壳。实操上我们的系统在Demo阶段就有三套兜底策略第一热门推荐。新用户进入推荐页后系统按商品销量和浏览热度排序从销量最高的商品里挑出一批来展示。代码里我已经写了这个逻辑——Item.objects.order_by(-sales, -created_at)。第二分类偏好推荐。注册时或首次使用系统时让用户选择自己感兴趣的商品分类服装、数码、图书等。之后在没有行为数据的情况下推荐系统可以直接按用户选择的分类推送商品。第三随机加热门混合。这个比较糙但适合数据极少的初期阶段。系统随机取一些商品和热门商品混合展示尽可能让用户产生点击行为——只要点了一下后面的协同过滤就有数据可用了。答辩时的标准话术可以这么说针对冷启动场景本项目采用了基于商品热度的基础推荐策略来填充新用户的推荐页面同时通过用户注册时选择的兴趣标签完成个性化初步匹配。随着用户行为数据的积累推荐系统会平滑地从冷启动策略过渡到协同过滤算法。这段话既解释了方案又体现了设计思路的完整性。4. Django项目环境搭建与关键模块配置如果你想从零开始把这个项目复现出来环境搭建和Django关键配置会决定你后面顺畅不顺畅。这里我按实际操作顺序来讲不走弯路。4.1 开发环境配置清单一个标准的Django推荐系统Demo依赖项通常如下依赖版本建议用途Python3.8 - 3.11开发语言Django3.2 - 4.2Web框架MySQL / SQLiteMySQL 5.7 / 内置数据存储毕设我用SQLite居多NumPy1.24矩阵计算Pandas2.0数据处理Pillow10.x图片上传处理如果你是纯新手强烈建议先装一个虚拟环境再动手python -m venv rec_env rec_env\Scripts\activate # Windows # source rec_env/bin/activate # macOS / Linux pip install django4.2 numpy pandas pillow mysqlclient不要图省事直接pip install全部依赖到全局环境。Python版本混乱、包冲突是毕业生电脑上的老戏码了到时候报错排查半天浪费时间还影响心态。4.2 Django项目的目录规划与自定义配置新建项目和应用的结构我建议这样recommend_system/ # 项目根目录 ├── manage.py ├── recommender/ # Django项目配置目录 │ ├── settings.py │ ├── urls.py │ └── ... ├── apps/ │ ├── users/ # 用户模块 │ ├── items/ # 商品模块 │ ├── orders/ # 订单模块 │ └── recommend/ # 推荐算法模块 ├── static/ # 静态资源 ├── media/ # 商品图片上传目录 ├── templates/ # 页面模板 └── scripts/ └── init_data.py # 初始化演示数据脚本有几个配置项是务必检查的否则后续一定会踩坑settings.py里的INSTALLED_APPS要注册所有的appTEMPLATES配置里的DIRS要指向项目根目录下的templates文件夹STATIC_URL和MEDIA_URL、MEDIA_ROOT要配好否则商品图片传上去再访问直接给你404如果用了自定义用户模型AUTH_USER_MODEL必须在你第一次迁移之前就配置好否则Django会报AttributeError而且几乎没法回退只能重建数据库。# settings.py 中一段关键配置 import os from pathlib import Path BASE_DIR Path(__file__).resolve().parent.parent INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, apps.users, apps.items, apps.orders, apps.recommend, ] MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media) STATIC_URL /static/ STATICFILES_DIRS [os.path.join(BASE_DIR, static)]4.3 演示数据初始化脚本的设计这个步骤很容易被忽略但实际上是整个项目演示顺不顺畅的前提。很多同学拿到一套源码结果数据库里空空如也用户登录进去点了一圈发现推荐页什么都没有也看不出任何推荐效果。比如你拿到的完整源码里通常会自带一批演示数据——商品几十个、分类十几个、模拟用户若干并且每个模拟用户都预置了几十条评分和购买记录。手工往数据库里一条一条录入演示数据显然不现实。我当时在某个模拟项目X里用的是Django管理命令的方式写一个自定义命令init_demo_data批量造数据python manage.py init_demo_data这个命令做的事情很简单创建若干商品分类每个分类下生成若干商品创建测试用户账号如demo1/demo2密码统一设为123456替这些用户随机生成一批浏览、收藏、购买行为并保证每个用户至少对几个商品有共同交互。测试账号和密码一定要写进你的实验说明文档里。答辩演示时老师经常懒得注册新账号你如果直接说点这里用演示账号登录体验会顺畅很多。提醒造演示数据时行为数据不要太稀疏。我见过有同学导入了几百个商品但每个用户只有一两条行为记录结果推荐结果完全随机、毫无逻辑。稳妥的做法是每个用户至少产生20条行为数据并且让不同用户之间的交互商品有30%左右的重合这样算法算出来的相似度才有可见的规律。5. 核心页面实现与推荐结果展示项目的页面数量不用多但关键页面的逻辑必须闭环。这一章我挑最要紧的页面逐个讲清楚顺带指出哪些地方是可以拿来加分的。5.1 首页与商品列表页功能闭环的入口首页在推荐系统里有两个使命。第一它是一张系统功能展示脸分类导航、搜索框、商品展示位都要有第二它要能承接推荐算法的结果——通常是把热门推荐或者猜你喜欢放在首页最显眼的区域。商品列表页则相对常规左侧是分类筛选中间是商品卡片网格支持按价格、销量、上架时间排序。商品卡片上要有明确的加入购物车和收藏按钮这两个按钮就是产生行为数据的入口。如果你的项目中这两个按钮没有接行为记录逻辑那推荐系统就是空中楼阁。商品详情页是最容易被忽略的推荐位。在详情页底部放一个相关推荐模块调用recommend_for_user接口根据当前商品找出相似的几款商品展示出来。这一处比首页推荐更能给评委留下深刻印象因为它的推荐逻辑是肉眼可见的关联性。5.2 推荐结果页让算法效果看得见推荐页是最有演示效果的一个页面。这里我强烈建议你不要只扔一个商品列表就完事。两个小设计能让效果提升一个档次第一每一件推荐商品下方加一行小字说明推荐理由。比如因为您浏览过某品牌某型号我们为您推荐这款或购买了该分类商品的用户也购买了以下商品。这一行小字在答辩演示时简直可以直接拷打老师的心智——一眼就能看出系统不是随机推的。第二推荐结果区做一个刷新推荐按钮。点击后前端发起AJAX请求后端重新调用算法返回更新后的推荐列表。这个交互在演示中非常讨喜因为它直观展示了算法是活的而不是写死的静态页面。实现上推荐页面与Django视图的配合大致如下from django.shortcuts import render from django.http import JsonResponse from .utils import recommend_for_user def recommend_page(request): user request.user if not user.is_authenticated: # 未登录用户走默认热门推荐 items Item.objects.order_by(-sales)[:10] return render(request, recommend/guess_you_like.html, {items: items}) items recommend_for_user(user.id, top_n10) return render(request, recommend/guess_you_like.html, {items: items}) def recommend_refresh_api(request): if not request.user.is_authenticated: return JsonResponse({code: -1, msg: 请先登录}) items recommend_for_user(request.user.id, top_n10) data [ { id: item.id, name: item.name, price: str(item.price), cover: item.cover_image.url if item.cover_image else , reason: 根据您的浏览与购买记录推荐, } for item in items ] return JsonResponse({code: 0, data: data})5.3 管理后台的定制技巧Django Admin自带的后台管理面已经够用但直接交上去会显得项目没有精心打磨。花半天时间做三块定制答辩时观感会上升一个台阶。第一列表页字段定制。用list_display控制后台列表展示哪些字段用list_filter增加分类、状态等筛选器。别小看这些简单配置它们能让管理后台看起来更像一个真实的后台系统。from django.contrib import admin from .models import Item, Category, UserRating admin.register(Item) class ItemAdmin(admin.ModelAdmin): list_display [id, name, category, price, stock, sales, created_at] list_filter [category, created_at] search_fields [name, description] list_per_page 20 admin.register(UserRating) class UserRatingAdmin(admin.ModelAdmin): list_display [user, item, behavior_type, rating, create_time] list_filter [behavior_type, create_time]第二增加一个推荐数据概览的统计面板用Django Admin的admin.site.index_template或者自定义一个视图展示用户总数、商品总数、行为记录总数、评分分布等。这部分工作量不大但在论文里能截图放进去作为系统功能展示中的高光一页。第三行为记录的可视化。如果你能做到这一步项目已经超过80%的同题同学了。用pyecharts或者Chart.js在前端画一个简单的用户行为频率柱状图展示浏览/收藏/购买的行为分布。这个小模块不涉及任何复杂链路但答辩时完全可以作为亮点讲出来。6. 常见问题与调试技巧实录这部分送给你的是我在无数次调试中攒下来的经验。每一条都是踩过坑之后才知道的写在这帮你省时间。6.1 推荐结果一片空白的排查思路我在给某家公司内部演示推荐系统时就遇到过推荐页输出空白的情况。大家千万别慌按照从数据到算法的顺序排查就行第一步检查UserRating表里有没有数据。如果数据为空推荐函数必然走兜底逻辑而如果你连兜底逻辑都没写页面肯定空白。检查方式很简单在Django shell里执行UserRating.objects.count()看看返回值。第二步检查用户是否已登录。recommend_for_user会针对当前用户查行为数据如果用户未登录或者user_id不对同样拿不到推荐。有的同学把request.user.is_authenticated的判断放在模板里而不是视图里结果用户没登录就直接渲染了一个空列表。第三步检查算法返回的item_id列表是不是包含已经被下架或删除的商品。Item.objects.filter(id__initem_ids)如果过滤后是空QuerySet页面自然什么都没有。做演示数据初始化时务必确保不再引用失效的item_id。6.2 物品相似度矩阵太大导致响应缓慢纯Python循环计算相似度矩阵在数据量小的时候无所谓但当商品数量达到几百个时三重循环的时间复杂度会让页面卡出天际。解决办法我已经在前面提到了把相似度矩阵的计算结果缓存到Django Cache里。另一种方案是把相似度矩阵落库到一张专门的ItemSimilarity表里商品数据变化不频繁的情况下每晚用定时任务重新计算一次即可。方案各有利弊论文里通常不需要写到这个细节但如果你写了推荐模块的性能优化小节这会是很好的素材。from django.core.cache import cache def get_similarity_matrix_with_cache(): key item_similarity_matrix sim_df cache.get(key) if sim_df is None: matrix build_user_item_matrix() sim_df compute_item_similarity(matrix) cache.set(key, sim_df, timeout600) return sim_df6.3 数据库迁移时出现的混乱错新手最常见的报错之一是迁移时提示AttributeError: str object has no attribute objects或者You need to specify default value for field。这两种报错的原因基本都是模型字段定义不严谨或者是历史迁移文件脏了。如果你用的是MySQL还容易遇到中文不乱码或者时区不统一的问题。虽然DEMO阶段用SQLite可以规避大量麻烦但如果你把项目最后部署到服务器给导师在线看效果MySQL还是更稳妥。搭配Django的时区配置TIME_ZONE Asia/Shanghai USE_TZ True记住一个原则模型字段的nullTrue和blankTrue不要混用。对字符串字段blankTrue对应表单校验允许为空对数值字段nullTrue对应数据库允许NULL。写反了的人很容易在数据写入时报NOT NULL constraint failed。6.4 商品图片无法访问的经典问题这个问题的坑点其实不大但几乎每个人都会遇到。如果你在商品页面能正常展示文字但图片加载报404请依次检查图片是否真的上传到了MEDIA_ROOT指向的目录urls.py里有没有挂载media路由from django.conf import settings from django.conf.urls.static import static urlpatterns [ # ... 其他路由 ] if settings.DEBUG: urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)models.py的ImageField里有没有设置upload_to并且Pillow库是否已安装。只要这三步查完图片问题必解。7. 关于毕设交付与答辩准备的补充建议写到这里我猜你可能已经对系统该怎么做了然于心。但毕设项目远不止把系统跑起来这么简单文档、演示视频、答辩语术这几个环节同样要提前准备。7.1 远程调试和讲解服务能帮你解决什么问题我在对接某位同学的需求时发现一个常见现象代码在自己的电脑上跑得没问题但一到老师指定的远程服务器上部署就各种报错。环境变量、Python版本、数据库连接方式、静态文件路径任何一个环节都能卡住人。市面上标注远程调试讲解定制的服务做的就是帮你消除环境差异带来的不确定性。如果条件允许购买这类服务时建议至少包含以下交付内容远程部署完成后确保系统从登录到推荐全流程可跑通核心算法部分特别是相似度计算和推荐流程能口头讲解清楚演示数据初始化脚本和测试账号都已经就位。用一句话总结就是宁可多花时间在上线前的调试上也不要把问题留给答辩现场。7.2 论文里应该重点突出的三个创新点写系统设计类论文时很多同学容易陷入流水账式记录。我强烈建议你的设计章节围绕以下三个创新点展开第一数据建模层面通过统一的行为数据表完成评分行为时效三要素的建模。普通的商城系统只记录订单而你的系统记录了用户从浏览到购买的完整链路这正是推荐系统研究所需的用户反馈偏好。第二算法实现层面实现了两种相似度计算方式并做了对比实验。如果论文里有【对比实验】的图表说明你在设计阶段就想到了验证环节这个细节很加分。第三工程落地层面的冷启动策略。很多同类课题都忽视冷启动问题而你在设计文档里把这个讲透可以体现你在系统设计阶段的整体思考。7.3 最后的经验演示几十遍也不嫌多每次给导师演示前我建议你先自己从头到尾走一遍全流程注册新账号、浏览几个商品、下单购买、查看推荐页、刷新推荐、进入后台管理。特别是注册新账号产生行为数据这个链路最考验系统鲁棒性也最容易暴露隐藏bug。我个人体会比较深的一点是推荐系统这种课题最怕的不是算法被问倒而是演示时系统突然崩了。答辩老师最关心的是你的系统能不能用你的代码只要逻辑清晰、数据完整、演示顺畅就已经赢了大半。至于算法精度是不是业界顶级——那从来都不是毕业设计评审的衡量标准。最后再分享一个小技巧把推荐结果页面也做成可导出的数据报告。哪怕只是简单的CSV把推荐的商品ID、得分、推荐理由导出来答辩时老师要看数据长什么样你直接拉出来一张表这种细节往往比讲十页PPT都管用。
阅读完成 · 觉得有帮助?
咨询建站