ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

电商用户行为预测与可视化:Django+LSTM完整实战

电商用户行为预测与可视化:Django+LSTM完整实战 1. 这个选题为什么值得做需求与价值拆解1.1 电商用户行为数据最典型的大数据场景淘宝用户购物数据在我看来是所有大数据入门场景里最“教科书”的一个。它天然具备高维、稀疏、强时序三个特征一条原始行为记录里至少包含用户ID、商品ID、类目ID、行为类型比如浏览pv、收藏fav、加购cart、购买buy和时间戳字段虽然不多但量级一上来就是千万级甚至亿级。这种数据和金融风控、物联网日志、内容推荐的数据结构非常相似学会处理它后面换任何业务场景都只是换表名而已。很多同学一开始看到“淘宝用户购物可视化与行为预测”这个标题第一反应是“这不是爬虫吗”。说实话我刚开始也这么想。但实际做下来会发现真正的难点不在爬数据而在怎么把一堆零散的点击日志变成有业务含义的指标和可训练的样本。这里我强烈建议不要直接爬淘宝一是合规风险高二是反爬机制会让你浪费大量时间。公开的UserBehavior数据集阿里天池就有完全够用做毕业设计的体量不需要去硬刚真实网页。行为预测的业务价值也很直观。电商平台最关心的一件事就是转化率来了100个访客最后到底有几个人下单平台能不能提前识别出“这个用户最近可能要买某类商品”如果能做到就可以做精准优惠券、商品推荐、库存调度。放到毕业设计里你只需要回答一个简化问题给定用户过去一段时间的浏览、收藏、加购序列预测他下一步会不会购买。这个问题能讲清楚答辩老师的核心问题基本就过关了。1.2 一个系统覆盖“大数据深度学习可视化”三条主线毕设评审最看重的几点我总结为工程完整度、算法理解度、呈现效果。很多系统要么只做了数据分析和可视化没有算法要么只训练了一个模型连网页都没有。而这个题目恰好把三条线串在一起Django负责后端和业务逻辑深度学习负责行为预测ECharts负责数据可视化。你一个人就能走通“数据清洗→特征工程→模型训练→接口服务→前端展示”的完整闭环这在答辩时是非常大的加分项。往深了说这个系统还可以延伸到用户画像、商品推荐、复购预测、实时营销等多个方向。毕设阶段你可以只做购买行为预测但代码结构上留好扩展位以后求职想包装成推荐系统项目也顺理成章。网上那些“附源码文档调试服务”的版本很多但我建议至少把核心代码自己敲一遍尤其是数据预处理和模型训练脚本面试官很爱追问这两块的细节。1.3 谁适合选这个题目如果你是那种Python语法熟悉但没系统接触过深度学习的学生这个题目的友好之处在于它不需要你发明新模型。淘宝用户行为预测的主流做法非常成熟网上能找到很多参考你要做的是把LSTM、DeepFM这类模型应用到自己的数据上再解释清楚为什么这么选。我见过不少零基础的同学两三天就能跑通一个基础版模型真正花时间的是数据清洗和Django对接。如果你本来目标就是数据挖掘或推荐系统方向的岗位这个项目简直是天然的简历素材。它既有时序特征处理又有模型训练和评估还有服务化部署和可视化几乎把日常数据分析工作流里最核心的环节都覆盖了。选这个题目本质上是花一个毕设周期提前体验一遍工业界“用户行为数据→决策模型→业务产品”的完整链路。2. 系统整体设计架构与技术选型2.1 功能模块怎么划分我觉得做毕设最忌讳一上来就写代码先把功能模块切清楚后面能省一半时间。这个系统可以拆成四个模块数据接入与清洗模块负责读取原始csv日志、处理缺失值、转换时间戳、行为类型映射、用户和商品抽样。行为预测模块做特征工程训练深度学习模型LSTM/DeepFM保存模型文件对外提供预测接口。可视化展示模块提供总览大屏、用户行为漏斗、商品热销排行、活跃时段分布、未来购买概率TOP用户列表。用户与权限模块用Django Admin做简单的后台管理给系统加登录和权限控制。模块切好以后开发和调试都能并行推进。比如我先把数据预处理脚本跑通把特征文件存成csv再让深度学习脚本读这个csv训练模型Django那边可以先把可视化页面写出来用假数据渲染等模型接口好了再对接真预测结果。这样即使中间某一步卡住也不会让整个项目停滞。2.2 为什么选Django而不是Flask或Spring Boot这个题目里的关键词“django”不是随便选的。Flask虽然轻量但做这种需要后台管理、用户认证、ORM建表的系统还是要自己装不少扩展。Django自带Admin后台、用户认证、模板引擎和ORM对毕业设计的开发效率提升非常明显。比如我想在后台给管理员加一个“重新训练模型”的按钮用Django Admin几行配置就能搞定如果用Flask从表单到路由、权限、日志都要自己写工作量会大很多。Spring Boot也是很多同学会纠结的选项它对大数据生态支持好但Java的学习成本比Python高。这个题目的算法部分用到TensorFlow或PyTorch属于Python生态用Django可以让前后端和算法语言统一省去跨语言调用的麻烦。实测下来Django跑一个中小型数据可视化系统性能完全够用真正耗时的模型推理放到后台任务里异步执行就可以不需要上微服务那套复杂架构。2.3 数据库设计与数据流向数据库设计直接决定你后面写代码痛不痛快。我的做法是三张核心表User表user_id、gender、age_level、city_level用户的静态属性。Product表product_id、category_id、brand_id商品的基础信息。Behavior表id、user_id外键、product_id外键、behavior_type、timestamp行为日志。最核心的是Behavior表它承担几乎所有特征计算。注意它不是一张“当前状态表”而是一张时序流水表每天都会产生大量新记录。做可视化时直接查Behavior表聚合出“今日PV/UV/下单量”就很快做模型特征时也是从这个表里按user_id分组提取最近N天的行为序列。数据流大致是这样原始csv先经过pandas清洗写入MySQL的Behavior表Django通过ORM查询统计数据供可视化接口使用训练脚本从MySQL里读样本构造特征训练完成后把模型文件放好预测接口读取请求里的用户特征经过同样的特征处理流程输入模型得到购买概率。这套链路里Redis可以放在中间做缓存比如把热榜数据缓存起来减轻数据库压力。这里提一个Django ORM的小技巧删除Behavior表中某个用户的数据不需要写SQL直接用Behavior.objects.filter(user_idxxx).delete()。很多人会忘记ORM的删除操作返回的是一个元组(deleted_count, {app.Behavior: count})调试的时候看到这个结果才知道删了多少行。这类细节虽然小但真能帮你节省排查时间。2.4 前后端交互与实时推送毕设阶段不需要做太复杂的前后端分离。我是先用Django模板直接渲染页面把ECharts要的数据结构在view里组装好传到模板里再让JavaScript初始化图表。这样做的好处是少写一套API文档开发效率最高。如果有余力再上Django REST Framework做一套json接口为以后扩展移动端或小程序留空间。这里顺便回答一个很多人私信问的问题后台数据更新后网页怎么自动刷新这就是热搜词里“python django websocket实现后台有数据前端推送”的场景。传统做法是前端轮询接口每5秒请求一次简单但不优雅。更体面的做法是用Django Channels实现WebSocket后端感知到新行为数据后主动推给前端ECharts再更新图表。考虑到毕设时间我建议先用轮询系统做完以后再把某个图表升级成WebSocket实时推送既贴合业务又能展示技术深度。Redis在中间可以作为消息代理配合常用的Redis可视化客户端可以直观看到消息Queue里的数据是否被消费掉。3. 核心算法与模型构建行为预测怎么做3.1 特征工程从原始点击日志到模型输入行为预测最容易被忽视却又最影响效果的就是特征工程。直接拿原始行为日志丢给深度学习模型是行不通的模型需要的是提取后的特征或者至少是结构化的序列。我的做法是把特征分成四类用户基础特征性别、年龄层次、城市层次这部分是静态的。统计特征过去7天浏览商品数、收藏商品数、加购次数、购买次数行为总时长跨度。商品偏好特征用户最常浏览的Top3类目最近一次购买的类目。序列特征把用户最近20次行为按时间排序每个行为映射成一个整数编号比如浏览0、收藏1、加购2、购买3同时记录行为之间的时间间隔序列。标签的构造也很关键。我选择“未来3天内是否购买”作为二分类目标正样本为1负样本为0。淘宝用户行为是典型的长尾分布大部分用户只看不买所以正负样本比例经常能到1:20甚至更低后面一定要处理。特征工程做完以后可以存成两个文件train.csv和valid.csv。每一行是一个用户样本列包括前面提到的所有特征最后一列是label。这样深度学习脚本只需要读csv不需要回去查数据库训练速度会快很多。3.2 模型怎么选LSTM还是DeepFM市面上常见的用户行为预测模型主要分两类。一类是以LSTM、GRU为代表的序列模型专门处理“用户先看了A又看了B最后加购了C”这种先后关系另一类是以DeepFM、WideDeep为代表的深度推荐模型擅长捕捉类别特征的交叉组合比如“女装类目收藏行为”这种组合对购买的刺激。对毕设来说我推荐用LSTM加一层注意力机制作为主模型。理由很直接淘宝用户行为的核心信息藏在“行为顺序”里浏览、收藏、加购、购买这四种行为有强烈的先后依赖LSTM对这种时序依赖的建模能力比DeepFM更直观答辩时也更容易讲清楚为什么选它。DeepFM当然也很好但需要做的特征交叉分析偏多反而容易把自己绕进去。这里还想提醒一句不要为了追求高分模型把毕设做成调参大战。你的目标不是刷到0.99的AUC而是完整地展示“为什么会选这个模型、数据怎么喂进去、结果怎么评估、预测结果怎么用”。LSTMAttention的基线模型做到0.85左右的AUC已经足够支撑整个毕设的合理性和深度。3.3 训练流程与评估指标训练流程里最容易犯的错误是数据泄露。很多人直接把用户行为随机切成训练集和测试集结果同一个用户的一部分记录在训练集、一部分在测试集模型“见过”这个用户了预测分数虚高答辩时一问就露馅。正确做法是按时间切分比如取前7天的行为构造特征训练模型预测第8天到第10天是否购买。这样才符合真实的“用历史预测未来”场景。正负样本不平衡也要处理。我用的是两种方式结合一是对负样本做下采样让正负比例控制在1:5左右二是在训练时给正样本更高的class_weight。评估指标不能只看Accuracy因为如果99%是负样本全预测成负样本也能有99%准确率。要重点看AUCROC曲线下面积它不受阈值影响能真实反映模型排序能力。我实际跑下来LSTM基线模型的AUC大概在0.84到0.88之间召回率在选择性阈值下能到0.45以上对毕设来说完全够用。下面是一段简化的Keras模型训练代码我建议动手敲一遍而不是直接复制from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, LSTM, Dense, Attention, Concatenate # 序列特征输入行为序列长度固定为20 seq_input Input(shape(20,), nameseq_input) # 特征输入统计特征用户属性维度为 example_feature_dim feat_input Input(shape(feature_dim,), namefeat_input) embed Embedding(input_dim4, output_dim8, mask_zeroFalse)(seq_input) lstm_out LSTM(units32, return_sequencesFalse)(embed) # 将序列特征和统计特征拼接 concat Concatenate()([lstm_out, feat_input]) dense1 Dense(32, activationrelu)(concat) output Dense(1, activationsigmoid)(dense1) model Model(inputs[seq_input, feat_input], outputsoutput) model.compile(optimizeradam, lossbinary_crossentropy, metrics[AUC])训练时使用EarlyStoppingpatience设为3监控验证集AUC。我的经验是LSTM训练不需要太多epoch10到15轮基本收敛再多的轮次只会过拟合。3.4 模型如何交给Django调用模型训练完不是放到文件夹里就结束了Django要能加载并调用它。最直接的方式是用Keras的load_model加载.h5或.keras文件。但这里有个性能坑如果每次请求都加载一次模型内存里会反复创建对象并发一高页面直接卡死。正确做法是让模型在Django进程启动时只加载一次之后所有请求复用同一个对象。我用了一个很简单的单例封装from tensorflow.keras.models import load_model from functools import lru_cache lru_cache(maxsize1) def get_model(): return load_model(ml_models/best_model.keras)预测接口的逻辑也不复杂先根据请求里的user_id从Behavior表取出最近行为序列和统计特征做同样的特征工程再调用get_model().predict()得到购买概率。返回给前端的除了预测概率最好还带上解释性字段比如“该用户最近浏览主要集中在美妆类目”这样可视化页面也能顺带展示。4. 可视化大屏与指标设计4.1 大屏该放哪些图可视化不是把图表堆满屏幕就好而是要回答业务问题。我设计大屏时先问自己运营人员最关心什么答案是总体销量、用户活跃情况、转化漏斗、热门商品类目。所以我最终选了这些图表顶部核心指标卡今日PV、今日UV、今日下单量、整体转化率。左侧转化漏斗图浏览→收藏→加购→购买的整体转化链路。中间商品热销Top10柱状图并列出未来可能购买用户预测名单。右侧用户活跃时段热力图横轴是小时纵轴是星期几。底部用地图展示不同城市的下单用户分布。最有亮点的其实是“预测名单”和漏斗图的联动。漏斗图展示历史数据预测名单回答未来趋势前者是“已经发生了什么”后者是“接下来可能发生什么”正好把可视化和深度学习串起来答辩时你可以顺着这条线讲逻辑非常顺。4.2 ECharts和Django模板集成ECharts在Django模板里的用法比很多人想象中简单。我在view里构造好图表需要的dict传给模板模板里用{{ chart_data|safe }}序列化到JavaScript变量然后初始化ECharts实例。注意|safe过滤器一定要加否则Django会转义引号和小括号JSON被弄坏图表怎么都不显示。我通常会把每个图表的配置放到单独的JavaScript函数里比如initFunnel(data)、initBar(data)这样即使某个图表数据没返回页面其他部分也能正常渲染。另外ECharts的data数据格式非常固定接口返回的字段名一定要对清楚比如漏斗图要用value和name字段热力图要用[x, y, value]这样的三维数组。我调试时踩过最蠢的坑就是把列表当成对象传进去控制台不报错但图表空白后来对照官方示例才反应过来。4.3 WebSocket实时推送与Redis可视化做实时推送之前先想清楚有没有必要。如果只需要“手动刷新页面能看新数据”那完全不用上WebSocket。如果希望大屏像监控中心一样自动跳动再考虑Django Channels。我当时实现了一个简化版后台用Redis作为消息队列模拟程序不断往队列里写“用户发生新的购买行为”事件Django Channels的Consumer订阅这个队列当收到消息时通过WebSocket推送到前端页面前端收到后重新请求一次热销榜接口只更新柱状图部分。这个方案不复杂但能很好展示你理解“推送机制”和“数据解耦”。调试时我习惯用Redis桌面可视化管理工具查看key数量和队列长度确认消息确实生产出来了再去找前端的问题效率会高很多。5. 实操过程与关键代码片段5.1 环境搭建与项目初始化先说环境。我用的Python 3.10Django 4.2TensorFlow 2.13。建议先创建虚拟环境不要一股脑全装进全局环境否则后面依赖冲突会让人崩溃。依赖清单大致是这样pip install django djangorestframework channels pandas numpy scikit-learn tensorflow redis项目初始化用两条命令django-admin startproject taobao_analysis cd taobao_analysis python manage.py startapp behavior python manage.py startapp dashboardbehavior这个app放行为日志数据接入和特征处理dashboard放可视化接口和大屏页面。接下来在settings.py里注册app配置MySQL数据库设置STATICFILES_DIRS指向放ECharts和自定义JS的目录。项目结构最后会类似这样taobao_analysis/ ├── manage.py ├── taobao_analysis/ │ ├── settings.py │ └── urls.py ├── behavior/ │ ├── models.py │ ├── views.py │ └── train_features.py ├── dashboard/ │ ├── views.py │ ├── urls.py │ └── templates/ │ └── dashboard.html ├── ml_models/ │ └── best_model.keras └── static/ ├── echarts.min.js └── dashboard.js5.2 数据清洗和特征构建流程拿到原始数据后我一般先做三件事过滤异常时间戳、映射行为类型、只保留最近15天数据。原始数据里的时间戳很多是秒级Unix时间戳要转成datetime再提取“小时”和“星期几”特征。数据清洗脚本用pandas即可import pandas as pd df pd.read_csv(user_behavior.csv) df.columns [user_id, product_id, category_id, behavior_type, timestamp] # 行为类型映射pv0, fav1, cart2, buy3 behavior_map {pv: 0, fav: 1, cart: 2, buy: 3} df[behavior_code] df[behavior_type].map(behavior_map) df[time] pd.to_datetime(df[timestamp], units) df[hour] df[time].dt.hour df[weekday] df[time].dt.weekday # 过滤过期数据只保留最近15天 cutoff df[time].max() - pd.Timedelta(days15) df df[df[time] cutoff] # 按用户抽样保证训练集不超过10万用户 selected_users df[user_id].drop_duplicates().sample(n100000, random_state42) df df[df[user_id].isin(selected_users)]到这里原始日志已经变成一张干净的行为流水表。再按用户聚合出统计特征和序列特征最终生成训练集。训练集里每一行是一个用户列是“统计特征列”和“行为序列列、标签列”保存成csv。5.3 模型训练与保存训练脚本我会单独放一个train_lstm.py和Django项目放在同一个仓库里但不用Django启动。这样调试模型时不用每次启动整个网站更快。训练时用EarlyStopping和ModelCheckpoint只保留验证集AUC最好的模型。from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint callbacks [ EarlyStopping(monitorval_auc, patience3, modemax, restore_best_weightsTrue), ModelCheckpoint(ml_models/best_model.keras, monitorval_auc, save_best_onlyTrue, modemax) ] model.fit( [X_train_seq, X_train_feat], y_train, validation_data([X_valid_seq, X_valid_feat], y_valid), epochs15, batch_size1024, callbackscallbacks )一个比较实用的经验batch_size根据显存调没有GPU就用CPU跑batch_size设小一点512或1024都可以。整个15轮训练在普通笔记本电脑上大概十几分钟完全可以接受。5.4 Django接口与可视化页面实现模型训练完成后我写一个预测视图放在behavior/views.py里from django.http import JsonResponse from .services import get_or_build_features, get_model def predict(request, user_id): feature get_or_build_features(user_id) if feature is None: return JsonResponse({error: user not found}, status404) seq feature[sequence] stat feature[stat] prob get_model().predict([seq, stat])[0][0] return JsonResponse({user_id: user_id, buy_probability: round(float(prob), 4)})核心是get_or_build_features函数它必须和训练时的特征处理完全一致差一步都会导致预测结果漂移。我踩过的一个坑是训练时把行为序列向左补齐到长度20但预测接口忘补了等于序列里全是0模型预测毫无区分度。建议把特征构建逻辑抽成公共函数训练和预测都调用同一个函数。可视化页面我用Django模板实现。dashboard/views.py里写一个index视图把图表需要的数据聚合成字典返回模板。模板中引入ECharts的js文件后按官方文档初始化即可。6. 常见问题与排查技巧实录6.1 高频问题速查表整理一份我在调试过程中遇到的高频问题按“现象—原因—解法”列出基本能覆盖大部分同学会踩的坑现象原因解决方法Django页面加载CSS/JS全部失效控制台404没有配置静态文件路径或忘加{% load static %}在settings.py中设置STATICFILES_DIRS模板中加入{% load static %}使用{% static xxx.css %}引用ECharts图表不渲染页面空白传给option的变量不是合法JSONDjango转义了引号在模板变量后加模型预测AUC很高但线上效果差数据切分方式有问题随机切分导致数据泄露改用按时间切分不使用未来数据构造特征LSTM训练loss不降学习率太高或特征未归一化把统计特征做标准化学习率降到0.001以内Django加载模型后内存暴涨每次请求都调用load_model用lru_cache缓存模型对象进程内只加载一次预测接口返回结果全是同一个值特征处理流程和训练流程不一致检查序列补齐方向、缺失值填充方式保证公共特征函数唯一6.2 我自己的调试心得最后分享几个不带在代码注释里的体会。第一个是关于Django执行查询和删除对象的习惯。很多人写Behavior.objects.filter(user_idxxx).delete()之前不知道这个delete会返回一个元组调试时以为删完就完事结果后面统计数量还是老数据后来才发现是缓存或没刷新。ORM删除、更新操作一定要看返回值这是排查很多“奇怪行为”的第一步。第二个心得是WebSocket如果实在调不出来不要死磕。毕设核心是深度学习模型和可视化实时推送属于锦上添花。我后来把推送功能砍成了轮询页面照样能用但我在文档里写了WebSocket的完整实现思路和代码片段答辩时依然能证明我理解了这项技术。第三个体会是珍惜自己的调试记录。做这个项目时我养成一个习惯每修一个bug就写一段“现象原因处理方式”的笔记后来整理成了一份问题排查文档写进毕设文档里很加分。这些记录不只是给别人看的也是自己复盘项目、准备答辩提问的最好素材。这个系统做完再回头看最值钱的不是那几份源码而是你在踩坑过程中建立起来的“数据-模型-系统”全链路直觉。
返回列表