
简介这是一套面向计算机相关专业学生与项目实战学习者的Python酒店评论情感分析系统可直接用于毕业设计、课程设计或期末大作业。项目以中文酒店评论为数据源围绕文本预处理、情感分类模型训练与可视化界面展开属于自然语言处理方向的入门到进阶实践案例。压缩包共43个文件约56.55MB包含6个py源码文件、20张png界面与结果图、3个jpg示意图、1个ui界面文件、1个ttf字体、1个h5模型权重、1个csv测试数据、1个json配置及说明文档等覆盖从数据爬取、模型训练到图形界面展示的完整链路。目前已有291人学习下载。项目经过严格调试确保可运行附带使用说明与项目说明读者可据此快速理解情感分析流程、复用界面代码、参考模型权重与测试数据并在此基础上完成二次开发或论文撰写适合需要完整可运行方案的学习者参考。1. 从一份能跑通的酒店评论情感分析源码说起打开这份利用Python实现酒店评论的中文情感分析.zip第一眼看到的不是一堆散乱脚本而是一套完整可运行的桌面系统main.py是入口main.ui配mainWindow.py撑起界面crawl.py负责抓评论weigths.h5是训练好的模型权重test.csv、test.json、test.txt是现成的测试样本accuracy_test.py单独做精度验证font.ttf解决中文显示wordCloud.jpg和analyse.png是可视化产物。它解决的核心问题很具体——把中文酒店评论自动判成好评、中评、差评并且用图形界面把结果摆出来。适合正在做 Python 毕业设计、期末大作业或者想找一个能直接跑通的中文情感分析实战项目练手的人。很多人卡在“模型训练完不知道怎么接到界面上”这份代码把这条链路走通了。2. 拆开这套源码文件结构、技术栈与选型理由2.1 目录里每个文件到底干什么拿到压缩包解压后根目录下大致分四类东西。第一类是入口与界面main.py启动程序main.ui是 Qt Designer 画出来的界面文件mainWindow.py是它编译后的 Python 代码resource.qrc和resource_rc.py管理图标、图片等资源。第二类是数据与模型crawl.py抓取评论weigths.h5保存训练好的网络权重test.csv、test.json、test.txt是不同格式的测试数据。第三类是评估与可视化accuracy_test.py算准确率analyse.png、wordCloud.jpg、train.png、Average.png、Poor.png、Fair.png、Good.png、Excellent.png、count.png是各类统计图。第四类是辅助font.ttf中文字体使用说明.txt操作说明demo1.png到demo4.png是运行截图。这里有个容易忽略的点__pycache__里带着cpython-36的 pyc 文件说明作者当初是在 Python 3.6 环境下跑通的。你如果直接用 3.11 或 3.12某些库的 API 可能已经变了这是后面避坑章节要重点说的。2.2 为什么用 Keras h5 而不是 PyTorch从weigths.h5这个文件名就能判断模型是用 KerasTensorFlow 后端保存的 HDF5 格式。选它的理由很实际毕业设计场景下Keras 搭 LSTM 或 BiLSTM 做文本分类代码量比 PyTorch 少model.save(weigths.h5)一行就能把结构和权重一起存下来加载时load_model直接还原不需要额外写网络定义。对于中文情感分析这种“嵌入层 循环层 全连接”的经典结构Keras 的Sequential模型足够用。常见做法是先用Tokenizer把中文评论转成整数序列pad_sequences统一长度然后走Embedding → LSTM → Dense(sigmoid 或 softmax)。三分类就用 softmax 输出 3 维二分类就用 sigmoid 输出 1 维。这份代码从图片文件名看有 Excellent、Good、Fair、Average、Poor 五档但实际建模时通常会合并成正面、中性、负面三类否则样本不均衡会很难训。2.3 界面层为什么选 PyQt5main.uimainWindow.py的组合是 PyQt5 的典型工作流。用 Qt Designer 拖控件保存成.ui再用pyuic5转成.py。相比 tkinterPyQt5 做出来的界面更接近商业软件图表嵌入、表格展示、图片切换都更顺手。毕业设计答辩时一个能点按钮、能出图、能切页签的界面比命令行打印结果加分得多。resource.qrc是 Qt 的资源系统把图标、图片打包进 Python 文件避免运行时找不到路径。resource_rc.py就是pyrcc5 resource.qrc -o resource_rc.py的产物。这一步很多人会忘导致换台电脑图标全丢。2.4 环境怎么搭从零到能跑先确认 Python 版本。源码里是 3.6我建议用 3.7 或 3.8太新的版本 TensorFlow 和 PyQt5 的兼容性会出问题。用 conda 建独立环境最稳conda create -n hotel_sa python3.8 conda activate hotel_sa然后装依赖。这份代码没有requirements.txt需要手动装。核心就几个pip install tensorflow2.4.0 pip install PyQt55.15.4 pip install jieba pip install pandas numpy matplotlib pip install wordcloudtensorflow负责 Keras 模型加载和推理PyQt5撑界面jieba做中文分词pandas读 csvmatplotlib画图wordcloud生成词云。版本不要盲目追新TensorFlow 2.4 配 Python 3.8 是经过验证的组合。装完后先别急着跑main.py先单独验证模型能不能加载from tensorflow.keras.models import load_model # 加载训练好的权重compileFalse 避免自定义损失函数报错 model load_model(weigths.h5, compileFalse) model.summary()compileFalse是关键。如果原模型用了自定义的损失函数或指标直接加载会报Unknown loss function加上这个参数先看结构确认没问题再决定要不要补custom_objects。3. 把评论喂进模型分词、序列化与预测全流程3.1 中文分词与停用词处理中文情感分析第一步不是建模是把句子切成词。jieba是标配import jieba def cut_text(text): # 精确模式分词适合情感分析这种需要保留完整语义的场景 words jieba.lcut(text) # 过滤掉单字和空白单字对情感贡献低还增加噪声 words [w for w in words if len(w) 1 and w.strip()] return .join(words) sample 这家酒店位置很好但是房间隔音太差了 print(cut_text(sample)) # 输出酒店 位置 很好 但是 房间 隔音 太差逻辑说明jieba.lcut返回列表比jieba.cut直接拿生成器方便。过滤单字是因为“的”“了”“很”这类词在情感分类里权重极低留着只会让词表膨胀。参数上len(w) 1这个阈值可以调如果你发现“差”“好”这种单字情感词被误删可以改成保留特定情感词典里的单字。停用词表一般放在stopwords.txt里逐行读取后转成 set分词后做差集。这份代码的test.txt可能就是测试语料test.json可能是带标签的样本。3.2 用 Tokenizer 把词转成数字Keras 的Tokenizer负责建词表和转序列from tensorflow.keras.preprocessing.text import Tokenizer from tensorflow.keras.preprocessing.sequence import pad_sequences # num_words 限制词表大小只保留出现频率最高的 5000 个词 tokenizer Tokenizer(num_words5000, oov_tokenOOV) tokenizer.fit_on_texts(corpus) # 转成整数序列 sequences tokenizer.texts_to_sequences(corpus) # maxlen 统一长度短的补 0长的截断 X pad_sequences(sequences, maxlen100, paddingpost, truncatingpost)参数说明num_words5000是经验值酒店评论的词汇量通常不大5000 足够覆盖。oov_token给未登录词一个占位符避免预测时遇到新词直接报错。maxlen100意味着每条评论保留 100 个词酒店评论一般不会超过这个长度超了就截断。paddingpost在末尾补零truncatingpost从末尾截断保持一致。这里有个坑训练时的Tokenizer必须和预测时用的是同一个。如果你重新fit_on_texts词表变了序列号就对不上模型输出全是乱的。正确做法是把训练好的tokenizer用pickle存下来预测时加载。3.3 加载模型做单条预测import pickle from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing.sequence import pad_sequences # 加载词表 with open(tokenizer.pickle, rb) as f: tokenizer pickle.load(f) # 加载模型 model load_model(weigths.h5, compileFalse) def predict_sentiment(text): words cut_text(text) seq tokenizer.texts_to_sequences([words]) padded pad_sequences(seq, maxlen100, paddingpost, truncatingpost) # 输出三维概率取最大值对应的类别 pred model.predict(padded)[0] labels [负面, 中性, 正面] return labels[pred.argmax()], pred result, probs predict_sentiment(房间很干净服务态度也好) print(result, probs)逻辑说明model.predict返回的是 batch 维度的数组取[0]拿单条。argmax取概率最大的索引映射到标签。如果你发现预测结果总是同一类大概率是词表没对上或者输入文本没做和训练时一样的分词。3.4 批量测试与准确率验证accuracy_test.py干的就是这件事。用test.csv里的带标签数据跑一遍import pandas as pd from sklearn.metrics import classification_report df pd.read_csv(test.csv) true_labels df[label].tolist() pred_labels [predict_sentiment(t)[0] for t in df[comment].tolist()] # 输出精确率、召回率、F1 print(classification_report(true_labels, pred_labels))classification_report比单纯看准确率有用得多。如果负面类召回率特别低说明模型把差评误判成了好评这在酒店场景里是致命的——用户看到差评被标成好评直接不信任系统。4. 界面与模型怎么接PyQt5 调用 Keras 的实操细节4.1 从 .ui 到可运行窗口main.ui是设计文件不能直接跑。需要转成 Pythonpyuic5 main.ui -o mainWindow.py pyrcc5 resource.qrc -o resource_rc.py第一条把界面布局转成类第二条把图片资源转成 Python 模块。转完后mainWindow.py里会有一个Ui_MainWindow类main.py里实例化它并绑定按钮事件。常见做法是在main.py里写一个继承QMainWindow的类把Ui_MainWindow作为成员然后在__init__里连接信号槽from PyQt5.QtWidgets import QApplication, QMainWindow from mainWindow import Ui_MainWindow import sys class HotelApp(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 绑定按钮点击到预测函数 self.pushButton.clicked.connect(self.on_predict) def on_predict(self): text self.textEdit.toPlainText() if not text.strip(): return result, _ predict_sentiment(text) self.label_result.setText(f预测结果{result}) app QApplication(sys.argv) window HotelApp() window.show() sys.exit(app.exec_())逻辑说明setupUi负责把控件摆好clicked.connect把按钮和槽函数绑起来。toPlainText()拿多行文本框内容setText更新结果标签。注意predict_sentiment要提前定义或导入否则界面点下去会报NameError。4.2 把 matplotlib 图表嵌进 PyQt5analyse.png、wordCloud.jpg这些图如果只是静态展示用QPixmap加载到QLabel就行。但如果要动态画图得用FigureCanvasfrom matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure class PlotCanvas(FigureCanvas): def __init__(self, parentNone): fig Figure(figsize(5, 4), dpi100) super().__init__(fig) self.axes fig.add_subplot(111) def plot_bar(self, labels, values): self.axes.clear() self.axes.bar(labels, values) # 中文标签需要指定字体否则显示方块 self.axes.set_title(情感分布, fontpropertiesfont.ttf) self.draw()font.ttf就是为这一步准备的。matplotlib 默认字体不含中文不指定就会显示成方框。用font_manager注册后全局设置更省事from matplotlib import font_manager font_manager.fontManager.addfont(font.ttf) plt.rcParams[font.family] SimHei4.3 词云生成的参数怎么调wordCloud.jpg是词云产物生成代码通常长这样from wordcloud import WordCloud # 把正面评论拼成一个长字符串 text .join(positive_comments) wc WordCloud( font_pathfont.ttf, # 中文字体路径不设会乱码 width800, height400, # 画布尺寸 background_colorwhite, # 背景色 max_words100, # 最多显示 100 个词 colormapviridis # 配色方案 ).generate(text) wc.to_file(wordCloud.jpg)参数说明font_path必须指向支持中文的 ttfmax_words控制密度太多会挤成一团。colormap可以换成Reds或Blues来配合情感倾向——正面用暖色负面用冷色视觉上更直观。5. 避坑与排查跑不起来时先看这几条5.1 报No module named tensorflow或版本冲突现象pip install tensorflow装完导入时报ImportError或DLL load failed。原因Python 版本和 TensorFlow 版本不匹配。源码是 3.6 环境你如果用 3.11TensorFlow 2.4 根本没有对应的 wheel。解决降 Python 到 3.8或者升 TensorFlow 到 2.10 以上。但升 TensorFlow 后load_model可能因为 Keras 版本差异报错这时候用compileFalse先加载再手动compile。5.2 加载 h5 模型报Unknown loss function现象load_model(weigths.h5)直接抛异常提示某个 loss 或 metric 找不到。原因训练时用了自定义函数保存时只存了名字加载时没有对应的定义。解决先load_model(weigths.h5, compileFalse)只加载结构预测不受影响。如果必须 compile用custom_objects传进去model load_model(weigths.h5, custom_objects{focal_loss: focal_loss})5.3 界面中文显示成方块现象PyQt5 界面上的中文标签、按钮文字全是方框。原因系统缺少中文字体或者 matplotlib 没指定字体。解决PyQt5 一般跟随系统字体如果系统有中文字体还乱码检查font.ttf是否被正确加载。matplotlib 那边必须显式设置font_path或rcParams[font.family]。5.4 预测结果全是同一类现象不管输入什么评论模型都输出“正面”或都输出“负面”。原因最常见的是词表对不上。训练时的Tokenizer和预测时的不是同一个序列号全错。其次是输入文本没做分词直接把整句喂进去texts_to_sequences找不到对应词全变成 OOV。解决确认tokenizer.pickle是训练时保存的那个预测前先cut_text分词。如果还不行打印padded看看是不是全零。5.5crawl.py抓不到数据现象运行爬虫脚本报连接错误或返回空列表。原因目标页面结构变了或者请求头没带 User-Agent 被拒。解决检查requests.get是否带了headers解析用的BeautifulSoup或XPath是否还匹配当前页面。这类脚本依赖外部网站时效性差建议直接用test.csv里的现成数据做演示别在答辩现场跑爬虫。6. 让这份代码真正变成你的改哪里、怎么验、如何讲拿到一份能跑的源码最忌讳的是“跑通就完事”。答辩老师或面试官问一句“你这个模型为什么用 LSTM 不用 TextCNN”答不上来就露馅了。我的习惯是先把weigths.h5的结构打出来逐层看参数model load_model(weigths.h5, compileFalse) for i, layer in enumerate(model.layers): print(i, layer.name, layer.output_shape if hasattr(layer, output_shape) else )看完你会知道嵌入层维度是多少、LSTM 单元数是多少、最后 Dense 是几维。这些数字就是你讲故事的素材——嵌入层 128 维说明词向量压缩得比较狠LSTM 64 单元说明模型不大适合小数据集。然后做一件很多人不做的事把test.csv按 8:2 切开自己重新训一版对比原模型的准确率。如果原模型在测试集上 92%你自己训出来 88%差距在哪可能是学习率、batch size、或者早停策略。把这个对比写进论文的“实验分析”章节比单纯贴一张准确率截图有说服力得多。再进一步改main.py里的界面逻辑。原版可能只支持单条输入你加一个“批量导入 CSV”按钮读文件后逐条预测结果写回新 CSV。这个改动不大但演示效果直接翻倍——老师看到你能处理批量数据印象分完全不一样。验证方法上除了accuracy_test.py我建议加一个混淆矩阵from sklearn.metrics import confusion_matrix import seaborn as sns cm confusion_matrix(true_labels, pred_labels) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(预测) plt.ylabel(真实) plt.savefig(confusion_matrix.png)这张图能直观看出模型在哪类评论上容易翻车。如果“中性”那一行错得特别多说明中性评论的特征不明显可以考虑合并到正面或负面或者加更多中性样本。最后说个血泪经验答辩前一定要在答辩用的电脑上完整跑一遍。我见过太多人在自己电脑上好好的换台机器就因为 Python 版本、缺少字体、路径带中文而翻车。把font.ttf、weigths.h5、tokenizer.pickle这三个文件单独拷出来写一个最小加载脚本确认在新环境下能跑通再上场。从那以后我每次交付这类项目都强制走一遍“换机验证”希望帮到你。本文还有配套的精品资源点击获取