简介:这是一份面向计算机相关专业学生和开发者的酒店评论情感分析系统项目,可用于毕业设计或课程作业。项目基于机器学习与自然语言处理技术,内置Flask Web应用程序,用户输入评论文本即可获得情感预测结果,同时提供了逻辑回归与XGBoost两种模型供对比选择。资源共11个文件,6.78MB,主要包括4个pkl模型与向量器文件、3个HTML页面模板、1个Python主程序、1个Jupyter笔记本及说明文档。其中Jupyter笔记本完整记录了数据集探索、模型训练和性能评估过程,便于学习者复现实验细节。目前已有179人浏览学习,适合需要上手实践情感分析任务、快速搭建Web演示系统或参考项目架构的读者。下载后按照README指引安装依赖即可运行,通过浏览器与模型交互,操作直观,具备较好的学习与二次开发价值。
1. 需求切入:酒店评论情感分析,这套资源到底解决什么问题
住过酒店的人都有这种经历:翻评论翻到手指发酸,也分不清哪些是真实体验、哪些是情绪发泄。对平台来说,评论数量一多,人工审核和排序就变成黑匣子,光靠打分根本看不出用户真正满意什么。对做毕设的学生来说,这个场景则是一个很标准的自然语言处理入门题:有公开数据集、有可解释的模型、有可交互的界面,做完之后能讲清楚「从文本到预测结果」的整条链路。这套酒店评论情感分析系统,核心就是让用户输入一段评论文本,马上得到正面或负面的预测结果,同时把逻辑回归和 XGBoost 两个模型的选型、训练、对比、部署都落在一个 Flask Web 应用里。
适合的人群有两类。一类是人工智能或计算机科学与技术专业的毕业生,拿它当毕设主体,可以顺着「数据清洗—特征工程—模型训练—Web 封装」这条线写论文;另一类是正在做课程设计的学生,需要一个能跑起来、能演示、能截图进报告的项目。这套资源包已经把模型文件和 Notebook 都训练好了,到手之后不需要从零跑一遍完整训练流程,重点在于理解它的设计逻辑,并且能在答辩时把每个文件的作用讲清楚。
2. 总体设计:Flask 应用与双模型双向量器的四层职责划分
2.1 系统模块拆解:五个文件各管一段
先看资源包里的核心文件,它其实对应了一套很完整的工程结构。app.py 是 Flask 入口脚本,负责启动 Web 服务、加载模型、处理请求;templates 目录下有三个 HTML 模板——index.html 是用户输入评论的主页面,hotel_detail.html 展示单条评论的分析明细,recommendations.html 给出基于情感分数的推荐结果;两个模型文件 logreg_model.pkl 和 xgboost_model.pkl 分别对应逻辑回归和 XGBoost 两套情感预测方案;vectorizer.pkl 和 tfidf_vectorizer.pkl 是两套文本向量化工具,作用是把中文评论文本转换成模型能读的数字矩阵;sentimentAnalysisofHotelReviews.ipynb 记录了从数据探索到模型评估的完整过程。
这个拆法的合理性在于,它把「训练」和「预测」彻底分开了。Notebook 负责离线训练,产出的 pkl 文件只做推理。Web 端永远不碰原始数据集,只用向量器和模型做转换和预测,这样做的好处是启动速度快、代码逻辑简单,而且模型文件可以被替换——想换成别的算法,只要训练新模型导出 pkl,app.py 里的加载路径改一行就行。
2.2 请求处理链路:一段评论文本是如何变成情感标签的
一段用户输入的评论文本,在系统里的流转路径是固定的:先由前端表单提交到 Flask 路由,路由把文本交给向量器做 TF-IDF 或词频向量化,向量化的结果是一个固定维度的稀疏矩阵,这个矩阵喂给已经加载好的模型,模型输出一个 0 到 1 之间的概率值,最后按照 0.5 阈值映射为「正面」或「负面」标签,随概率值一起渲染到结果页面。
这条链路里最容易被忽略的是维度对齐问题。训练时用 vectorizer.pkl 拟合评论语料,得到了一个固定长度的词汇表;预测时也必须用同一个向量器去转换新文本,不能重新 fit,否则特征维度对不上,模型会直接报错。app.py 里加载模型和向量器的顺序也有讲究,我一般会先加载向量器再加载模型,这样如果两个文件有版本兼容问题,能更早暴露出来。
2.3 双模型设计的价值:逻辑回归与 XGBoost 不是重复造轮子
很多人会问:一个情感分析系统,为什么要放两个模型?逻辑回归和 XGBoost 在这里不是简单重复。逻辑回归是线性模型,在 TF-IDF 向量化后的高维稀疏特征上表现稳定,训练快、可解释性强,适合作为基线模型,论文里可以说「以 LR 为基准验证特征工程有效性」。XGBoost 是梯度提升树模型,能捕捉特征之间的非线性关系,在同样特征下往往能拿到略高的准确率,但训练时间和模型体积都更大。两个模型并存的直接价值,是答辩时能拿同一份测试集跑对比实验,用一张表展示两个模型的精确率、召回率和 F1 值,这是很加分的实验设计。
从资源包的命名也能看出来,作者特意保留了 logreg_model.pkl 和 xgboost_model.pkl 两个文件,而不是只留效果最好的那个。Web 应用里没有做模型切换界面,但 app.py 的预测函数里保留了选择模型的参数入口,想看效果对比的话,手动改一行代码就能切换预测引擎。
3. 模型实现:从数据集到两个 pkl 文件的完整训练流程
3.1 Notebook 里的标准步骤:探索、清洗、训练、评估
sentimentAnalysisofHotelReviews.ipynb 是这套系统里最能体现工作量的一份文件。它通常遵循四条主线:读入酒店评论数据集后,先看标签分布和评论文本长度分布,确认是否存在类别不平衡;接着做文本清洗,包括去标点、去停用词、统一小写化等操作,这一步直接影响向量化的质量;然后把数据集按比例拆成训练集和测试集,在训练集上拟合向量器并转换特征,再分别训练逻辑回归和 XGBoost;最后在测试集上输出分类报告和混淆矩阵。
如果你打算把它写进毕设论文,这里有一个很关键的操作细节:向量器必须只在训练集上 fit,然后在训练集和测试集上分别 transform,绝对不能在整个数据集上先 fit 再拆分。否则测试集的信息会泄漏进训练过程,导致评估指标虚高,答辩时被老师问一句「你的测试集是怎么处理的」就可能翻车。
3.2 向量器选型的差异:CountVectorizer 与 TF-IDF 各自的适用场景
资源包里同时出现了 vectorizer.pkl 和 tfidf_vectorizer.pkl。vectorizer.pkl 对应的通常是 CountVectorizer,它统计每个词在文本中出现的次数,简单直观;tfidf_vectorizer.pkl 对应的就是 TF-IDF 向量器,它不仅统计词频,还考虑了词在多少篇文档中出现过,能压低「的」「了」这类高频词的权重,突出真正有区分度的词。
从工程角度讲,逻辑回归对原始词频特性和 TF-IDF 特性都兼容,但 TF-IDF 做逻辑回归的特征时,对「好」「差」「干净」「吵」这类情感词的辨识度更高。XGBoost 这种树模型对稀疏矩阵的处理能力不强,做树模型的特征时,可以仍然用 TF-IDF,也可以对原始词频做二值化处理,看哪组效果更好。资源包保留了两种向量器,用意就是让你分别跑一轮实验,以测试集 F1 为准选最优组合,这个对比过程在论文里非常值钱。
3.3 训练脚本示意:以 LR 为主模型的加载与预测代码
在 app.py 中,预测逻辑一般长这样:
import joblib import numpy as np from flask import Flask, request, render_template app = Flask(__name__) # 加载训练好的模型和向量器 vectorizer = joblib.load('vectorizer.pkl') model = joblib.load('logreg_model.pkl') @app.route('/predict', methods=['POST']) def predict(): review_text = request.form['review'] if not review_text.strip(): return render_template('index.html', error='评论内容不能为空') # 向量器负责将文本转为模型输入格式 features = vectorizer.transform([review_text]) prob = model.predict_proba(features)[0][1] label = '正面' if prob >= 0.5 else '负面' return render_template('hotel_detail.html', review=review_text, sentiment=label, probability=round(float(prob), 4))predict_proba 返回的是一个二维数组,[0][1] 取的是「属于正类」的概率。很多人第一次写这里会直接取 [0],拿到的是负类的概率,导致预测结果完全反了,这是一个很容易掉进去的坑。阈值 0.5 是默认值,如果训练集类别不平衡,可以改成 0.4 或 0.6 来调整召回率与精确率的平衡,具体的值需要看验证集的 ROC 曲线来定,不要凭感觉拍脑袋。
4. Web 交互层:三个 HTML 模板如何支撑完整的产品体验
4.1 index.html:提交入口的设计逻辑
index.html 是整个系统的门面,它只需要做一件事:提供一个文本框和提交按钮,把评论文本以 POST 方式交给 /predict 路由。表单的 action 指向 Flask 路由地址,method 必须是 post,不然中文文本放在 URL 参数里会出现编码问题。页面上还可以放一条示例评论,比如「房间很干净,位置也方便,就是隔音不太好」,方便演示时快速填入。
模板里可以留一个隐藏字段,标记当前使用的是哪个模型,这样后续如果要加模型切换功能,不用改模板结构。评论输入框要设置 maxlength 限制长度,不然用户在页面上粘贴一篇几千字的评论,向量器转换出的稀疏矩阵虽然不至于崩,但响应时间会明显变慢。对演示场景来说,输入 200 字以内的评论是最舒适的体验区间。
4.2 hotel_detail.html:预测结果的展示规范
hotel_detail.html 负责把预测结果呈现给用户。建议展示三块内容:原始评论文本、情感标签、正类概率值。标签可以用不同的 CSS 颜色区分,正面用绿色、负面用红色,概率值保留四位小数,同时显示「模型判定该评论为正面/负面,置信度 xx%」。这种设计的价值在于,它把黑匣子结果透明化了——用户看到的不只是「正面」两个字,还能看到概率,知道模型有多确定。
模板里再加一个返回按钮,允许用户连续测试多条评论,这个细节在演示时很稳妥,能避免答辩现场因为回头操作麻烦而冷场。要注意的是,Flask 端返回 hotel_detail.html 时用的 render_template 参数名,必须和模板里的变量名一一对应,少传一个参数模板直接报 UndefinedError。
4.3 recommendations.html:基于情感分布的推荐思路
recommendations.html 是这套资源里比较灵活的部分,不同版本里它可能有不同形态。一种常见设计是:用户输入多条评论后,系统对每条评论做情感预测,统计正面评论占比,按占比排序给出一个「推荐指数」。这种设计比单条预测更能体现情感分析在真实业务里的价值——平台可以用它来筛选高分酒店,也可以识别差评集中的门店。
实现上,可以在 app.py 里加一个 /recommend 路由,接收一个包含多条评论的列表(来自表单 textarea 多行输入),逐条做预测,汇总结果。为了展示效果,模板里放一个表格,每一行是一条评论的原文、情感预测和概率,表格下方是正面评论条数和占比汇总。这一页如果做进课程设计报告,可以配一段话说明「本模块模拟了情感分析在用户决策支持场景中的应用」,很容易讲清楚。
5. 常见问题与排查指南:五个最容易翻车的点
5.1 pkl 文件加载失败:报错显示维度不匹配
现象是启动 app.py 后,第一次提交评论就报错,错误信息类似 ValueError: X has 2500 features, but LogisticRegression is expecting 3200 features。原因是训练模型时的特征维度,和加载的向量器转换出的维度不一致,也就是向量器换错文件了。比如用 tfidf_vectorizer.pkl 转换文本,却加载了 logreg_model.pkl 这个基于 CountVectorizer 训练的模型。
解决办法是配对加载:vectorizer.pkl 配 logreg_model.pkl,tfidf_vectorizer.pkl 配 xgboost_model.pkl,不要交叉使用。如果两个模型都是用同一份数据训练的,理论上向量器可以互换,但不同向量器的词汇表规模不同,特征维度就对不上。动手之前先看 README.md,里面有明确的加载组合说明。
5.2 中文文本预测不准:出现「正面」概率徘徊在 0.5 附近
现象是无论输入什么评论,预测概率都接近 0.5,模型给不出很确定的判断。原因是训练集里样本可能以英文评论为主,或者数据量偏少,中文泛化能力弱。很多公开的酒店评论数据集是英文的,中文的标注语料不多,资源包里的训练集可能在文本模式上与你要测试的中文评论差异较大。
解决办法是,把 Notebook 里的训练过程在自己的数据上重跑一遍,或者直接换用逻辑回归加载原始英文语料测试效果。如果必须测中文,找少量中文酒店评论并手动标注,追加进训练集重新训练模型,替换掉原来的 pkl 文件。别指望预训练好的模型对完全不在分布内的语言照样有效,这是自然语言处理的基础认知。
5.3 类别不平衡问题:模型全部预测为负面
有一种很隐蔽的翻车情况:训练集中负面样本占比超过 85%,逻辑回归学到的决策倾向是「宁可错杀,不可放过」,测试集准确率看着很高,但真实输入一些正面评论时全部被判负面。查看 Notebook 里的分类报告可以发现,负类的 F1 很高,正类的召回率可能只有 0.2 左右。
解决办法是,在训练前做类别重采样,对少数类做过采样,或者给模型加 class_weight='balanced' 参数。XGBoost 里也有 scale_pos_weight 参数可以调整正负样本权重。如果数据集本身比较均衡,就看测试集上两个类别的 F1 是否都在 0.8 以上,达不到就先处理类别不平衡,再谈调参。
5.4 Flask 用开发服务器跑生产:演示时卡死或报 500
取这个标题是因为很多同学在演示时直接用 python app.py 启动,没开 debug 模式,出错后页面只显示 500 Internal Server Error,排查困难。而且开发服务器是单进程的,同时有多个人访问性能很差。资源包定位是课设和毕设演示,单机演示没问题,但不代表它可以不做错误处理。
解决办法是,app.py 里显式声明 @app.errorhandler(500) 捕获异常并输出错误信息到日志文件,同时把 app.run(debug=True) 设置在单独的入口条件里,避免部署环境误开 debug。演示时建议先用本地浏览器完整走一遍流程,确认没有明显报错,再考虑给别人访问。
5.5 安装依赖时版本冲突:sklearn 新版无法加载旧版 pkl
现象是 pip install scikit-learn 装的是最新版本,运行 app.py 时 joblib.load 报 ModuleNotFoundError 或 AttributeError。原因是部分模型文件由旧版本 scikit-learn 训练导出,不同大版本的模型序列化格式不完全兼容。这个问题在课程设计里出现频率极高。
解决办法是,先在 README.md 里查看写明的依赖版本要求,按那个版本装环境,或者用 conda 建一个独立环境,在环境里安装 requirements.txt 中的固定版本。装完之后跑一遍 Noteb员工ok 里的模型训练单元,确认当前环境能正常生成和加载 pkl 文件,这一步可以作为环境是否就绪的冒烟测试。
6. 验收与答辩:你该怎么向老师和同学展示这套系统
验收一个情感分析系统,要按三个层次来走,每一层都有明确的可操作标准。
功能层验收最简单也最关键:打开浏览器访问首页,输入一条明显正面的评论「服务很好,早餐很丰富,下次还会来」,预测结果应该显示正面且概率明显大于 0.5;再输入一条「房间很脏,床单有异味,不会再住」,预测结果应该显示负面。这两条测试用例能跑通,说明 Web 链路是通的。再测一个边界用例:输入空白文本或只有标点符号的评论,页面应该给出友好提示而不是报错。
模型层验收要看分类报告:逻辑回归在测试集上的准确率不应该低于 0.8,F1 值至少达到 0.75 以上才算合格;XGBoost 如果效果明显低于逻辑回归,要能解释原因,通常是因为树模型在稀疏高维特征上的优势没有发挥出来,需要更多的特征工程。把两个模型的精确率、召回率、F1 值、训练时间放在一张对比表里,这页 PPT 就是整个答辩的实验核心。
答辩现场的高频问题,十有八九会出现在预测逻辑上。老师很可能会问:「你的系统怎么判断一条评论是正面的还是负面的?」这时候你要讲清楚:文本先被 TF-IDF 向量化,变成稀疏矩阵,然后逻辑回归给每个词学到一个权重,正面词权重为正,负面词权重为负,最后把所有词的加权分数求和再映射到 0 到 1 之间。为了应对这个问题,可以在 Notebook 里额外加一个步骤:输出权重绝对值排名前 20 的词,用来证明模型学到了有意义的语义信息,这是很亮眼的一个展示。
我留下一个习惯:每次演示前,都会先在本地跑一遍完整的最小路径——启动服务、输一条正面评论、输一条负面评论、确认结果页渲染正常,全程不超过两分钟。这套流程看起来简单,但技术演示翻车的概率,八成不是模型不工作,而是小问题没提前暴露。走到答辩现场才第一次开项目,那才是真的后悔药都找不到。希望这篇拆解能帮你在拿到资源包后,更快地把它变成一份自己讲得清楚、老师挑不出硬伤的设计方案。
本文还有配套的精品资源,点击获取