基于Word2vec与Flask的电影评论情感分析系统毕设详解

发布时间:2026/10/9 6:23:35
基于Word2vec与Flask的电影评论情感分析系统毕设详解 简介这是一份基于 Python 语言的深度学习电影评论情感分析系统设计与实现文档面向计算机专业毕业设计选题、自然语言处理初学者以及影评舆情分析开发者。内容围绕 Web 框架与词向量模型展开详细阐述了从系统需求分析、中文文本预处理、情感分类模型构建到分析结果可视化展示的完整设计流程并给出关键算法的选型理由与实现思路能够帮助读者理解如何利用深度学习对大量影评文本进行正向与负向倾向判断以及好坏评论比例的综合统计。资源为单个 docx 文档压缩包约 1.34MB包含中英文摘要、完整目录、绪论、相关技术介绍、系统设计等论文必备章节结构规范清晰适合直接作为毕业设计写作框架参考也可用于学习文本情感分析领域中的核心模型与工程实践。目前已有 466 人在线学习内容覆盖研究背景、架构设计、算法细节及应用场景是一份兼顾理论深度与项目落地性的参考资料。1. 电影评论情感分析系统是什么一份能直接复现的 Flask Word2vec 毕设文档把十万条影评丢进 Word2vec 训练成词向量再用 Flask 搭一个网页输入一句电影评论就能自动判断积极还是消极——这是「基于 python 深度学习的电影评论情感分析系统设计与实现」这份资源的真实能力。它是一份完整的毕业设计文档从绪论、算法研究、需求分析一直写到系统实现和测试适合正在选毕设题目、或者想快速搭一个文本情感分析 Demo 的开发者。技术栈很克制Python 处理数据和训练模型Flask 搭 Web 端MySQL 存数据核心算法是 Word2vec 词向量加情感值加权。不用 GPU不搞分布式一台普通笔记本加一个 PyCharm 就能复现。整套系统最值得抄的不是页面代码而是「词向量 → 句向量 → 情感分值」这条判断链路。下面按算法选型、系统设计、环境搭建、踩坑排查的顺序拆解把能直接落地的部分全部展开。文档和配套资源可以一起下载照着后面几章的步骤就能跑出完整系统。2. 从情感词典到 Word2vec算法选型的关键理由与训练参数影评情感分析可以粗略分成两派基于情感词典的传统方法和基于词向量的深度学习方法。这份资源选的是后者核心是 Word2vec。原因很直接情感词典对短文本的命中率不错但遇到「IOS 系统比 Android 系统好」和「Android 系统比 IOS 系统好」这类句子词典方案算出来的情感值几乎一样实际表达的意思却完全相反。Word2vec 把词放进上下文里训练词与词的相对位置带有语义信息能缓解这类顺序敏感问题。当然它不是银弹第 5 章会讲它翻车的地方。另外文档第 2 章先介绍了卷积神经网络但落地选型时用的却是 Word2vec。原因在于 CNN 擅长提取图像和局部 n-gram 特征对影评这种长度不一、句法自由的文本收益不如词向量加权直接而且 CNN 训练需要大量人工标注数据毕设场景下标注成本太高。理解了这个取舍后面看代码就不会纠结「为什么不用 CNN」这个问题。2.1 CBOW 和 Skip-gram两个训练模式怎么选Word2vec 有两种典型模型。CBOW 是根据上下文词预测中间词训练速度快对高频词友好Skip-gram 反过来根据中间词预测上下文词对低频词和小语料更稳。文档里的原话是「通过结合上下文来进行中间词的概率预测」实现层面就是 gensim 的sg参数sg0是 CBOWsg1是 Skip-gram。对电影评论这个场景我的建议是语料量在十万条以下用 Skip-gram。原因是评论里大量出现「烂」「炸裂」「惊艳」这类观点词很多词出现次数不高Skip-gram 捕捉低频词的能力更强。十万条以上、词频足够稳定再换回 CBOW 提速。训练完成后每个词对应一个固定维度的向量比如vector_size128意思是「好看」和「精彩」这两个词在 128 维空间里的距离会非常近。这是后续情感判断的基础也是模型「深度学习」效果的直接体现。2.2 情感词典与修饰词词典情感值计算的前提情感值计算离不开两份词典情感词典和修饰词词典。情感词典存的是每个词的正负极性修饰词词典存的是程度倍率。两者的 JSON 结构大概长这样# sentiment_dict.json 示例 { 精彩: {polarity: 1.0}, 好看: {polarity: 1.0}, 糟糕: {polarity: -1.0}, 无聊: {polarity: -1.0}, 一般: {polarity: 0.0} } # modifier_dict.json 示例 { 不: {weight: -1.0}, 没: {weight: -1.0}, 很: {weight: 1.5}, 非常: {weight: 1.8}, 太: {weight: 1.6} }polarity只用 1.0、-1.0、0.0 三档够用且不容易配错。weight是程度倍率否定词给负数程度副词给大于 1 的倍率。词典可以基于 HowNet 情感词表扩展也可以人工标注常用影评词——「惊艳」「催泪」「演技在线」这类影评高频词一定要覆盖否则判断会漏。这份资源的核心判断流程就是分词 → 定位情感词 → 向前找修饰词 → 乘权重 → 累加。这一步是整条链路的承重墙词典质量直接决定系统判断上限。模型训练得再好词典里没有「烂片」这个词系统也会对它视而不见。2.3 句向量加权把词向量变成一句话的情感值拿到词向量不等于能判断情感。评论是一句话不是单个词所以资源里的做法是先分词、去停用词再找到句子里的情感词和修饰词从第一个情感词开始逐个计算情感值和加权值循环到找完所有情感词累加得到整句的情感分。核心判断逻辑落到代码里是这个样子def calc_sentence_emotion(words, sentiment_dict, modifier_dict): total_score 0.0 for idx, word in enumerate(words): if word not in sentiment_dict: continue base sentiment_dict[word][polarity] # 情感词的基础极性 score base # 向前扫描最多两个位置命中修饰词就乘权重 for offset in (1, 2): if idx offset and words[idx - offset] in modifier_dict: score * modifier_dict[words[idx - offset]][weight] total_score score return total_score这段代码的关键点有两个。一是polarity是情感词典里每个词的正负极性「精彩」是 1「糟糕」是 -1二是modifier_dict的权重是预先配好的「不」是 -1「很」「非常」是 1.5 这类倍率。从情感词位置向前扫描一到两个词的修饰词保证「不是很差」这类组合能算出正向分数。这里有一个很容易写歪的地方扫描范围为什么只取两个位置因为影评里「真的很不好看」这种句子修饰词链超过两个后权重叠加容易失真三层否定「不是不好看」在中文里实际是偏正向的但纯乘权重会算成负向。所以扫描窗口限制在两个位置是工程上的折中宁可不处理也不乱处理。2.4 数据预处理分词、去停用词和语料清洗模型训练效果七成取决于预处理。资源里的链路是统一编码 → 分词 → 去停用词 → 清洗特殊符号。分词用 jieba停用词表自己维护一个 txt把「的」「了」「啊」「然后」这类无信息量的词过滤掉。重点提醒否定词不能进停用词表。import jieba STOPWORDS set() with open(stopwords.txt, r, encodingutf-8) as f: for line in f: STOPWORDS.add(line.strip()) def preprocess(text): text text.strip().lower() words jieba.lcut(text) return [w for w in words if w not in STOPWORDS and w.strip()]jieba.lcut返回分词列表按停用词表过滤后剩下的词就是进入 Word2vec 训练的语料。有个容易被忽略的细节停用词表里如果混入了「不」「没」「别」那「不好看」会被拆成「好看」模型直接判断反。我一般单独维护一个否定词表预处理时保留否定词在情感值计算阶段单独处理。预处理完把全部评论按每行一条写入movie_comments.txt每行内词与词用空格隔开格式对了才能交给LineSentence训练。3. 系统架构与数据库设计三张表的字段规划和 Flask 路由这套系统是典型的 B/S 结构浏览器访问Flask 提供页面和数据接口。整体链路是用户登录 → 首页搜索电影 → 进入电影简介页 → 查看评价分析 → 管理员查看情感分类结果。每个环节对应一个独立模块模块之间通过 MySQL 表关联。文档第 4 章给出了功能模块设计和数据库表设计这里按实际落地顺序拆一遍。3.1 功能模块划分登录、搜索、简介、分析和分类系统从需求上拆成五个模块。登录模块负责身份校验数据库存管理员账号首页模块是搜索入口文本框提交电影名称关键词电影简介模块展示名称、图片、主演、上映时间和简介带「立即播放」按钮评价分析模块是核心展示该电影积极、消极、一般三类评价占比用环形图呈现情感分类模块把每条评论打上情感标签存入数据库供管理员整体查看。五个模块有清晰的前后依赖没有登录进不了首页没有搜索看不到电影没有电影详情点不到评价分析。所以复现时建议先按「登录 → 搜索 → 详情 → 分析」的顺序打通页面链路再填情感分析算法逻辑否则容易出现页面全部写好了、模型还没跑通的尴尬局面。文档里对每个模块都有截图说明对照着写页面能省不少时间。3.2 数据库表设计管理员、电影、评论的字段规划文档里明确提出了管理员表和电影表实际开发中评论数据也需要一张表来存分析结果。三张表的字段规划如下。表 3-1 管理员表admin字段名类型说明idINT 自增主键管理员唯一标识usernameVARCHAR(50)登录用户名passwordVARCHAR(100)登录密码建议存哈希roleVARCHAR(20)角色默认 admincreate_timeDATETIME创建时间表 3-2 电影表movie字段名类型说明movie_idINT 自增主键电影唯一标识movie_nameVARCHAR(100)电影名称cover_imageVARCHAR(255)封面图片路径directorVARCHAR(50)导演actorsVARCHAR(255)主演逗号分隔release_dateDATE上映时间synopsisTEXT电影简介play_urlVARCHAR(255)在线播放地址表 3-3 评论表review字段名类型说明review_idINT 自增主键评论唯一标识movie_idINT外键关联电影表comment_textTEXT评论文本sentiment_labelVARCHAR(10)情感标签积极/消极/一般sentiment_scoreFLOAT情感分值like_countINT点赞数comment_timeDATETIME评论时间字段类型上有两个坑。简介和评论文本必须用 TEXTVARCHAR(255) 放不下长评论插入时会报Data too long时间字段统一用 DATETIME前端按时间排序展示热门点评时才不会出现字符串比较的偏差。建表 SQL 建议写成ENGINEInnoDB DEFAULT CHARSETutf8mb4不然中文评论插入时会报Incorrect string value。注意连接 MySQL 时连接串一定要带charsetutf8mb4三张表也统一用 utf8mb4这是中文评论不乱码的前提。3.3 Flask 路由设计和页面流转Flask 在这套系统里承担的是视图层和控制器的工作路由遵循传统 GET/POST 风格毕设项目不用刻意上 RESTful。核心路由可以这样组织from flask import Flask, render_template, request, redirect, url_for app Flask(__name__) app.route(/login, methods[GET, POST]) def login(): if request.method POST: username request.form.get(username) password request.form.get(password) # 校验通过重定向到首页失败留在登录页 return redirect(url_for(index)) return render_template(login.html) app.route(/, methods[GET]) def index(): return render_template(index.html) app.route(/movie/int:movie_id, methods[GET]) def movie_detail(movie_id): # 从 MySQL 查出电影详情传入模板 return render_template(movie_detail.html, moviemovie) app.route(/analyze/int:movie_id, methods[GET]) def analyze(movie_id): # 查出该电影全部评论逐条跑情感分析结果给前端渲染 return render_template(analyze.html, resultresult)movie/int:movie_id这种动态路由把电影详情和评价分析串在同一个 ID 下前端点「下一页」时带着movie_id跳转后端用WHERE movie_id ?查出对应数据。这就是整个页面流转最核心的一条线后面的展示页全部依赖它。数据查询我一般用 PyMySQL 直接写 SQL比引入完整 ORM 更直观也方便调试。登录态可以用 Flask 的session管理登录成功后写入session[user]每个页面开头判断一下没登录就重定向回/login。4. 动手复现PyCharm 环境配置、模型训练和情感分析接口前面把算法和架构讲清楚了这一章直接落到能跑通的步骤。环境建议 Windows 10 以上、PyCharm 2022 以上Python 用 3.8 或 3.9不需要 GPU。按「环境 → 训练 → 接口」三步走。4.1 依赖安装和项目目录规划新建一个虚拟环境避免和系统 Python 打架。依赖就五个核心包Flask、Flask-SQLAlchemy、PyMySQL、gensim、jieba。装完确认一次版本防止 gensim 和 numpy 版本冲突导致训练直接崩。python -m venv venv venv\Scripts\activate pip install flask flask-sqlalchemy pymysql gensim jieba python -c import gensim; print(gensim.__version__)提示如果训练时报module numpy has no attribute float是 numpy 1.24 移除了旧别名把 numpy 降到 1.23.5 即可解决。gensim 4.x 把size参数改成了vector_size老教程里的Word2Vec(sentences, size128)在新版本会直接报TypeError。项目目录我一般这样建data/放语料和停用词表models/放训练好的模型templates/放 HTML 模板app.py放 Flask 主程序。语料文件命名用英文避免路径编码问题。4.2 Word2vec 模型训练代码语料准备好之后训练代码很短。关键在参数vector_size128是词向量维度window5是上下文窗口min_count2过滤出现次数少于 2 的词sg1用 Skip-gramepochs20是训练轮数。性能一般的电脑把vector_size降到 100、epochs降到 10速度和效果差距不大。from gensim.models import Word2Vec from gensim.models.word2vec import LineSentence # 语料格式每行是一句分词后的评论词之间用空格隔开 sentences LineSentence(data/movie_comments.txt) model Word2Vec( sentences, vector_size128, window5, min_count2, sg1, epochs20, workers4 ) model.save(models/word2vec_movie.model) # 冒烟测试查看「精彩」的相似词确认语义学出来了 for word, score in model.wv.most_similar(精彩, topn5): print(word, round(score, 4))LineSentence是 gensim 的流式迭代器按行读语料不把全部数据一次性载入内存几万条评论完全够用。most_similar是训练完必做的一次验证如果「精彩」的相似词里有「好看」「出色」「惊艳」说明模型学出了语义如果输出一堆无关词回去查语料格式和编码大概率是预处理环节的问题训练本身很少出错。这里要特别说明Word2vec 训练是无监督的不需要人工标注所以毕设场景下数据准备成本集中在分词和清洗不在打标签上。4.3 情感分析接口封装和 Flask 联动模型训练完接口层做两件事分词预处理、情感值计算。把前面的preprocess和calc_sentence_emotion组合封装Flask 路由直接调用import json from flask import Flask, request, jsonify from preprocess import preprocess from emotion import calc_sentence_emotion app Flask(__name__) # 加载情感词典和修饰词词典 sentiment_dict json.load(open(data/sentiment_dict.json, encodingutf-8)) modifier_dict json.load(open(data/modifier_dict.json, encodingutf-8)) app.route(/api/analyze, methods[POST]) def api_analyze(): comment request.form.get(comment, ) if not comment.strip(): return jsonify({error: 评论内容不能为空}), 400 words preprocess(comment) score calc_sentence_emotion(words, sentiment_dict, modifier_dict) if score 0.05: label 积极 elif score -0.05: label 消极 else: label 一般 return jsonify({label: label, score: round(score, 4)})接口返回的label直接驱动前端环形图。0.05 的阈值是为了避免把中性评论误判成积极或消极这个值可以根据测试集准确率微调。前端拿到 JSON 后把积极、消极、一般的评论数分别累加传给 ECharts 渲染环形图。MySQL 的连接用 PyMySQL 直连即可pymysql.connect(host, user, password, database, charsetutf8mb4)注意字符集参数必填。整个链路跑通后输入「特效炸裂值得一看」返回积极输入「剧情拖沓看得想睡觉」返回消极这时候模型就真正接进系统了。5. 避坑指南情感分析复现中的五个常见问题与排查这一章是血泪经验。我照着这份资源完整复现过一遍下面五个坑每个都踩过按「现象 → 原因 → 解决」写清楚遇到直接照着查。5.1 训练完的模型输出全是乱序词或直接报 KeyError现象most_similar(精彩)返回的词和「精彩」毫无关联甚至直接抛KeyError: 精彩 not in vocabulary。原因语料文件编码不是 UTF-8或者文本从 Word 里直接复制出来带了 BOM 头和不可见字符jieba 分词后大量词没进词典词表里根本没有「精彩」。解决用 VS Code 或 Notepad 把所有语料统一转成 UTF-8 without BOM预处理时加一行text.encode(utf-8, errorsignore).decode(utf-8)把脏字符扔掉。改完重新训练再跑most_similar验证。判断依据是词表大小训练后打印len(model.wv.key_to_index)如果只有几百个词语料肯定没读对。还有一个连带问题如果语料里混入了爬虫抓下来的 HTML 标签分词结果会全是碎片词建议先写一个临时脚本把几条样本分词结果打印出来肉眼扫一遍确认没有、、nbsp;残留再训练。5.2 情感判断和实际感受完全相反现象输入「这部电影非常不好看」系统返回「积极」。原因否定词「不」被停用词表过滤了剩下的「好看」被情感词典判成积极或者修饰词权重没配「非常不好看」里的「不好看」没有正确翻转。解决停用词表里绝对不要放否定词检查停用词文件里有没有「不」「没」「别」「莫」在情感词典里单独配「不好看」「不好」这类组合词条让词典直接命中。停用词表是个黑匣子过滤规则越少越可控我后来把所有否定词从停用词表彻底移除并单独维护一个否定词表判断准确率立刻提升。经验是改完词典和停用词表后务必拿测试集重新跑一遍准确率别只在浏览器里试一两句话就收工。5.3 中文评论在页面上显示乱码现象MySQL 里存的评论读出来是????????页面标题和评论内容全部乱成一团。原因建表时字符集是默认的latin1或者连接串没指定字符集中文被转成拉丁字符集后数据已经损坏无法原地恢复。解决建库建表统一用utf8mb4连接串必须带charsetutf8mb4。已经在latin1表里的数据导出后转码重新导入不要指望在现表上直接改字符集能恢复乱码。这个坑在毕设答辩演示时最容易暴露别人一输中文评论页面上全是问号观感非常差。数据库连接对象创建后建议先执行一次SET NAMES utf8mb4双保险。5.4 gensim 版本 API 不兼容导致训练报错现象Word2Vec(sentences, size128)报TypeError或者训练完访问model.wv报属性不存在。原因gensim 4.x 把size改成了vector_size老教程代码直接迁移会挂。解决装 gensim 3.8.3或者把代码升级成vector_size。我建议升级代码而不是降版本gensim 4.x 的LineSentence和most_similar效率更高后续扩展也方便。验证方法是训练后执行print(model.wv.vector_size)能输出 128 就说明 API 走通了。另外 gensim 4.x 里model.most_similar的顶层方法已经被移除统一改用model.wv.most_similar写代码的时候留意一下。5.5 环形图数据一直不刷新现象提交新评论后环形图占比不变热门点评还停留在旧数据。原因前端把情感分析结果写死在初始化数据里没有重新从/api/analyze拿最新结果或者 Flask 路由返回了缓存页面。解决环形图的数据源改成每次切换电影时重新请求接口Flask 侧对动态页面关闭缓存响应头加response.headers[Cache-Control] no-store。排查方法是在浏览器 DevTools 的 Network 面板确认/api/analyze每次都有新的 JSON 返回——有返回就问题在前端无返回就问题在后端十分钟内能定位。另外要注意前端累加情感标签计数的逻辑很多人习惯在初始化时写死一个{积极: 30, 消极: 10}后续拿接口数据更新时直接覆盖而不是累加导致数字对不上。6. 结果可视化验证用环形图和准确率指标核验模型效果资源里的电影评价分析页用的是环形图展示积极、消极、一般的占比这个环节值得再往前推一步画图之前先做一次模型准确率核验。常见做法是手工标注 100 条测试评论跑一遍模型统计分类准确率。我一般会建一个test_set.txt每行一条评论加真实标签用制表符分隔跑完输出准确率correct 0 total 0 with open(data/test_set.txt, r, encodingutf-8) as f: for line in f: parts line.strip().split(\t) if len(parts) ! 2: continue text, true_label parts pred_label analyze_text(text)[label] total 1 if pred_label true_label: correct 1 print(f准确率: {correct / total:.2%})准确率到 85% 以上环形图才有说服力。然后才是前端可视化把接口返回的积极、消极、一般数量传给 ECharts 的pie系列roseType: radius的玫瑰图比普通环形图更能放大占比差异适合答辩展示。热门点评列表按like_count倒序取前十条和情感标签一起渲染形成「占比图 示例评论」的对照观众一眼能看出模型判断不是瞎蒙。从那以后我每次做这类情感分析系统都会强制走一遍「训练 → 冒烟验证 → 手工标注测试集 → 准确率达标再画图」的流程。训练完先跑most_similar看词向量有没有学出语义再对测试集算准确率最后才把模型接进 Flask。这条顺序一旦反过来十个有八个会在答辩前夜因为模型效果翻车。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询