资讯动态

基于深度学习的用户购物行为预测系统:Django与LSTM实战

发布时间:2026/10/18 19:02:52 来源:尧图企业网站定制
简介本资源面向计算机专业学生与深度学习入门开发者提供一套基于Django与深度学习融合的淘宝用户购物可视化及行为预测系统完整实现方案适合作为毕业设计、课程项目或技术练手参考。压缩包共287个文件约15.35MB涵盖49个Python后端脚本、54个Vue前端组件、32个JavaScript文件及43个编译缓存文件另含41张JPG与28张PNG图表素材、8个CSS样式、6个HTML页面和多个批处理启动脚本前后端分离结构清晰。资源围绕系统架构设计、深度学习模型构建与训练、可视化模块呈现、数据采集与预处理、行为预测准确性评估等环节展开并附有万字论文、答辩PPT、部署说明与讲解视频。已有97人学习下载可帮助读者快速理解Django与深度学习结合的项目落地路径掌握从数据清洗、特征提取到模型评估的完整流程同时获得可复用的目录组织与排错思路。1. 从一份电商行为数据说起这套系统到底在解决什么问题电商后台每天沉淀的点击、收藏、加购、下单记录单看每一条都是流水账但把它们按用户维度串起来就是一张能预测下一步动作的行为图谱。这套「基于深度学习的用户购物可视化与行为预测系统」核心就两件事把散落在订单表、行为日志表里的数据变成能看懂的图表再用序列模型判断某个用户接下来会不会买、会买什么品类。它适合两类人一类是手里有电商数据集、想跑通「数据清洗→特征工程→模型训练→前端展示」全链路的开发者另一类是需要在课程设计或内部技术验证里快速搭出一个能演示、能讲清原理的原型系统的同学。技术栈上后端用 Django 做接口和权限前端用 ECharts 做可视化模型侧用 LSTM 或 GRU 处理用户行为序列整套东西不依赖昂贵算力单机就能跑。2. 数据层怎么搭从原始日志到模型可用的行为序列2.1 先想清楚要预测什么再决定表结构很多人在这一步翻车是因为一上来就建表、导数据结果训练时发现标签对不上。行为预测的标签通常有三种二分类的「是否购买」、多分类的「下一个交互品类」、回归类的「未来 7 天消费金额」。我一般会先定标签再倒推需要哪些字段。以「是否购买」为例输入是用户过去 N 次行为序列输出是 0/1。原始数据至少需要用户 ID、商品 ID、品类 ID、行为类型点击/收藏/加购/下单、时间戳。Django 的 models.py 里我会把原始行为日志和用户画像分开建表避免宽表字段膨胀。# models.py 核心表结构 from django.db import models class UserProfile(models.Model): user_id models.CharField(max_length64, uniqueTrue, db_indexTrue) age_range models.CharField(max_length16, blankTrue) register_days models.IntegerField(default0) # 注册天数做静态特征 class BehaviorLog(models.Model): user models.ForeignKey(UserProfile, on_deletemodels.CASCADE) item_id models.CharField(max_length64) category_id models.CharField(max_length64) behavior_type models.SmallIntegerField() # 1点击 2收藏 3加购 4下单 ts models.DateTimeField(db_indexTrue) # 时间戳必须建索引 class Meta: indexes [models.Index(fields[user, ts])]逻辑说明BehaviorLog 里 behavior_type 用整数而不是字符串是为了后续做 embedding 时直接映射ts 建联合索引因为序列切分要按用户和时间排序没索引在百万级数据上会慢到怀疑人生。参数上user_id 用 CharField 而不是自增主键是因为原始数据里的用户标识往往是哈希串直接沿用省去映射表。2.2 序列切分滑动窗口的窗口长度和步长怎么定行为序列不能直接把一个用户所有记录塞进模型太长且噪声大。常见做法是滑动窗口取最近 L 条行为作为一个样本预测第 L1 条是否购买。L 的取值我一般从 10 开始试步长取 1 做数据增强。窗口太短小于 5模型学不到上下文太长大于 50训练慢且容易过拟合。下面这段代码把 BehaviorLog 转成 (序列, 标签) 的 numpy 数组。import numpy as np from collections import defaultdict def build_sequences(logs, window10, step1): # logs: 按 user_id, ts 排好序的列表元素为 (user_id, item_id, behavior_type) user_seq defaultdict(list) for uid, item, btype in logs: user_seq[uid].append(btype) X, y [], [] for uid, seq in user_seq.items(): if len(seq) window 1: continue # 序列太短直接丢弃别硬补零 for i in range(0, len(seq) - window, step): X.append(seq[i:iwindow]) y.append(1 if seq[iwindow] 4 else 0) # 4 表示下单 return np.array(X), np.array(y)逻辑说明这里只用了 behavior_type 作为序列特征实际项目中可以把 item_id 的 embedding 拼进去。参数 window 控制历史长度step 控制样本重叠度step1 时样本量最大但相邻样本高度相关训练时要注意验证集按用户划分而不是随机划分否则会数据泄漏。标签生成里把「下单」作为正样本其他行为作为负样本正负比通常悬殊后面训练时要处理。2.3 类别不平衡别急着上 SMOTE先看业务容忍度电商行为里下单占比往往不到 5%直接训练模型会偏向预测「不买」。我试过三种做法一是对负样本下采样二是给正样本加权三是用 focal loss。下采样简单但丢信息加权改动最小focal loss 适合极端不平衡。实际落地时如果业务更怕漏掉潜在买家就提高正样本权重如果更怕误打扰就保持原始分布但调阈值。Django 侧不需要感知这些模型训练脚本独立跑导出权重文件给推理接口用。3. Django 后端与深度学习模型的对接方式3.1 模型不放在 Django 进程里用独立推理服务新手常犯的错是把 PyTorch 模型直接 load 在 Django 的 views.py 里每次请求都前向传播结果并发一上来 GIL 和显存一起炸。我的做法是训练脚本导出 ONNX 或 TorchScript起一个独立的推理服务FastAPI 或 Flask 都行Django 只负责调 HTTP 拿结果。这样 Django 可以多 worker 部署推理服务单独控制并发。下面是一个最小推理服务示例。# inference_server.py 独立进程 import torch from fastapi import FastAPI from pydantic import BaseModel app FastAPI() model torch.jit.load(behavior_lstm.pt) # TorchScript 导出 model.eval() class SeqReq(BaseModel): seq: list[int] # 行为类型序列 app.post(/predict) def predict(req: SeqReq): x torch.tensor([req.seq], dtypetorch.long) with torch.no_grad(): logit model(x) prob torch.sigmoid(logit).item() return {buy_prob: round(prob, 4)}逻辑说明TorchScript 导出后不依赖训练时的 Python 类定义部署干净。seq 用 list[int] 接收Django 侧把用户最近行为查出来直接传。prob 返回给前端做阈值判断阈值不写死在服务里方便业务调整。3.2 Django 侧封装超时、降级、缓存三件套Django 调推理服务必须设超时否则推理服务卡住会拖垮整个后端。我一般用 requests 设 timeout2 秒失败时返回默认概率 0.5 并记日志保证页面不白屏。另外同一个用户短时间内多次请求结果可以缓存 5 分钟减少推理压力。# services.py import requests from django.core.cache import cache def get_buy_prob(user_id, seq): key fprob:{user_id}:{hash(tuple(seq))} cached cache.get(key) if cached is not None: return cached try: resp requests.post( http://127.0.0.1:8001/predict, json{seq: seq}, timeout2 ) prob resp.json()[buy_prob] except Exception: prob 0.5 # 降级默认值 cache.set(key, prob, timeout300) return prob逻辑说明缓存 key 用 user_id 加序列哈希避免不同序列命中同一结果。timeout2 是经验值推理服务正常在 50ms 内返回2 秒足够覆盖冷启动。降级返回 0.5 而不是 0 或 1是为了不让前端展示过于绝对的结论。3.3 可视化接口ECharts 要的数据格式和后端聚合前端 ECharts 要的是聚合后的数组不是原始明细。比如「用户行为漏斗」需要四个阶段的计数「品类偏好」需要 top10 品类及占比。这些聚合在 Django ORM 里用 annotate 做别把全量数据拉到 Python 里循环。from django.db.models import Count def behavior_funnel(): qs BehaviorLog.objects.values(behavior_type).annotate(cntCount(id)) mapping {1: 点击, 2: 收藏, 3: 加购, 4: 下单} return [{stage: mapping[r[behavior_type]], count: r[cnt]} for r in qs]逻辑说明values annotate 生成 GROUP BY 查询数据库层完成聚合。返回结构直接对应 ECharts 的 dataset前端不用再转换。如果数据量特别大可以加时间范围过滤避免全表扫描。4. 避坑与排查那些让模型和页面一起崩的细节4.1 时间戳时区不统一序列顺序全乱现象训练时 loss 正常下降但验证集准确率始终 0.5 左右。原因BehaviorLog 里 ts 存的是 UTC但部分数据导入时用了本地时间排序后序列顺序错乱。解决入库前统一转 UTCDjango 设置 USE_TZTrue查询时用 order_by(ts) 显式排序别依赖默认顺序。4.2 验证集随机划分导致数据泄漏现象验证准确率 0.95上线后实际效果一塌糊涂。原因同一个用户的多个窗口样本被随机分到了训练集和验证集模型见过该用户的其他片段。解决按 user_id 划分用 GroupShuffleSplit 或手动按用户切分确保验证集用户不出现在训练集。4.3 推理服务显存不释放跑几小时就 OOM现象推理服务运行一段时间后报 CUDA out of memory。原因每次请求都创建新 tensor 且没释放或者模型没有设 eval 模式导致 dropout 层持续计算。解决模型 load 后立即 model.eval()推理包在 torch.no_grad() 里tensor 用 .detach() 断开计算图。如果还不行限制服务并发数用队列削峰。4.4 Django 静态文件 404ECharts 加载不出来现象页面结构正常但图表空白控制台报 echarts.min.js 404。原因DEBUGFalse 时 Django 不再自动服务静态文件而 collectstatic 没执行或 STATIC_ROOT 配置错误。解决生产环境用 Nginx 托管 static 目录或者临时把 DEBUG 打开验证。STATIC_URL 和 STATIC_ROOT 别写混前者是 URL 前缀后者是磁盘路径。4.5 序列长度不一致DataLoader 报错现象训练时 collate_fn 报 stack expects each tensor to be equal size。原因不同用户序列长度不同直接 stack 会失败。解决用 padding 补齐到固定长度或者用 pack_padded_sequence。我一般选 padding在 build_sequences 里就把短序列补零同时记录真实长度传给模型。5. 把预测结果用起来阈值调优与可视化联动的一个具体技巧模型输出的是一个 0 到 1 的概率直接拿 0.5 当阈值往往不是最优。我习惯在验证集上画一条 PR 曲线根据业务目标选阈值。比如运营活动希望覆盖更多潜在买家就把阈值降到 0.3牺牲精确率换召回率如果是短信打扰成本高就提到 0.7。这个阈值不写死在代码里放到 Django 的配置表或环境变量运营可以自己调。# 阈值调优脚本片段 from sklearn.metrics import precision_recall_curve import numpy as np probs model.predict_proba(X_val)[:, 1] prec, rec, thresholds precision_recall_curve(y_val, probs) f1 2 * prec * rec / (prec rec 1e-8) best_idx np.argmax(f1) best_thr thresholds[best_idx] print(f最佳阈值 {best_thr:.3f}, F1 {f1[best_idx]:.3f})逻辑说明precision_recall_curve 返回的 thresholds 长度比 prec/rec 少 1取 argmax 时注意索引对齐。best_thr 存到数据库推理服务每次请求时从缓存读避免硬编码。可视化联动上我一般会在用户详情页放一个「购买概率」仪表盘旁边列出该用户最近 10 条行为的时间线。概率高于阈值时时间线对应节点标红运营一眼就能看到是哪些行为推高了概率。这个联动不需要复杂前端框架ECharts 的 markLine 和 markPoint 就能做。最后说一个我踩过的坑别在 Django 的模板里直接写大段 JavaScript 拼 ECharts 配置后期改一个字段要翻半天。把配置项抽成 JSON 接口前端用 fetch 拿数据再 setOption模板只留一个空 div。这样后端改聚合逻辑不影响前端前端换图表类型也不用动 Django。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑