Django+机器学习:电商评论情感分析毕设全解析
每年到这个节点我总会碰到几波咨询毕设的其中基于django机器学习的电商评论情感分析绝对是出现频率最高的题目之一。标题挂着源码文档远程调试全包定制的要么是代做广告要么是二手倒卖但这类题目本身的技术含量和完成度其实被很多人低估了。今天我不聊代做那点事就把它当做一个正经的工程技术项目来拆一遍题目背后的核心难点在哪、技术栈为什么这么搭、从数据到模型再到网页的完整链路怎么走、以及那些你只有真正动手才会踩到的坑。这个题目本质上是一个文本分类 Web 展示的全栈项目适合计算机、大数据、电子商务、信息管理等相关专业的毕业设计也适合想入门 NLP 应用开发的初学者参考。它既不需要搞多前沿的算法也不用烧钱租显卡一台普通笔记本就能完整跑通但对工程整合能力的要求相当全面数据处理、模型训练、后端接口、前端展示、论文撰写一条龙。下面我从头到尾把这条链路捋一遍。1. 题目拆解一个情感分析毕设的真实工作量1.1 情感分析到底解决什么问题情感分析Sentiment Analysis学术上叫意见挖掘本质上是让机器判断一段文本传递的情绪倾向。放到电商场景里具体任务就是从用户评论中判断这个评论是好评、差评还是中性更细一点还能分析出用户具体在夸哪个方面物流快、质量好、服务差或者吐槽哪个点尺寸不符、客服敷衍。很多同学一看题目就慌了觉得NLP 机器学习门槛很高。实际上单论电商评论情感分析这个场景它已经被研究得很透属于文本分类里最经典、最容易落地的一类问题。你不需要做生成式模型不需要搞大模型微调核心就是一句话把评论文本变成向量然后喂给一个分类器让分类器输出正面/负面的标签。就这么简单。1.2 电商评论场景的特殊性电商评论跟新闻文本、社交文本相比有几个明显特点直接决定了你的技术选型口语化严重东西不错就是有点小贵物流贼快也就那样吧大量省略主语、乱用标点、夹杂表情符号。短文本为主大多数评论就几十个字不像新闻那样有丰富的上下文所以特征很稀疏。正负样本不均衡真实场景里好评天然占比高很多人买到满意的东西懒得评价买到不满意的才疯狂吐槽但总体看好评仍然远多于差评。隐含情感表达这价格还要啥自行车表面看是句调侃实际是好评用了一次就坏了没有直接负面词但明显是差评。这类表达对模型的语义理解能力有要求。这些特点决定了你不能拿一套通用 NLP 流程硬套必须针对中文电商评论做专门的数据清洗和特征处理。1.3 交付物清单源码之外还要有什么凡是认真做过毕设的人都知道老师看的绝不只是能跑。一个完整可交付的情感分析系统至少要包含这几块可运行的 Django 项目源码包含数据预处理脚本、模型训练脚本、Web 应用代码训练好的模型文件.pkl / .h5 之类保证拿到源码能不重新训练直接启动项目文档包括需求分析、系统设计、数据库设计虽然这个项目可能用不到数据库、接口说明毕业论文或设计报告这是大头后面我会专门讲怎么组织一个稳定的演示环境能现场展示单条分析、批量分析、可视化图表这些功能。把这些模块列出来你就会发现这个题目的难点压根不在算法本身而在把算法包装成一个完整系统这件事上。很多同学模型调得飞起最后卡在 Django 部署和前后端联调上那才叫冤枉。2. 技术选型逻辑为什么是 Django 机器学习而不是别的2.1 Django 在这个项目里的真实职责先说 Django。它的定位是 Web 框架负责对外提供页面和接口。为什么毕设选它而不是别的几个很实在的理由Python 生态一致机器学习这边用的 sklearn、TensorFlow、PyTorch 全是 Python 的Django 也是 Python模型文件直接可以joblib.load()/keras.models.load_model()加载完全不用跨语言调用这是最省事的一条路。自带后台和管理界面Django 的 admin 模块免费送一个管理后台可以拿来管理评论样本、查看标注数据演示的时候也是加分项。开发效率高ORM 让你不用写原生 SQL模板系统让你快速搭页面对主要精力在机器学习上的毕设来说非常友好。相比之下Flask 更轻量但很多东西要自己拼FastAPI 虽然后起之秀但很多学校老师没听过答辩容易被质疑选型理由。Django 是大而全的稳妥牌就业市场上 Python Web 岗位提到 Django 的概率也高选它从答辩和工作两个角度都说得过去。2.2 机器学习算法的选型路线算法部分要分两层看传统机器学习层和深度学习层。毕设做到什么程度取决于你想拿什么档次的成绩。传统机器学习朴素贝叶斯MultinomialNB、逻辑回归、线性 SVM、随机森林。这几个是文本分类的经典基线模型训练快、解释性强论文里可以画很多对比分析的图。深度学习方法TextCNN、LSTM、BiLSTM。这些模型能捕捉词序和上下文信息对这价格还要啥自行车这类句子效果明显更好但训练时间和调参难度也上来。预训练模型进阶项BERT 及各种中文预训练模型如中文 RoBERTa、ERNIE效果确实好但显存占用大、推理慢普通毕设不一定有必要。我建议最多作为改进方向写进论文的展望不要当作主方案否则光是环境配置就够你喝一壶。核心选型建议主方案做TF-IDF 机器学习和Word2Vec 深度学习两套对比既覆盖了基础要求又体现工作量答辩时数字也漂亮。2.3 系统分层与数据流转整个系统从架构上分四层理解了这个分层后面做起来思路就非常清晰数据层评论数据集 → 清洗/标注 → 训练集/测试集 模型层文本向量化 → 分类模型 → 评估/调优 → 模型持久化 应用层Django 视图 → 加载模型 → 推理预测 → 返回结果 展示层单条输入框 → 批量分析 → 图表可视化数据从原始爬虫文件或公开数据集进来经过预处理变成干净的训练语料训练出的模型通过 pickle/joblib 保存成文件Django 启动时加载模型用户在前端输入评论请求打到视图函数视图调用预处理和模型把预测结果返回给前端渲染。这条链路每环都可以独立测试建议按这个顺序开发不要一上来就写 Django先把模型跑通再说。3. 数据预处理中文评论比英文难在哪里3.1 数据集的选择与标注策略数据是情感分析项目的命根子。公开的电商评论数据集可以找到不少但来源和质量参差不齐。毕设场景下我建议用以下几种来源组合公开的某平台商品评论数据集通常包含评论文本和评分自己写爬虫抓取如果敢用爬虫要注意遵守网站协议仅作学术用途中文情感语料库或者开源的中文酒店/购物评论数据。数据规模上二分类正/负至少准备 1 万条以上最好能到 3~5 万条。太少模型容易欠拟合太多你预处理和训练的时间也受不了。如果原始数据带评分可以直接用评分做弱标注4~5 星算正面1~2 星算负面3 星可以扔掉或单独归为中性。这是学术论文里常见的做法省去了大量人工标注时间但要在论文里说明清楚因为评分和真实情感并不完全一致有人给 3 星却写了段好评。3.2 分词、停用词与传统特征中文文本和英文最大的区别是没有天然的空格分词所以分词是中文 NLP 的第一道工序。主流方案是 jieba也考虑用 jieba 的全模式和搜索引擎模式做对比实验。核心代码很简单import jieba text 这个手机续航不错就是屏幕有点暗整体性价比很高 seg_list jieba.cut(text, cut_allFalse) print( | .join(seg_list)) # 这个 | 手机 | 续航 | 不错 | | 就是 | 屏幕 | 有点 | 暗 | | 整体 | 性价比 | 很高分词之后是清洗和去停用词去除网址、 用户、纯数字、无意义符号去停用词的了就也这类高频但无信息的词需要用一份中文停用词表去重同一用户对同一商品的重复评论、完全相同的刷单评论否则会污染训练集可选繁体转简体、表情符号替换成情感词比如哈哈哈哈转为开心。传统机器学习里最经典的特征就是 TF-IDF。它的思路是一个词在文档中出现次数多TF 高、但在整个语料中出现得少IDF 高那它就对这篇文档有很强的区分度。比如差评退款这类词在差评里密集出现但总体少见TF-IDF 会给它很高权重from sklearn.feature_extraction.text import TfidfVectorizer vectorizer TfidfVectorizer(max_features5000, ngram_range(1, 2)) X_train vectorizer.fit_transform(train_texts) X_test vectorizer.transform(test_texts)注意这里fit_transform和transform的区别一定要只用训练集 fit测试集只能 transform否则会造成信息泄露测试集数据提前见到了词表评估结果虚高。这个细节毕业论文里可以单独写老师会觉得你真懂。3.3 词向量与序列化表示传统 TF-IDF 是离散的、稀疏的表示无法体现词与词之间的语义关系。深度模型一般用的是稠密词向量先通过 Word2Vec 或 GloVe 把每个词映射到固定维度的向量空间语义相近的词在向量空间里距离更近。比如好评和点赞的向量就很接近。用 gensim 训练词向量或者直接加载开源的中文词向量from gensim.models import Word2Vec # 语料是分词后的句子列表每句是一个词列表 sentences [jieba.lcut(s) for s in train_texts] model Word2Vec(sentences, vector_size100, window5, min_count2, sg1) model.save(word2vec.model)然后把每条评论映射成词向量序列再 padding 到固定长度比如 128 个词超过截断、不足补零。这步做完数据才能喂给 LSTM 或 TextCNN。4. 模型训练与外评估从跑通到能答辩4.1 先跑传统机器学习模型做基线我强烈建议所有做这个题目的同学先跑传统机器学习模型而不是直接上深度学习。原因有三一是速度快一分钟内出结果方便快速验证数据管道有没有问题二是结果稳定不依赖随机种子三是论文有对比素材。以 TF-IDF 特征为例把数据 8:2 切分然后分别跑逻辑回归、朴素贝叶斯、线性 SVMfrom sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.naive_bayes import MultinomialNB from sklearn.svm import LinearSVC from sklearn.metrics import accuracy_score, f1_score X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) models { LogisticRegression: LogisticRegression(max_iter1000), MultinomialNB: MultinomialNB(), LinearSVC: LinearSVC() } for name, model in models.items(): model.fit(X_train, y_train) pred model.predict(X_test) print(f{name}: 准确率 {accuracy_score(y_test, pred):.4f}, fF1 {f1_score(y_test, pred):.4f})实际跑出来的典型结果是线性 SVM 通常略优于逻辑回归朴素贝叶斯在某些数据集上也相当能打。这个阶段不用追求极致准确率重点是得到一组可比对的基线数值比如准确率 0.85~0.90 左右就很正常。4.2 再接 LSTM 或 TextCNN传统模型的瓶颈在于忽略词序。比如不是不好和不好语义完全相反但如果只看词的权重很容易搞混。这时就需要深度学习模型。TextCNN 的原理很直观把评论看成一维的信号用多个不同尺寸的卷积核去扫提取局部 n-gram 特征再接池化层和全连接层。它实现简单、训练快是文本分类性价比最高的深度模型之一。LSTM 则是按顺序读词能记住前面出现过的重要信息适合处理虽然……但是……这种句式。用 Keras / TensorFlow 实现一个简单的 TextCNNfrom tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense, Dropout model Sequential([ Embedding(vocab_size, 128, input_lengthmax_len), Conv1D(128, 5, activationrelu), GlobalMaxPooling1D(), Dense(64, activationrelu), Dropout(0.5), Dense(1, activationsigmoid) ]) model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy]) model.fit(X_pad_train, y_train, epochs10, batch_size64, validation_split0.1)注意几个会让结果难看的坑Embedding 层如果随机初始化而不加载预训练词向量需要更多训练轮次才能收敛Dropout 不要加太大0.3~0.5 即可epochs 建议配合早停EarlyStopping防止过拟合因为毕设数据量不大过拟合非常容易发生。4.3 评测指标、混淆矩阵与结果对比很多毕设论文写模型准确率达到 90%然后就没了。这其实是不够的。二分类问题必须看一组指标准确率、精确率、召回率、F1 值、混淆矩阵。举个例子如果 100 条评论里 90 条好评、10 条差评模型无脑全预测为好评准确率都有 90%。但这明显是一个废物模型。所以一定要看差评这一类的召回率——有多少差评被你漏掉了。用混淆矩阵可以看出模型到底在哪个类别上犯错from sklearn.metrics import confusion_matrix, classification_report print(classification_report(y_test, pred, target_names[负面, 正面])) print(confusion_matrix(y_test, pred))论文里建议同时放三张表传统模型对比表、深度模型对比表、以及优劣错误案例分析表。案例分析尤其加分——找几个预测错误的评论分析为什么错比如遇到反讽句式无法理解缺少领域词典等这体现了你的思考深度。5. Django 集成把模型装进网页的完整链路5.1 模型持久化与加载策略训练完模型的最终归宿不是 jupyter 而是文件。传统机器学习模型用 joblib 保存比 pickle 在 numpy 数组上的效率更高import joblib joblib.dump(vectorizer, models/tfidf_vectorizer.pkl) joblib.dump(model, models/sentiment_model.pkl)深度学习模型用model.save(models/textcnn_model.h5)同时也要保存分词器和词表否则部署时没法对用户输入做同样处理。这里我踩过一个坑光保存模型不行预处理管线必须和模型一起保存。比如 TF-IDF 的vocabulary_、分词用的词典、padding 用的max_len这些都要持久化否则新来的文本无法转成和训练时一致的表示。Django 端加载模型要注意时机。最忌讳在每个请求里都load_model()模型加载一次要好几秒用户点一下等五秒演示直接翻车。正确做法是模块加载时只执行一次用全局变量保存# sentiment_service.py import joblib _vectorizer None _model None def get_model(): global _vectorizer, _model if _model is None: _vectorizer joblib.load(models/tfidf_vectorizer.pkl) _model joblib.load(models/sentiment_model.pkl) return _vectorizer, _modelDjango 的开发服务器是单进程多线程的模块级全局变量在开发阶段完全够用。如果将来要上生产就再考虑 Redis 缓存或者独立推理服务但毕设不需要。5.2 单条分析接口与批量分析有了服务模块视图层就很薄了。设计两个核心功能单条分析和批量分析。单条分析是一个简单的 POST 接口前端输入框传入评论文本后端做分词、向量化、预测返回情感标签和置信度# views.py from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .sentiment_service import get_model import jieba csrf_exempt def analyze_one(request): if request.method POST: text request.POST.get(text, ) if not text.strip(): return JsonResponse({error: 评论不能为空}, status400) vec, model get_model() # 这里要做和训练时完全一样的预处理 text_seg .join(jieba.cut(text)) x vec.transform([text_seg]) pred model.predict(x)[0] proba model.predict_proba(x)[0].tolist() label 正面 if pred 1 else 负面 return JsonResponse({label: label, proba: proba, text: text}) return JsonResponse({error: 仅支持POST请求}, status405)批量分析则是用户上传一个 CSV 文件后端逐行预测然后汇总统计并让用户下载结果文件。这个功能演示效果好因为能直观展示模型的批量处理能力数据量可以搞个几千条几秒钟处理完视觉效果很震撼。5.3 前端展示与可视化前端不求花哨但要有几个关键元素一个大的输入框、一个分析按钮、结果区域情感标签置信度标签颜色。再加一个批量分析的上传表单区域和结果下载按钮。可视化是让毕设显得完整的重要一步。用 ECharts 或 Chart.js 画三个图情感占比饼图正面多少、负面多少、不同类别评论数量的柱状图、以及 API 响应时间的折线图可选。这些图表的数据可以从批量分析的结果中统计出来也可以从历史分析记录中读取。Django 模板里嵌入 ECharts 很简单引入 CDN然后在 JavaScript 里填数据script srchttps://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js/script div idpieChart stylewidth: 100%; height: 400px;/div script const chart echarts.init(document.getElementById(pieChart)); chart.setOption({ series: [{ type: pie, data: [ { name: 正面, value: {{ positive_count }} }, { name: 负面, value: {{ negative_count }} } ] }] }); /script关于静态资源我建议把 ECharts 文件下载到本地放在static目录下。为什么因为答辩现场经常没网CDN 加载不出来当场尴尬本地文件最保险。所有外部依赖都尽量本地化这是演示稳定性的第一原则。5.4 项目文件结构与路由设计一个标准的 Django 项目结构大概长这样sentiment_project/ ├── manage.py ├── sentiment_app/ # 核心应用 │ ├── views.py # 视图函数 │ ├── urls.py # 路由 │ ├── sentiment_service.py # 模型加载与推理 │ ├── models.py # 可能用的数据模型可选 │ ├── templates/ │ │ └── sentiment_app/ │ │ ├── index.html │ │ └── batch.html │ └── static/ │ ├── css/ │ ├── js/ │ └── echarts/ ├── models/ # 训练好的模型文件 │ ├── tfidf_vectorizer.pkl │ ├── sentiment_model.pkl │ └── textcnn_model.h5 ├── scripts/ # 数据预处理与模型训练脚本 │ ├── preprocess.py │ ├── train_traditional.py │ └── train_deep.py └── data/ # 数据集 ├── raw/ └── processed/这个结构清晰、职责分明写进论文架构图里也好看。路由就两个核心页面加两个接口不需要搞复杂。6. 毕设实战踩坑记录这些问题我基本都遇到过6.1 中文编码到处报错做中文 NLP 项目编码问题是第一个拦路虎。Windows 下默认编码经常是 GBK而 Django 和大多数数据处理库默认 UTF-8。常见的报错就是UnicodeDecodeError: gbk codec cant decode byte。解决方案是全项目统一 UTF-8。所有代码文件头部声明编码所有文件读取显式指定encodingutf-8CSV 文件读取时加encodingutf-8-sig带 BOM 时用这个。另外在settings.py里设置LANGUAGE_CODE zh-hans和TIME_ZONE Asia/Shanghai否则 Django 后台会报一些本地化的小问题。6.2 pickle 版本与跨环境加载问题模型文件从你训练电脑搬到另一台电脑或者服务器最容易翻车的是版本不一致。sklearn 的模型文件在版本跳跃大的时候比如 0.24 到 1.2可能加载失败报ModuleNotFoundError: No module named sklearn...或者ValueError: pickle protocol。如果对方环境没法强制匹配版本有两条路一是用 joblib 加compress3保存并在文档里写清楚依赖版本二是提供一份requirements.txt锁定所有关键包版本。我见过太多人远程调试时因为环境不一致把两三个小时耗在装包上。交付的时候一定要把环境依赖清单列全最好精确到版本号。6.3 样本不均衡导致的假高分前面说过好评天然比差评多。如果直接用原始分布训练模型会倾向把所有样本预测为多数类。除了看混淆矩阵之外处理手段有几种欠采样随机删掉部分好评、过采样差评做 SMOTE 或简单复制、或者给少数类加大惩罚权重sklearn 的class_weightbalanced。从论文角度我建议把数据不均衡问题及处理方案写成独立小节。老师看到你主动发现并处理了数据分布问题比看到 0.99 的准确率更靠谱。6.4 DataFrame 在 Django 里的不可序列化问题批量分析时很多人习惯用 pandas 处理结果最后return JsonResponse(result_df)直接报错因为 DataFrame 不能被 JSON 序列化。正确做法是先转成records格式或者列表records result_df.to_dict(orientrecords) return JsonResponse({data: records, total: len(records)})还有个类似问题numpy 的np.int64类型 JSON 也序列化不了。预测结果的标签如果是 numpy 类型记得先int()或者float()强制转换。这些小坑单独看都不大但串联起来会消耗大量调试时间。6.5 模型推理速度过慢如果深度模型没有 GPU一个长评论预测可能要 100 毫秒以上前端如果同步等待会导致页面卡顿几十秒。解决方案一是限制输入长度截断到 128 或 256 词二是用异步请求AJAX loading 动画先让用户感知在处理中而不是页面没反应。答辩演示最怕冷场。我建议把模型预热做一遍服务启动时先拿几条测试数据跑一次把模型加载和编译的耗时消化在后台再用浏览器访问就流畅多了。7. 文档、演示与答辩准备让工作量看得见7.1 毕业论文结构怎么搭这个题目写论文结构基本可以按下面这个骨架走既符合软件工程流程又贴合 AI 类课题绪论背景、国内外研究现状、主要工作与论文结构相关技术介绍Django 框架、机器学习基础、中文文本处理技术系统需求分析功能性需求单条分析、批量分析、可视化与非功能需求响应时间、准确率系统设计总体架构、模块划分、数据集构建与标注策略、模型选型方案系统实现数据预处理的代码逻辑、模型训练过程与参数设置、Django 页面与接口实现实验与结果分析实验环境、评价指标、模型对比、错误案例分析与改进方向总结与展望。其中第 6 章是精华老师说工作量都体现在实验章节不是开玩笑的。多放图表数据分布图、词云图、混淆矩阵热力图、模型对比柱状图。7.2 演示 Demo 的固定流程演示不能临场发挥建议固定为一条路径打开系统主页说明技术栈和页面功能输入一条明显的正面评论比如物流很快包装严实客服态度也很好看结果输入一条中性带隐含情感的评论比如价格便宜但质量一般般看模型怎么判断然后进入批量分析上传测试 CSV展示统计图和下载结果最后切到后台管理页面展示评论样本管理功能。整个过程控制在 5 分钟以内重点突出数据和模型的可视化部分。提前在本地起好服务关闭无关弹窗断开外部依赖本地 echarts 就是为此准备的。7.3 答辩时容易被追问的点老师对这个题目的提问基本集中在几个地方提前准备好答案就不慌为什么选这个模型你和别的模型比较过吗——准备一张对比表说清楚每个模型的准确率、F1 和优缺点。你的结果准确率 90%误差主要来自哪里——准备三五个预测错误的例子分析反讽、缺主语、领域新词等原因。这个系统如果上线有什么不足——答数据覆盖面不够、实时性一般、对反讽和方言识别弱未来可以引入预训练模型、扩大数据规模。你的特征是怎么提取的——把 TF-IDF 原理和 Word2Vec 原理用简单的话讲清楚别背公式用例子说明。8. 结语与最后几点建议文章写到这里技术链路基本走完了。最后分享几点我做这类项目最深的感受第一这个题目最大的价值不是算法本身而是让你完整走一遍数据 → 模型 → 系统 → 文档的工程流程这种全链路的经验在面试时会成为非常扎实的项目故事。第二不要迷信全包定制哪怕是买来的源码你也要把每一行代码的原理搞懂不然答辩老师几个追问就能看出破绽到时候比没做还被动。第三真实的数据比花哨的模型更能打动老师把数据清洗、分布分析、错误案例做扎实比堆一堆大词要强得多。如果你正在做这个题目建议从数据预处理脚本开始写起先跑通一条最简单的朴素贝叶斯全流程再逐步替换为深度模型和完善 Django 页面。路是一步一步走出来的等你在浏览器里看到自己训练的模型实时给出一条评论的正面/负面判断时那种成就感是代做和抄袭永远给不了的。