简介:本资源为基于机器学习的商品评论情感分析毕业设计完整项目包,面向计算机、人工智能及数据科学相关专业的学生与自学者,帮助解决从文本预处理到模型部署的全流程实践问题。包内共43个文件,以14个Python脚本、7个CSV数据集、4个NumPy数组、3个PKL模型文件及2个H5权重文件为主,另含XML配置、Excel语料与YML参数文件,压缩包约66.66MB,覆盖数据清洗、分词、词向量训练、SVM与LSTM建模、GUI界面及爬虫模块。项目完整呈现词袋、TF-IDF、Word2Vec等特征提取方法,以及朴素贝叶斯、SVM、LSTM、BERT等模型的训练、调参与评估流程,并配有混淆矩阵、ROC曲线等可视化脚本。目前已有166人学习,适合需要完整赛题方案、可运行代码与排错思路的读者参考复用。
1. 从一份评论数据到能跑通的情感分类器:这套毕设资源到底交付了什么
电商后台每天沉淀几万条评论,人工翻十条就眼花,更别提按好评率做选品决策。这套「基于机器学习的商品评论情感分析」毕业设计项目,解决的就是把中文评论自动判成正面或负面这件事。它适合三类人:正在找计算机、软件工程、大数据方向毕设选题的学生;需要一份能改能跑的课程设计参考的在校生;以及想快速搭一个文本分类 demo 验证思路的初级工程师。资源本身是一套完整工程,覆盖数据读取、中文分词、特征提取、模型训练、评估到可视化展示的链路,不是只丢一个算法文件让你自己拼。拿到手先别急着改代码,先确认它跑得起来、结果可信,再谈二次开发。下面按「它是什么、怎么跑、坑在哪、怎么改」的顺序拆开讲。
2. 拆开工程看结构:数据、分词、特征、模型四层怎么串起来
2.1 先认清目录与依赖,别一上来就 pip install
拿到压缩包解压后,常见做法是先扫一遍目录再动手。这类毕设工程通常长这样:data/放原始评论语料,src/或根目录放训练脚本,model/存训练好的模型文件,static/和templates/是可视化页面,requirements.txt锁依赖。先看requirements.txt里有没有版本号,没有版本号的包是第一个雷——scikit-learn、jieba、pandas这几个跨版本 API 变动不小。
# 建议先建独立环境,别污染系统 Python python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate # 再装依赖,装之前先看 requirements 内容 pip install -r requirements.txt逻辑说明:虚拟环境是为了隔离依赖,毕设工程经常锁老版本sklearn,和你机器上已有的新版冲突。参数说明:如果requirements.txt里写的是scikit-learn(不带版本),装完大概率是最新版,部分老代码里的sklearn.cross_validation会直接报ModuleNotFoundError,这时要么降版本,要么改代码。装完先跑一次python -c "import sklearn, jieba, pandas; print(sklearn.__version__)"确认导入无误,再往下走。
2.2 中文分词与停用词:情感分析的第一道分水岭
中文和英文不一样,英文按空格切词就行,中文必须先分词。这套工程里jieba基本是标配。分词质量直接决定后面特征的好坏,很多人跑出来准确率上不去,问题就出在这一步。
import jieba import re # 加载停用词表,工程里一般在 data/stopwords.txt def load_stopwords(path): with open(path, 'r', encoding='utf-8') as f: return set(line.strip() for line in f) stopwords = load_stopwords('data/stopwords.txt') def clean_and_cut(text): # 去掉非中文、非数字字符,评论里常混表情和链接 text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', '', text) words = jieba.lcut(text) # 过滤停用词和单字,单字对情感判断贡献很小 return [w for w in words if w not in stopwords and len(w) > 1]逻辑说明:先正则清洗,把表情、URL、特殊符号去掉,这些噪声会干扰分词。再用jieba.lcut精确模式切词,最后过滤停用词和长度为 1 的字。参数说明:len(w) > 1这个阈值可以调,如果你做的是短文本舆情分析,单字有时也带情感(比如「差」),可以放宽到>= 1,但会引入更多噪声。停用词表建议自己补几个电商高频词,比如「包邮」「物流」「客服」,这些词本身不带情感倾向,留着反而稀释特征。
2.3 特征提取:TF-IDF 和词袋怎么选
分词完要把文本变成模型能吃的数字。这套工程大概率用的是 TF-IDF 或词袋(CountVectorizer)。两者区别在于:词袋只看词频,TF-IDF 会惩罚高频但无区分度的词。
from sklearn.feature_extraction.text import TfidfVectorizer # 假设 corpus 是分词后用空格拼接的字符串列表 vectorizer = TfidfVectorizer( max_features=5000, # 只保留权重最高的 5000 个词 ngram_range=(1, 2), # 同时考虑单字词和双字词组合 min_df=2, # 至少出现在 2 篇文档里才保留 max_df=0.8 # 出现在超过 80% 文档里的词丢掉 ) X = vectorizer.fit_transform(corpus)逻辑说明:max_features控制特征维度,太大容易过拟合且训练慢,太小会丢信息,5000 是这类毕设的常见起点。ngram_range=(1,2)让「不」「好」和「不好」都能被捕捉,对情感分析很关键。min_df和max_df是过滤噪声词和通用词的手段。参数说明:如果你的语料只有几千条,max_features可以降到 2000~3000;语料上万条再往上加。改完参数记得重新fit_transform,不能复用旧的 vectorizer。
2.4 模型训练与评估:别只看准确率
工程里通常会用朴素贝叶斯、SVM 或逻辑回归做基线。朴素贝叶斯在文本分类上快且稳,SVM 在小样本上表现好,逻辑回归可解释性强。
from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import classification_report X_train, X_test, y_train, y_test = train_test_split( X, labels, test_size=0.2, random_state=42, stratify=labels ) model = MultinomialNB() model.fit(X_train, y_train) pred = model.predict(X_test) print(classification_report(y_test, pred, target_names=['负面', '正面']))逻辑说明:stratify=labels保证训练集和测试集里正负样本比例一致,评论数据经常正负不均衡,不加这个参数评估结果会失真。classification_report会输出精确率、召回率和 F1,比单看准确率靠谱得多。参数说明:test_size=0.2是常规切分,数据量小于 1000 条时建议用交叉验证代替单次切分。如果正负样本差得离谱(比如 9:1),要在模型里加class_weight='balanced',否则模型会倾向于全预测成多数类。
3. 从零跑通全流程:环境、训练、可视化三步落地
3.1 环境搭建与数据检查
跑通的第一步不是敲训练命令,而是确认数据格式。打开data/下的语料文件,看是 CSV 还是 TXT,列名是什么,标签是 0/1 还是「正面/负面」。
import pandas as pd # 常见格式:两列,一列评论一列标签 df = pd.read_csv('data/comments.csv', encoding='utf-8') print(df.head()) print(df['label'].value_counts()) # 看正负样本分布 print(df.isnull().sum()) # 看有没有空值逻辑说明:value_counts()让你一眼看出样本是否均衡,isnull().sum()排查缺失值。参数说明:encoding常见有utf-8和gbk,中文 CSV 用 Excel 打开过再保存经常变成gbk,读出来乱码就换编码试。如果标签是文字,训练前要映射成数字,df['label'] = df['label'].map({'正面': 1, '负面': 0})。
3.2 训练脚本执行与模型保存
数据没问题后,直接跑训练脚本。多数工程会有一个train.py或main.py。
# 常见入口,具体看工程里的 README 或文件名 python train.py # 如果工程用 Flask 做展示,训练完再启动服务 python app.py逻辑说明:训练脚本一般会完成分词、向量化、训练、评估、保存模型这一串动作。跑完检查model/目录下有没有生成.pkl或.joblib文件,没有的话说明保存逻辑没执行或路径写错。参数说明:有些工程把超参数写在脚本顶部的常量里,比如MAX_FEATURES = 5000,改完直接重跑即可,不用动函数内部。
import joblib # 保存模型和向量器,预测时必须成对使用 joblib.dump(model, 'model/sentiment_model.pkl') joblib.dump(vectorizer, 'model/tfidf_vectorizer.pkl')逻辑说明:模型和向量器必须一起保存,预测时先用同一个向量器转换新文本,再喂给模型,否则特征对不上,结果全是错的。这是新手最容易翻车的地方之一。
3.3 可视化页面与预测接口
如果工程带 Flask 或 Django 页面,启动后浏览器访问本地端口就能输入评论看预测结果。核心预测逻辑通常长这样:
def predict_sentiment(text): words = clean_and_cut(text) vec = vectorizer.transform([' '.join(words)]) label = model.predict(vec)[0] prob = model.predict_proba(vec)[0] return '正面' if label == 1 else '负面', max(prob)逻辑说明:注意这里用的是transform而不是fit_transform,预测阶段绝不能重新拟合向量器。predict_proba给出置信度,方便你在页面上显示「正面 87%」这种更直观的结果。参数说明:如果输入文本分词后为空(比如全是符号),transform会得到一个全零向量,模型可能给出随机结果,实际部署时要加个兜底判断。
4. 避坑与排查:这几处不处理,跑十遍也白搭
4.1 现象:准确率异常高或异常低
原因:数据泄漏或标签错位。常见情况是先把全量数据做了 TF-IDF 再切分训练测试集,测试集信息泄漏到训练里,准确率虚高到 99%。或者标签列和评论列读反了,模型在学无关特征。 解决:严格先切分再fit_transform,训练集fit,测试集只transform。读数据后打印前几行肉眼确认列对应关系。
4.2 现象:中文全部乱码
原因:文件编码不一致。Windows 下用 Excel 编辑过的 CSV 默认gbk,代码里写utf-8就读出乱码。 解决:读文件时显式指定编码,或用chardet检测。统一把语料转成utf-8再入库,一劳永逸。
4.3 现象:ModuleNotFoundError 或 API 报错
原因:依赖版本不匹配。老工程用sklearn.cross_validation,新版已移除;jieba某些版本lcut行为有差异。 解决:按requirements.txt装指定版本,没有版本号就查工程里 import 的写法反推版本。实在找不到就改代码适配新版 API,比如cross_validation换成model_selection。
4.4 现象:预测结果全是同一类
原因:样本极度不均衡,或向量器与模型不匹配。前者模型学会了「全猜多数类」就能拿高准确率,后者是预测时用了新的向量器。 解决:检查value_counts(),不均衡就加class_weight='balanced'或做重采样。确认预测时加载的是训练时保存的同一个向量器文件。
4.5 现象:Flask 页面启动报端口占用
原因:5000 端口被系统或其他程序占用,macOS 上尤其常见。 解决:换端口启动,app.run(port=5001),或先查占用进程再决定是否结束。
5. 二次开发与效果验证:把毕设改成能写进简历的项目
跑通只是起点,真正让这份资源有价值的是你能改出什么。我一般会先做一轮基线验证,确认原始工程的 F1 在什么水平,再动手改。验证方法很简单:固定随机种子,跑三次训练,看classification_report的 F1 波动大不大。波动超过 3 个点,说明数据切分或样本量有问题,先解决稳定性再谈优化。
优化方向上,最划算的是换模型。把朴素贝叶斯换成LinearSVC或LogisticRegression,通常能涨 2~5 个点,代码改动不超过五行。再进一步可以上sklearn的Pipeline把分词、向量化、分类串成一条流水线,避免手动管理向量器的坑。
from sklearn.pipeline import Pipeline from sklearn.linear_model import LogisticRegression pipe = Pipeline([ ('tfidf', TfidfVectorizer(max_features=5000, ngram_range=(1, 2))), ('clf', LogisticRegression(class_weight='balanced', max_iter=1000)) ]) pipe.fit(X_train_text, y_train) # 直接喂原始文本,不用手动分词逻辑说明:Pipeline把预处理和模型绑在一起,fit和predict都走同一条路径,彻底杜绝向量器不匹配的问题。参数说明:max_iter=1000是逻辑回归的迭代上限,默认 100 经常不收敛报警告,调大即可。class_weight='balanced'处理不均衡样本。
如果想再上一个台阶,可以引入snownlp或SnowNLP做对比基线,或者用word2vec预训练词向量替代 TF-IDF。但要注意,毕设答辩看的是你能否讲清每一步为什么这么做,而不是模型多花哨。我见过太多人堆了一堆模型,被问「为什么用这个」就卡壳。从那以后我每次改模型前都强制自己写一句「换它的理由是___,预期提升___,验证方式是___」,写不出来就不改。希望这份资源能帮你把毕设稳稳落地,也希望你改完之后,能对着代码把每一行的来龙去脉讲清楚。
本文还有配套的精品资源,点击获取