又是一年毕设季,后台留言被“大数据毕设选题”刷屏是常态。今年被问得最多的,就是标题里这个“基于django+深度学习的淘宝用户购物可视化与行为预测系统”。说实话,这个题目能火不是没道理——它把Web开发、大数据处理、可视化大屏、深度学习预测这几个毕业设计里的“硬通货”全串在了一起,既有工程落地感,又有算法研究点,答辩时也好讲故事。很多同学私信我问这个题到底怎么入手、代码拿到后跑不起来怎么办、模型效果差怎么调,我干脆把整个项目的拆解、实操流程和踩坑记录整理成一篇,按我平时做项目的习惯从头讲到位,希望能帮准备选这个题或者正在做这个题的同学省点时间。
1. 项目整体设计与思路拆解
1.1 为什么是“django+深度学习”这个组合
先聊选题思路。淘宝用户购物可视化与行为预测,本质上是一个典型的大数据应用闭环:数据采集 → 数据清洗 → 特征工程 → 可视化展示 → 行为建模预测。这套闭环用别的技术能不能做?能,比如Spring Boot加Python算法服务,或者干脆前后端分离用Flask,但django在这个场景里有一个天然优势——它是Python生态里最完整的Web框架,自带Admin后台、ORM、模板系统,和深度学习那套Python工具链(TensorFlow/PyTorch/sklearn)完全无缝衔接。
这意味着你不需要在Java和Python两个语言之间来回切换,也不用单独给算法模型写一套RESTful接口再去联调。用django的ORM操作MySQL里的用户行为数据,用视图函数直接调用训练好的模型做预测,模板引擎配ECharts渲染可视化大屏,整个项目一个Python进程全跑完,逻辑链路短,出问题好排查。对毕设来说,这种“少折腾”就是最大的优势。
再说深度学习。很多同学一听到“深度学习”就慌,觉得非得搞什么ResNet、Transformer才算数。实际上用户购物行为预测这个场景,数据的本质是“用户历史行为序列 + 商品/用户静态属性”,最适合的模型反而不是那些特别深的网络,而是以Embedding加序列建模为核心的轻量级深度模型。我用的是“Embedding层 + 双向LSTM + 注意力机制”的结构,参数量控制在几十万级别,单卡CPU训练十分钟就能收敛,效果却比XGBoost这类传统模型在AUC上高出3到5个点。这正好是答辩时能讲清楚、也能体现算法功底的点。
1.2 功能模块划分:可视化与预测两条线
整个系统我按“一轴两线”来划分模块,主轴是“用户购物行为数据”,两条线分别是可视化和行为预测。
可视化这条线,核心是搭建一个大屏驾驶舱,分四个维度展示:
- 用户画像:年龄、性别、会员等级的分布
- 商品画像:类目销量排行、价格区间分布、品牌热度
- 行为洞察:浏览、收藏、加购、下单四种行为的转化漏斗
- 地域分析:各省份的购买力热力图
行为预测这条线,核心是两个任务:
- 用户购买意图预测(二分类):根据用户最近N天的行为序列,预测他未来7天内会不会下单
- 用户活跃度分层预测(多分类):预测用户属于高活跃、中活跃、低活跃、沉睡中的哪一类
这两条线共用同一份清洗后的数据,但特征工程各有侧重。可视化用的是聚合统计类特征,预测用的是序列类特征。很多教程喜欢把这两件事混在一起做,我的经验是分开做,后续调试和扩展都会轻松很多。
1.3 技术选型与版本搭配
我实测下来比较稳的一套搭配是这样的(直接照着装,不要自己乱升级版本):
| 组件 | 版本 | 说明 |
|---|---|---|
| Python | 3.8 | 兼容性最好,Torch和Django都稳 |
| Django | 3.2 | 长期支持版,自带Admin好用 |
| MySQL | 5.7 或 8.0 | 存业务数据和行为日志 |
| Redis | 5.x 及以上 | 缓存热点数据和模型预测结果 |
| TensorFlow 或 PyTorch | 2.x / 1.10+ | 训练行为预测模型 |
| ECharts | 5.x | 前端可视化图表库 |
| pandas / numpy | 1.x 系列 | 数据处理标配 |
这里特别强调一句:不要一上来就追最新版。Django 4.x、5.x改了一些底层行为,很多老教程的代码直接跑会报错,而毕设项目要的是稳定能跑,不是版本最新。Python 3.8搭配Django 3.2是我试过最省心的组合,网上能找到的参考代码几乎都能直接用。
2. 核心细节解析与实操要点
2.1 数据从哪来:爬虫还是现成数据集
做这个题,第一个拦路虎就是数据。淘宝的接口反爬很严,直接爬实时数据不现实,而且毕设阶段爬大量真实用户数据也有合规风险。我的建议是“两条腿走路”:
一是用公开数据集。网上有一些脱敏的淘宝用户行为数据集,典型的是UserBehavior.csv这类,包含用户ID、商品ID、类目ID、行为类型(pv、cart、fav、buy)、时间戳这几个核心字段。几十万到几百万条不等,做可视化和预测都够了,而且字段干净,省去大量清洗工作。
二是自己构造补充数据。如果觉得公开数据集太少,可以写一个Python脚本,按幂律分布模拟生成用户、商品、行为记录,再注入一些规则型的噪声(比如周末购买率高、晚上浏览多、部分用户只浏览不买),让数据看起来更“真实”。
我自己的做法是公开数据集打底,再补充大概20%的模拟数据,让用户量达到5000以上、行为记录达到50万条以上。这个规模既能撑起可视化大屏的展示效果,又不会让本地训练慢到离谱。
2.2 数据库设计与Django模型层实现
拿到数据后,第一步是设计表结构。我用的是Django ORM来建表,核心三张表:
用户表
- user_id、年龄、性别、城市、会员等级、注册时间
- 用于用户画像分析和用户维度特征聚合
商品表
- product_id、类目ID、品牌、价格、上架时间、销量
- 用于商品画像和价格区间分析
行为表
- 自增ID、user_id、product_id、行为类型(1浏览 2收藏 3加购 4购买)、行为时间
- 这是整个系统的核心表,体量最大,必须做索引
实际建模时要注意:
- 行为表的数据量最大,一定要给user_id和product_id建联合索引,否则后面聚合统计时SQL慢到让你怀疑人生。
- Django默认的自增主键在数据量大时没问题,但如果你用了分布式ID之类的东西,反而画蛇添足。
- 时间字段建议用DateTimeField,并且按天做分区(如果MySQL支持)。我数据量50万条的时候没分区也能跑,但上了百万级之后,分区带来的查询提速非常明显。
2.3 数据清洗与特征工程实操
这块是整个项目里最影响最终效果、也最容易被忽视的部分。我踩过的坑不少,直接列要点:
缺失值处理:行为表基本不会有缺失,但用户表的年龄、城市经常空。我自己是年龄用中位数填充、城市用“未知”填充,比直接删行靠谱。
异常值处理:有一类用户一天浏览了几千件商品,这种明显是爬虫或异常行为,直接剔除,否则会拉偏整个画像统计。
时间特征:从行为时间戳里拆出小时、星期几、是否节假日、是白天还是晚上。这一步能显著提升预测模型的效果,因为用户的购买意愿和时段强相关。
行为序列构造:这是深度学习模型的核心输入。每个用户按时间排序,取最近N条行为,按“user_id + 行为类型 + 商品类目”做序列化。比如有一条序列是“浏览-女装-浏览-女装-收藏-女装-加购-女装-购买-女装”,模型就能学到“连续浏览同类目后加购、购买”的路径依赖。
标签构造:购买意图预测的标签是“未来7天内是否下单”。活跃度分层的标签按30天行为频次划分:大于等于20次为高活跃,10到19次为中活跃,1到9次为低活跃,0次为沉睡。这些规则不复杂,但决定了模型学什么,一定要结合实际业务理解来定。
2.4 Django项目结构和核心配置
很多新手拿到一个Django项目zip包,第一步就懵了:该从哪里看起?该运行哪个文件?我先讲Django项目的标准结构和这个项目的配置要点。
一个标准的Django项目包含一个外层项目目录(比如taobao_analysis)和多个app目录。我习惯分成四个app:
- users:用户管理和认证
- visualization:可视化图表数据接口
- prediction:行为预测接口
- system:后台管理和文件上传
这些app各司其职,后续扩展功能时只要在对应app里加视图和模板就行,不会牵一发动全身。
配置文件集中在settings.py里,核心要改的地方有三个:
- INSTALLED_APPS:把上面几个app和第三方库注册进去
- DATABASES:配置MySQL连接信息(用户名、密码、主机、库名)
- STATICFILES_DIRS:配置静态文件路径,否则ECharts的JS文件和自定义CSS会加载不出来
从拿到代码到能在浏览器上跑起来,顺序是:建虚拟环境 → 安装依赖(requirements.txt)→ 改数据库配置 →python manage.py makemigrations→python manage.py migrate→ 导入数据 →python manage.py runserver。这套流程我每天至少走一遍,闭着眼都能背出来。
3. 可视化大屏的完整实现过程
3.1 数据接口设计:从ORM查询到JSON响应
可视化大屏的核心不是前端,而是后端接口。前端ECharts只是画图,真正决定展示效果的是后端把什么数据返回给它。
我的做法是给可视化app写若干个视图函数,每个函数只做一件事:
get_user_portrait:返回年龄段分布、性别占比、会员等级分布get_category_rank:返回销量Top10商品类目get_price_range:返回各价格区间的商品数量和销量get_behavior_funnel:返回浏览→收藏→加购→购买四个环节的转化数据get_geo_analysis:返回各省份的购买量数据
视图函数里用Django ORM做聚合查询,比如统计年龄分布:
from django.http import JsonResponse from ..models import UserProfile from django.db.models import Count def get_age_distribution(request): data = ( UserProfile.objects .values('age_group') .annotate(count=Count('user_id')) .order_by('age_group') ) result = {item['age_group']: item['count'] for item in data} return JsonResponse({'code': 0, 'data': result})注意这里用到了values('age_group')配合annotate,这是Django ORM做分组统计的标准姿势。如果你在字段上做了索引,这条查询在百万级数据量下也就是几十毫秒的事。
需要重点提醒的是:千万别在视图函数里写复杂的Python循环去统计!比如先把查询结果全取出来,再用for逐个计数。这种写法在数据量小的时候看不出问题,数据量一上来,接口响应直接卡成5秒以上。正确的做法是把统计分析尽量推给SQL(ORM)完成,Django的aggregate和annotate就是干这个的。
3.2 前端大屏布局与ECharts实战
大屏设计这块,要的是“一眼高级”。我用的方案是:一个宽屏页面(通常是1920x1080),左中右三栏布局。
- 左侧:用户画像(年龄、性别、会员等级)
- 中间:行为漏斗图 + 类目热销榜 + 实时行为动态滚动
- 右侧:地域热力图、价格区间分布、预测结果展示
ECharts直接通过CDN引入,或者把echarts.min.js放到static目录下。每个图表初始化时,用fetch或axios调用后端接口,拿到JSON数据后setOption渲染。
这里分享一个实测提升大屏“高级感”的小技巧:配色方案不要用ECharts默认的蓝红配色,改成深蓝底 + 荧光绿/橙高亮的科技风。背景用深色渐变加一个暗网格,图表透明底,数字用大号粗体。同样一组数据,配色换一下,视觉差距巨大,答辩时第一印象分能直接拉满。
还要注意大屏自动刷新。我写了一个setInterval定时器,每30秒重新请求一次接口。如果数据没有变化,前端做个判断就不重新渲染;如果有新数据,就做一个过渡动画。这样大屏幕放在那里,随时看都是“活”的。
3.3 Redis缓存:让可视化接口飞起来
当你的数据量到了百万级,就算SQL写得再漂亮,每次前端刷新都实时查全量库也是扛不住的。这时候就轮到Redis上场。
我的方案是这样:给上面的那些接口加一个缓存装饰器,第一次请求时查数据库并把结果序列化写入Redis,设置过期时间(比如300秒),后续请求直接返回Redis里的数据,只有缓存过期才重新查库。
import json import redis r = redis.Redis(host='localhost', port=6379, db=0) def get_category_rank(request): cache_key = 'viz:category_rank' cached = r.get(cache_key) if cached: return JsonResponse({'code': 0, 'data': json.loads(cached)}) # 查数据库(省略ORM代码) result = {...} r.set(cache_key, json.dumps(result), ex=300) return JsonResponse({'code': 0, 'data': result})这个优化做完之后,大屏接口的平均响应时间从“数据库查询的几百毫秒”降到了“Redis读内存的几毫秒”。而且Redis自带可视化客户端工具,比如Another Redis Desktop Manager,你可以实时看到缓存里的键值变化,调试非常直观。
如果你问“数据不实时更新会不会影响展示效果”——我实话说,大屏要的是“不卡顿的实时感”,不是“毫秒级的真实时”。300秒的缓存窗口完全够用,而且很大程度上减轻了数据库压力。
3.4 动态数据推送扩展:WebSocket有没有必要做
很多搜索热词里提到django websocket,说明大家还想做大屏的实时推送。我的看法是:毕设阶段,Ajax轮询完全够用,没必要上WebSocket增加复杂度。
Django本身是同步框架,要做WebSocket需要引入channels和ASGI,这一下子就要改部署方式、加Redis channel layer,复杂度直接上一个台阶。如果你的题目明确要求“实时推送”,那可以加,但建议放到最后做,用channels实现一个简单的行为流推送(比如新产生一条购买记录就推到大屏上滚动展示),这样有亮点又不至于拖垮主线。
如果只是为了演示效果,用setInterval加Ajax轮询已经能做到“伪实时”。我在演示的时候,就是把定时器设为5秒一刷新,行为动态区域看起来就跟实时推送一样流畅。
4. 深度学习行为预测模型的构建与部署
4.1 模型选型:从传统机器学习到深度学习
行为预测这条线,很多教程上来就让你堆LSTM,但我的经验是:先用传统模型打底,再上深度模型提升,这样你能拿到两组对比数据,答辩时非常有说服力。
我实际跑下来的对比是这样的:
| 模型 | 准确率 | AUC | 训练时间 |
|---|---|---|---|
| 逻辑回归 | 71.2% | 0.68 | 秒级 |
| XGBoost | 78.5% | 0.74 | 分钟级 |
| Embedding+BiLSTM+Attention | 83.1% | 0.79 | CPU约15分钟 |
准确率和AUC只是参考,因为数据集不同结果会有差异,但趋势是一致的:深度学习在这个任务上确实能带来显著提升。而且你要在答辩时说明“为什么用深度学习”而不是“为了用而用”,这个对比表就是最好的答案。
4.2 特征编码与训练数据处理
深度学习模型吃不了“用户ID”“商品ID”这种原始字段,必须做编码。我推荐的做法是:
- 类别字段(用户ID、商品ID、类目ID):用Embedding。先做一个ID到索引的映射表,再查表得到整数索引,网络第一层就是Embedding层。
- 数值字段(价格、浏览次数等):做标准化,减均值除标准差,让数值落在0附近。
- 时间字段:拆成小时(0-23)和星期(0-6)两个整数特征,同样做索引。
训练数据要按用户划分训练集和测试集,不能随机打乱切分。原因很简单:同一个用户的行为如果一部分在训练集、一部分在测试集,模型相当于见过这个用户的部分行为,再去预测他的未来行为,这叫“数据泄露”,测出来的指标虚高,答辩时容易被老师抓住。
正确的切分方式是按“时间窗口”切:前30天数据做训练,后7天数据做测试。这样模型预测的是“未来”,才贴合真实业务场景。
4.3 模型结构构建实战
我用PyTorch搭的模型主体是这样的结构:
import torch.nn as nn class BehaviorPredictor(nn.Module): def __init__(self, user_num, item_num, hidden_size=64): super().__init__() self.user_emb = nn.Embedding(user_num, 32) self.item_emb = nn.Embedding(item_num, 32) self.cat_emb = nn.Embedding(cat_num, 16) self.lstm = nn.LSTM(80, hidden_size, batch_first=True, bidirectional=True) self.attention = nn.Linear(hidden_size * 2, 1) self.fc = nn.Linear(hidden_size * 2 + 32, 64) self.out = nn.Linear(64, 1) self.sigmoid = nn.Sigmoid() def forward(self, user_ids, item_seq, cat_seq, user_feat): user_vec = self.user_emb(user_ids) # [batch, 32] item_vec = self.item_emb(item_seq) # [batch, seq_len, 32] cat_vec = self.cat_emb(cat_seq) # [batch, seq_len, 16] # 拼接 item 和 cat 向量 seq_vec = torch.cat([item_vec, cat_vec], dim=-1) # [batch, seq_len, 48] lstm_out, _ = self.lstm(seq_vec) # [batch, seq_len, hidden*2] attn_score = self.attention(lstm_out).squeeze(-1) # [batch, seq_len] attn_weight = torch.softmax(attn_score, dim=1) attn_vec = torch.sum(attn_weight.unsqueeze(-1) * lstm_out, dim=1) fused = torch.cat([attn_vec, user_vec, user_feat], dim=-1) hidden = torch.relu(self.fc(fused)) out = self.sigmoid(self.out(hidden)) return out这个结构不算复杂,但每一层都有它的意义:Embedding层把高维稀疏的ID压缩成低维稠密向量;LSTM捕捉行为序列的时序依赖;注意力机制自动学出“哪些历史行为对预测更重要”;用户向量和特征向量做融合,让模型既看序列又看静态属性。
训练的时候有几个关键点:
- 二分类用BCEWithLogitsLoss,注意力权重和LSTM隐藏层维度不要设太大,我实测64就够,大了反而过拟合。
- 优化器用Adam,学习率从1e-3开始,每5个epoch衰减一次。
- 样本不均衡要注意:购买用户通常只占10%左右,直接用原始比例训练,模型会倾向全预测为“不购买”,看起来准确率有90%但毫无意义。我用的是正负样本1:2的采样比例,配合Focal Loss,效果明显好。
4.4 模型与Django集成
训练好模型后,保存成.pth文件,放在项目路径下的prediction/models/目录里。运行时在Django视图里加载:
import torch model = BehaviorPredictor(user_num=5000, item_num=10000, hidden_size=64) model.load_state_dict(torch.load('prediction/checkpoints/best_model.pth', map_location='cpu')) model.eval() def predict_purchase(request): user_id = request.GET.get('user_id') seq = build_user_sequence(user_id) with torch.no_grad(): prob = model(seq) return JsonResponse({'user_id': user_id, 'purchase_probability': round(prob.item(), 4)})这里有一个非常关键的坑:模型load进来后一定要设model.eval(),否则Dropout和BatchNorm还在训练模式,同样的输入每次预测结果都不一样。我早期调试时因为这个没少头疼,查了半天才发现是这个细节。
4.5 预测结果如何“讲故事”
预测模型不能只输出一个概率值,还得“可视化”起来才有演示效果。我做了两块:
一是个体预测展示:在页面上输入一个用户ID,系统返回他的购买概率、活跃层级,并用雷达图展示他近30天的行为特征。
二是群体预测统计:系统遍历测试集中的用户,统计预测“未来7天会购买”的人群比例,按会员等级、城市、年龄段交叉分析,生成“预测购买潜力人群画像”。这一块答辩时非常加分,因为它展示了模型产出如何反哺业务决策。
5. 常见问题与排查技巧实录
5.1 环境与依赖问题
问题1:Django版本冲突,网站打不开
这是我被问得最多的一个。很多人拿到代码,不管三七二十一pip install django装了个最新版5.x,然后各种报错:URL配置语法变了、ugettext_lazy没了、模板语法报错。解决方法是严格按照requirements.txt里锁定的版本安装:
pip install django==3.2如果已经装了别的版本,先卸载再装。不要总觉得“新版一定更好”,对毕设来说稳定压倒一切。
问题2:MySQL连接报错“ModuleNotFoundError: No module named 'MySQLdb'”
Django连MySQL需要mysqlclient这个库。Windows上直接pip装mysqlclient经常失败,我建议用pymysql替代,然后在项目的__init__.py里加一行:
import pymysql pymysql.install_as_MySQLdb()实测Win10、Win11下都能跑通,省去编译MySQL驱动的烦恼。
问题3:静态文件加载不出来(img、css、js都404)
这个在开发阶段其实很好解决。先确认settings.py里DEBUG = True,再用python manage.py runserver启动,Django会自带静态文件服务。如果还不行,检查STATICFILES_DIRS配置的路径是不是指向了真实的静态目录。这里最容易出错的是:用了系统模板自带的一套目录结构,结果自己没有完整放置目录名称,导致路径对不上。
我用的一句话排查套路是:先ping一下静态文件URL,看是404还是403。403多半是权限或路径问题,404多半是根本没找到文件,方向完全不同。
5.2 数据相关的坑
问题4:导入CSV数据时中文乱码
淘宝行为数据里如果有中文(比如商品标题、类目名),用pandas读入时一定要指定编码:
import pandas as pd df = pd.read_csv('data.csv', encoding='utf-8')如果utf-8报错,换encoding='gbk'。Excel导出的CSV常见gbk,爬虫导出的常见utf-8,多试几次就知道。
问题5:Django执行查询时删除对象报错
数据库迁移后想清空行为表,用Behavior.objects.all().delete(),结果外键约束报错。这个很正常,因为其它表里有外键引用。解决办法是先把关联表清空,或者用on_delete=models.CASCADE,让Django教你做人。
5.3 深度学习训练与预测的问题
问题6:模型一直不收敛,Loss跳水后变NaN
我遇到过两次,一次是学习率太大,设成了0.1,Loss直接飞掉;一次是输入数据里出现了NaN,一般是特征处理时除零了。排查方法:先检查训练数据的pd.isnull().sum(),再检查学习率,把初始值降到1e-3,通常能解决。
问题7:预测结果全部是同一个值
这是典型的“标签泄漏”或者“模型没学到有效特征”。先检查训练集和测试集是否按用户划分,再看正负样本比例,最后看特征里是不是有目标泄漏(比如把“是否购买”直接当成输入特征了)。我见过最离谱的操作是有人把目标列不小心留在特征矩阵里,模型直接学会了“看到1就输出1”。
问题8:模型在CPU上跑太慢
如果用户量上万、序列长度50以上又没GPU,LSTM训练确实慢。三个缓解方案:减少hidden_size、缩短序列长度(取最近20条)、只用1层LSTM。模型效果损失不大,训练速度能提升两三倍。
5.4 部署与演示的翻车记录
问题9:换机器演示时模型路径失效
训练好的模型文件在路径prediction/checkpoints/best_model.pth,到了别的机器上没同步过去,结果一调用预测接口直接报错找不到文件。解决办法:一是用相对路径并确保上传项目时带上模型文件;二是写一个启动检查程序,运行前自动检查模型文件是否存在,不存在就给出清晰提示。
问题10:大屏页面在投影仪上比例不对
答辩教室的屏幕比例常常不是16:9,大屏用了固定像素布局就会拉伸变形。我建议用rem或者vw/vh做适配,或者至少在body上做一个高度自适应缩放,保证任何分辨率下都能完整显示。这个小细节很多同学不注意,一到现场就翻车。
6. 个人实操心得与扩展方向
做这个项目前前后后我大概花了三周左右,不算快,但踩坑踩得比较全面。最后分享几个个人体会比较深的地方。
第一,这个项目的正确打开顺序是:先跑通可视化,再做预测模型。可视化的成就感来得快,能让你保持动力;预测模型是硬骨头,放在后面集中啃。如果一开始就陷在模型调参里,大概率两周过去连大屏都没做出来,心态很容易崩。
第二,答辩和演示前,一定要准备一份“数据剧本”。比如:输入一个特定的用户ID,预测结果是“购买概率87%”,你打开他的行为序列,发现他最近3天在同一个类目下反复浏览加购,展示给评委看“模型为什么这么判断”。这种从数据到结论的完整链路,比干巴巴讲准确率有说服力得多。
第三,关于扩展方向,如果学有余力,可以在现有框架上加两个功能:一是把预测从“未来7天是否购买”升级成“未来7天购买哪些商品类目”的多标签预测,这会让项目从“能用”变成“有业务价值”;二是做一个简单的推荐模块,基于用户行为序列召回相似商品,和预测模块形成联动。这两块都是在现有Embedding和序列特征的基础上做的,迁移成本不高,但项目深度完全不一样了。
我在实际调试中最深的一个感受就是:这个项目难的不是任何一个单独的技术点,而是把Django、可视化、深度学习这三样东西串成一个完整作品的能力。只要按“数据先行、可视化兜底、模型收尾”的节奏走,稳扎稳打,这个题完全能做成一个拿得出手的毕业设计,甚至可以作为求职时的项目经验写进简历里。希望这份拆解能帮你少走点弯路,如果你在复现的时候遇到别的坑,欢迎带着报错信息来交流。