如果你正在准备计算机类毕业设计,又恰好想碰一碰 Web 开发、数据分析和深度学习三个方向,那么“基于 Django + 深度学习的电商用户购物可视化与行为预测系统”是一个很值得参考的题目。别被这个长名字吓到,拆开来看无非是:用 Django 写一个网站,把用户购物行为数据做成图表展示,同时训练一个深度学习模型,预测用户接下来会不会下单。这类题目在毕设里非常典型,难度适中,工作量肉眼可见,答辩也好讲。
这篇文章我会按实际做项目的顺序,从需求拆解、数据准备、模型训练、系统集成到文档撰写和答辩准备,把完整链路讲一遍。就算你之前只写过简单的 CRUD,也能顺着思路搭出一个能跑、能讲、能答辩的项目。项目里的数据我统一以“电商平台用户行为日志”代称,不绑特定平台,换成任何公开电商行为数据都能跑。
1. 项目定位:这个毕设到底在做什么
1.1 一句话拆解核心功能
这个系统可以拆成三个核心块:用户购物可视化、用户行为预测、后台管理。
先看可视化。页面上要能看到整体销售趋势、用户活跃度、商品热门排行、地区分布、行为转化漏斗。图表不是花架子,它要回答几个问题:平台整体走势怎么样、哪类商品最受欢迎、用户从浏览到购买转化率如何。对毕设而言,这部分最直观,导师打开网页就能看到效果。
再看行为预测。这是整个系统的亮点模块。输入一个用户的最近N条行为序列,比如最近看了哪些商品、加购了什么、最终买了什么,模型输出他下一步最可能做什么:继续浏览、收藏、加购还是购买。把这一步做成在线功能,用户在前端页面选择一个用户ID,系统返回四类行为的概率,同时把历史行为序列展示出来,效果非常清晰。
后台管理用 Django Admin 就够了。管理用户、商品、行为日志、预测记录。预测结果保存到数据库,方便回看和演示。三个模块加起来,前端、后端、数据库、深度学习全都有了,工作量刚好覆盖本科毕设的要求,不会让人觉得只是套了一个管理系统模板。
1.2 技术选型为什么是 Django + 深度学习
后端框架选 Django,原因很实际:它自带的 ORM、Admin 后台、用户认证和模板系统可以直接用。做一个数据展示加模型预测的网站,不需要前后端完全分离,用 Django 的 Template + 少量 JavaScript 就能把页面做出来。Flask 虽然更轻,但很多功能要自己拼,比如数据库迁移、表单校验、分页,都得多花时间。Django 把所有常用能力提前装好了,适合一个人短周期完成。
深度学习部分选 TensorFlow / Keras 或者 PyTorch 都可以。毕设推荐用 Keras 的 Sequential 或 Functional API 来搭模型,代码短、调试直观、显存要求低。LSTM 这类序列模型处理用户行为序列很合适,一段行为日志本身就是有时间顺序的,用户先浏览、再比较、最后购买,这个顺序信息对预测很重要。
可视化部分选开源图表库,比较常见的是 ECharts。它配置简单,折线图、柱状图、饼图、漏斗图都有现成组件,配合 Django 返回的 JSON 数据,前端几行代码就能渲染。数据库先用 SQLite 起步,数据量到几十万条依然跑得动,等后期需要并发访问再换 MySQL 或 PostgreSQL。缓存可以用 Redis,但也不是必须,先跑通再优化。
1.3 交付物拆解:程序、文档、讲解、定制
标题里提到的“程序 + 文档 + 讲解 + 定制”几乎可以对应到毕业设计的四个交付环节。
程序就是完整工程,包括数据预处理脚本、模型训练脚本、Django 项目代码、前端模板、静态资源。文档包括需求分析、数据库设计、接口说明、模型原理、部署手册。讲解指答辩PPT和演示话术,要能把项目讲清楚,不能只会跑代码。定制则是这个题目最常见的扩展方式:换一套数据集、换一个预测目标、加一个推荐模块、改用其他模型,都能变成一篇新论文。
做之前想清楚这四件事,整个项目就不会只是为了“交差”。我的建议是先把程序跑通,再补文档,最后准备讲解,这个顺序最省时间。
2. 数据从哪来:电商用户行为数据的获取与预处理
2.1 数据集选择与字段说明
电商平台的真实数据通常拿不到,也不建议去爬,既有合规风险,数据质量也无法保证。毕设场景下直接用公开的电商行为日志数据集最稳妥。这类数据集一般包含用户ID、商品ID、商品类目ID、行为类型、时间戳五个字段。
行为类型常见的有四种:浏览、收藏、加购、购买。为了方便模型处理,要统一编码。浏览可以编码为 0,收藏为 1,加购为 2,购买为 3。编码本身没有实际大小含义,后续会通过 Embedding 层映射成向量,所以数字顺序不影响模型效果。
数据量不需要贪大,几十万条到一百万条就足够了。数据太少模型容易欠拟合,太多训练时间太长,毕设阶段“够用”就好。另外可以额外造一些统计特征,比如用户活跃天数、近7天浏览数、近7天加购数、用户购买力分群等,这些特征能提升模型效果,后面要合并到训练样本里。
2.2 数据清洗与行为序列构造
拿到原始日志后,第一步是做基础清洗。时间戳要转成 datetime 类型,统一格式;缺失字段直接删除;用户ID和商品ID中的异常值要过滤;如果有重复日志,需要去重。然后按用户ID分组,组内按时间戳排序,得到每个用户的完整行为序列。
这一步的代码思路大概是:
import pandas as pd # 读取原始行为日志 df = pd.read_csv('behavior_log.csv') df['timestamp'] = pd.to_datetime(df['timestamp']) # 去重、排序 df = df.drop_duplicates() df = df.sort_values(['user_id', 'timestamp']).reset_index(drop=True) # 行为类型编码 behavior_map = {'pv': 0, 'fav': 1, 'cart': 2, 'buy': 3} df['behavior'] = df['behavior'].map(behavior_map) # 过滤行为数过少的用户 user_cnt = df.groupby('user_id').size() valid_users = user_cnt[user_cnt >= 20].index df = df[df['user_id'].isin(valid_users)]为什么过滤行为数少于 20 的用户?因为深度学习模型需要足够的上下文。如果一个用户只有两三条行为,序列特征学不到东西,预测结果也没意义。过滤之后,剩下的用户行为轨迹更完整,模型训练也更稳定。
2.3 标签构造与样本平衡
预测用户“下一步行为”本质是一个分类问题。给定用户最近 K 条行为,预测第 K+1 条行为属于哪个类别。构造样本的时候采用滑窗方式:以每个用户的完整行为序列为基准,窗口长度为 10,标签为第 11 个行为类型。窗口每次向后滑动一步,就能生成大量训练样本。
代码如下:
def create_samples(user_group, seq_len=10): X_user, X_item, X_behavior, y = [], [], [], [] behaviors = user_group['behavior'].values items = user_group['item_id'].values user_id = user_group['user_id'].iloc[0] for i in range(seq_len, len(behaviors)): X_item.append(items[i - seq_len:i]) X_behavior.append(behaviors[i - seq_len:i]) X_user.append(user_id) y.append(behaviors[i]) return X_user, X_item, X_behavior, y这里需要注意的是:特征只包含第 i 个行为之前的序列,标签是第 i 个行为,绝不能用前后混合的数据,否则会造成严重的数据泄露。
类别不平衡是这类数据最典型的问题。浏览行为占比极高,购买行为占比很低。如果不处理,模型会倾向于把所有样本都预测成浏览,准确率看似不低,实际没有意义。解决思路有两种:第一种是训练时给不同类别设置权重,购买类权重大一点;第二种是对购买样本做过采样,让每个 batch 里各个类别的数量相对均衡。实际用下来 class_weight 最简单,几行代码就能接进 Keras。
2.4 数据划分按用户还是按时间
训练集、验证集、测试集的划分有一个容易被忽略的坑:不能随机打乱所有样本再切分。同一用户的两条样本可能在训练集和测试集里同时出现,模型相当于已经见过这个用户的模式,测试结果虚高。
正确的做法是按用户划分,或者按时间划分。按用户划分就是把用户ID集合切成三段,分别构建训练集、验证集、测试集。按时间划分则是取时间戳前 80% 作为训练集,后 20% 作为测试集。我更推荐按时间划分,因为要预测的是未来行为,用过去的数据训练、未来的数据验证,更贴近真实场景。
3. 预测模型:用深度学习预测用户下一步行为
3.1 问题建模:多分类不是回归
行为预测不是预测“买不买”这种二分类,也不是预测“未来销售额多少”这种回归,而是预测用户下一步的具体行为类型,包含浏览、收藏、加购、购买四个类别。虽然也可以简化成二分类,比如“转化”和“不转化”,但四分类在答辩时更好讲,和真实业务场景也更贴近。
模型输入有三类信息:用户ID、最近商品ID序列、最近行为类型序列。用户ID可以理解为用户的静态画像,商品序列和历史行为序列则反映用户在短期内的兴趣变化。输出的是长度为 4 的概率向量,取 argmax 得到预测类别。
这里要强调一个原则:预测的标签是第 11 步行为,输入是前 10 步,时间边界必须严格。用户在第 10 步刚刚加购,那么第 11 步购买的概率自然会升高,模型要学的正是这种“加购之后容易购买”的规律。
3.2 模型结构:Embedding + LSTM + Softmax
模型不需要太复杂,一个简单的 Embedding 加 LSTM 结构就够用。Embedding 层会把稀疏的 ID 映射成稠密向量,LSTM 层负责捕捉序列依赖关系,最后的全连接层输出概率分布。
完整的构建代码如下:
from tensorflow.keras.models import Model from tensorflow.keras.layers import ( Input, Embedding, LSTM, Dense, Concatenate, Dropout, Reshape ) def build_model(user_vocab, item_vocab, seq_len=10, embed_dim=32): # 用户ID输入 user_input = Input(shape=(1,), name='user_id') user_emb = Embedding(user_vocab, embed_dim, name='user_emb')(user_input) user_emb = Reshape((embed_dim,))(user_emb) # 商品ID序列输入 item_input = Input(shape=(seq_len,), name='item_seq') item_emb = Embedding(item_vocab, embed_dim, name='item_emb')(item_input) # 行为类型序列输入 behavior_input = Input(shape=(seq_len,), name='beh_seq') behavior_emb = Embedding(4, embed_dim, name='beh_emb')(behavior_input) # 拼接序列特征 seq_vec = Concatenate(axis=-1)([item_emb, behavior_emb]) lstm_out = LSTM(64, return_sequences=False)(seq_vec) # 用户向量与序列输出拼接 merged = Concatenate(axis=-1)([user_emb, lstm_out]) merged = Dropout(0.3)(merged) output = Dense(4, activation='softmax', name='output')(merged) model = Model(inputs=[user_input, item_input, behavior_input], outputs=output) model.compile( optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'] ) return model解释一下为什么这样设计:用户ID Embedding 学习的是用户长期偏好;商品 Embedding 学习商品之间的相似关系;行为 Embedding 学习“浏览”“加购”“购买”这些行为的语义关系。LSTM 则把最近十步的行为模式压缩成一个向量,比如“浏览A商品、浏览B商品、加购A商品”这种模式,最后的 Dense 层再决定下一步最可能的行为。
3.3 训练配置与评价指标
训练时建议使用 EarlyStopping 和类别权重。EarlyStopping 可以避免过拟合,如果验证集指标连续几个 epoch 不提升就停止训练。类别权重让少数类(购买)在 loss 中的占比更高。
一个典型的训练配置如下:
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau class_weights = {0: 0.2, 1: 1.0, 2: 1.2, 3: 3.0} callbacks = [ EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True), ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=2) ] model.fit( [train_user, train_item, train_behavior], train_label, batch_size=128, epochs=20, validation_data=([val_user, val_item, val_behavior], val_label), class_weight=class_weights, callbacks=callbacks )类别权重的具体数值不需要太纠结,浏览占比高就给 0.2,购买占比低就给 3.0,训练过程中看验证集表现再微调。
评价指标不能只看准确率,因为类别不平衡导致准确率天然偏高。重点看 Macro-F1 和 AUC。Keras 训练过程中可以记录 accuracy,但最终在测试集上建议用 scikit-learn 的 metrics 计算各指标:
from sklearn.metrics import classification_report, roc_auc_score y_pred = model.predict([test_user, test_item, test_behavior]) y_pred_label = y_pred.argmax(axis=1) y_true_label = test_label.argmax(axis=1) print(classification_report(y_true_label, y_pred_label))3.4 模型导出与 Django 集成
训练完成后,把模型保存为 H5 格式或者 SavedModel 格式。H5 文件单个文件比较方便:
model.save('models/behavior_model.h5')Django 中加载模型不能放在视图函数里重复加载,否则每个请求都会读一次磁盘,性能很差。正确做法是在 Django 应用启动时加载一次,放到模块级变量或者一个单例类里。
4. 可视化与系统实现:Django 怎么把数据和模型串起来
4.1 系统整体架构
整个系统可以分成三层:数据层、服务层、展示层。
数据层负责存储用户、商品、行为日志、预测记录。Django 默认的 SQLite 在一百万条数据内都能胜任,表结构按照业务设计:用户表、商品表、行为日志表、预测记录表。服务层负责数据聚合和模型预测,包括可视化接口、预测接口、后台管理逻辑。展示层用 Django Template 加 JavaScript 实现,核心图表通过开源库渲染。
前后端不分离,用 Django 视图返回数据,Template 直接渲染页面,部分需要异步加载的数据用 Ajax 请求 JSON 接口。这样做的好处是代码量少,国内多数毕设团队都能维护。
4.2 页面规划与导航
我的建议是设计五个主页面:
第一个是首页仪表盘,放核心指标卡片和总体趋势图,展示用户总数、商品总数、行为总数、整体转化率。第二个是用户分析页,展示用户活跃度分布、行为路径、浏览到购买的漏斗图。第三个是商品分析页,展示热门商品 Top10、类目销售占比、商品价格分布。第四个是行为预测页,用户选择用户ID后,系统展示最近行为序列并输出预测概率。第五个是 Django Admin 后台,用于管理数据和查看预测记录。
首页仪表盘是整个项目的门面,建议花最多时间做。图表布局要整齐,指标卡片要醒目,趋势图颜色统一。答辩时最先打开的就是这个页面,第一印象很重要。
4.3 后端接口设计与返回格式
可视化数据不要在前端写死,后端提供 JSON 接口。用 Django 视图返回 JSON 最简单的做法是 JsonResponse。
一个典型的趋势接口可能是:
from django.http import JsonResponse from django.db.models import Count, Sum from .models import BehaviorLog def trend_data(request): days = request.GET.get('days', 30) # 实际项目中可以按天聚合 trend = ( BehaviorLog.objects .values('date') .annotate(cnt=Count('id')) .order_by('date')[:days] ) return JsonResponse({ 'dates': [item['date'] for item in trend], 'counts': [item['cnt'] for item in trend] })注意前端需要的是列表,日期和数值要分开返回,方便图表直接绑定。返回之前最好先 sort,否则折线图会出现乱序。
4.4 ECharts 可视化核心图表
ECharts 的核心用法是 setOption,一个典型的折线图配置如下:
const trendChart = echarts.init(document.getElementById('trendChart')); trendChart.setOption({ title: { text: '近30天行为趋势' }, tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: dates }, yAxis: { type: 'value' }, series: [{ name: '行为数', type: 'line', data: counts, smooth: true }] });页面加载时用 fetch 或 axios 请求后端接口,拿到数据后更新图表。需要注意的一点是:ECharts 的容器要有明确高度,很多新手把 div 高度设置成 0 或未设置,图表就不显示。建议每个图表父容器都显式给 height,比如 400px 或 60vh。
漏斗图很适合展示用户转化路径。从浏览到收藏、加购、购买,每一步的人数都在减少,漏斗图能把流失过程直观展示出来。
4.5 在线预测功能实现
在线预测是系统的核心亮点。页面选择用户后,后端从行为日志表读取该用户最近 10 条行为,组装成模型输入,调用已经加载好的模型。
代码的大致流程:
def predict_view(request): user_id = request.GET.get('user_id') if not user_id: return JsonResponse({'error': '缺少 user_id'}) recent = get_recent_behavior(user_id, length=10) if len(recent) == 0: return JsonResponse({'error': '该用户没有行为记录'}) # 如果不足10条,在左侧做 padding,统一长度 item_seq, beh_seq = pad_sequence(recent, seq_len=10) prob = predict_next_behavior(user_id, item_seq, beh_seq) return JsonResponse({ 'user_id': user_id, 'prob': prob, 'history': recent })这里有一个细节:模型训练时输入的序列长度固定为 10,线上预测时也要构造同样长度。如果某用户不足 10 条,用 0 填充商品ID和用 -1 填充行为类型,但要在 Embedding 层预留 padding 索引。如果用户行为超过 10 条,取最近 10 条即可。
预测结果保存到预测记录表,方便后续展示和导出。预测页除了输出概率,还可以画一个饼图或者横向条形图,视觉上很直观,答辩时可以拿这个页面重点讲。
4.6 性能优化与异步任务
毕设数据量不大,性能压力不明显,但有几个优化点可以加分。第一,可视化接口用数据库聚合,不要把所有原始数据查出来再丢给 Pandas 处理,能直接在 SQL 层算完的就直接算。第二,高频接口加缓存,比如首页仪表盘的数据 5 分钟内不会变,可以用 Django 的 cache 框架缓存住,减少重复查询。第三,如果训练时间长,可以把模型训练放到后台任务里,用户提交训练请求后页面显示训练进度,训练完成再刷新结果。这部分用 Celery 加 Redis 可以实现,但毕设非必需。
缓存示例:
from django.core.cache import cache def dashboard_data(request): data = cache.get('dashboard_data') if data is None: data = compute_dashboard_data() cache.set('dashboard_data', data, timeout=300) return JsonResponse(data)加上这层优化,答辩时可以理直气壮地说自己考虑了系统性能。
5. 常见坑位与排查技巧实录
5.1 模型加载慢和多线程冲突
Django 开发服务器默认是多线程的,TensorFlow 模型第一次加载到内存可能要几秒钟,如果每次请求都重新加载一次,接口会慢到不可用。解决方法是启动时加载模型,并且加一个线程锁保护预测过程。
import threading from tensorflow.keras.models import load_model _model = None _lock = threading.Lock() def get_model(): global _model if _model is None: with _lock: if _model is None: _model = load_model('models/behavior_model.h5') return _model这个写法是典型的懒加载加双重检查,既避免重复加载,又保证多线程安全。
5.2 数据泄露导致指标虚高
数据泄露是这类项目里最隐蔽的坑。一旦某一条样本的标签出现在同一条样本的特征里,模型在训练集上表现会异常好,但真正部署后效果很差。典型错误是:构造序列时用了滑窗却忘了丢弃最后一个行为,或者做数据归一化时用了全量数据的均值,把测试集信息带进了训练过程。
排查方法很简单:做一个“随机模型”基线。如果随机模型也能达到 70% 的准确率,说明标签分布严重倾斜;如果模型在训练集上接近 100%,在测试集上却快掉到随机水平,基本可以判断是数据泄露。
5.3 前端图表渲染不出来
图表不显示的原因通常有三个:容器没有高度、数据格式不对、JavaScript 执行顺序问题。ECharts 初始化时容器必须存在于 DOM 中,如果页面脚本在 DOM 加载之前执行,也会拿到空容器。
排查这类问题,先用浏览器的开发者工具看接口返回的数据,确认是数组还是字符串。再从后端角度检查 JsonResponse 是否把 Python 列表正确序列化了。最后确认图表容器有固定的高度,比如height: 400px。
5.4 文档撰写与答辩准备
文档部分建议按七个部分组织:需求分析、系统设计、数据库设计、算法设计、系统实现、系统测试、总结。算法设计是重点,要写明白为什么用 LSTM、输入输出是什么、准确率和 F1 是多少。数据库设计要给出 ER 图和核心表结构。系统实现部分要附关键代码和页面截图。
答辩时不要照着 PPT 念,重点讲三件事:数据怎么来的、模型怎么训练的、系统有哪些模块。看到“用户行为预测”这个功能,评委大概率会问“为什么不用规则”,“模型准确率多少”,“训练集测试集怎么划分”。这些都要提前准备。还有一个容易被问倒的问题:“如果换成另一个电商平台,你的模型还能用吗?”答案是可以,因为模型输入的是用户ID、商品ID和行为序列,不依赖平台特有字段,新数据只需要做同样的清洗和编码。
5.5 定制扩展的方向
如果题目需要定制,通常有四个方向可以改。数据集方向:换一套更完整的电商数据,加入价格、品牌、评论等字段。模型方向:把 LSTM 换成 Transformer 或增加注意力机制,提升预测效果。功能方向:在行为预测基础上增加商品推荐模块,或者增加用户分群。部署方向:把系统部署到云服务器,加上 Nginx 和 uWSGI,做一个线下演示环境。
每个方向改起来难度都不算大,但都需要重新训练和测试。读者可以根据自己时间精力选一到两个方向扩展。
说实话,这类项目做下来,收获最多的地方其实不在某一个算法,而在把数据、模型、Web 系统串起来的完整流程。我自己在做类似项目时,最常跟同学强调的就是:先跑通最小闭环,再慢慢加图表、加模型、加文档。否则一开始就追求完美,很容易卡在某个环境问题上,最后连一个能演示的页面都出不来。希望这篇拆解能帮你少走一点弯路。