资讯动态

基于Python与Django的机器学习文本情感分析系统实现

发布时间:2026/10/2 10:58:22 来源:尧图企业网站定制
简介这是一份基于Python的机器学习文本情感系统毕业设计文档面向计算机相关专业毕业生与自然语言处理初学者系统讲解从需求分析到系统实现的完整流程。文档围绕Python、Django框架与MySQL数据库展开给出了情感分类系统的总体架构、功能模块划分、数据库设计并具体展示登录模块、管理员首页、文本分类、文本管理、用户信息管理等核心界面的实现思路适合课程设计、毕业设计或作为相关项目起步参考。资源仅包含1个docx文档压缩包约1.07MB目录覆盖绪论、系统分析、系统设计、系统实现与系统测试等完整章节结构清楚、便于按需查阅。目前已有323人学习下载是一份能够帮助读者快速理解文本情感分析系统设计要点并在此基础上扩展开发的实用资料。1. 基于python的机器学习文本情感系统它解决的是什么问题把一段网络评论自动判断成“积极”或“消极”听起来只是个小功能但真正要搭一套能演示、能答辩、能在浏览器里完整跑通的系统背后还牵涉中文分词、模型训练、页面交互、数据落库和后台管理一整套链路。这套基于python的机器学习文本情感系统设计与实现选用的是 Python Django MySQL 的 B/S 架构用户在网页文本框里输入一句中文系统调用训练好的情感分类模型返回情绪倾向并把判断记录存进数据库管理员登录后可以查看、删除分类记录维护用户信息。它适合正在做文本情感方向毕业设计或课程设计的人拿来复现也适合刚接触机器学习项目、想弄清“算法到底是怎么被 Web 项目调用起来”的初学者。2. Django MySQL 技术选型MTV 架构与数据库设计落地2.1 为什么是 Django 而不是 FlaskMTV 分层带来的开发效率文本情感系统的核心是算法但这不代表 Web 部分可以随便凑合。论文里选定 Django 而不是 Flask核心原因是 Django 是一个自带电池的框架ORM、表单处理、会话管理、CSRF 防护、后台模板引擎全部内置开发者不需要花费额外精力去拼装第三方库。对一个以“情感分类效果好、页面能跑通”为目标的毕设项目来说用 Flask 虽然轻量但登录、权限、数据库迁移这些通用机制都要自己接整体工作量反而会大不少。更要紧的是 Django 的 MTV 分层方式恰好把“算法调用”和“业务逻辑”拆得很清晰。M 对应 Model负责和 MySQL 的表结构做映射T 对应 Template负责渲染 HTML 页面V 对应 View负责接收 HTTP 请求、调用情感分类模型、组织数据并返回响应。实际写代码时训练好的模型被封装成一个独立组件放在 View 层里被调用算法部分和 Web 部分互不干扰。这也是答辩时经常被问到的概念题MVC 和 MTV 的区别到底是什么。Django 的 MTV 在职责安排上对应经典 MVC 模式但控制器角色被框架一部分吸收掉了。URL 路由负责把请求分发给对应 View而 View 内部处理业务逻辑模板系统承担展示逻辑。简单说你在 Django 里写的 View承担的其实更接近 Controller 加 Model 调用的混合职责。理解了这一点后面写文本分类接口、登录校验、记录管理时心里会非常有数。2.2 数据库表设计管理员表与文本分类表字段定义论文中的 E-R 模型给出了两个核心实体管理员实体和文本分类实体。管理员实体包含管理员编号、用户名、密码文本分类实体包含分类编号、分类内容。落到 MySQL 里按常规表结构设计思路扩展即可。管理员表负责保存后台登录账号字段包括用户 ID、用户名、加密后的密码、手机号、创建时间。文本分类表要记录每一次情感判断过程字段包括分类记录 ID、关联用户 ID、原始输入文本、模型判断结果、创建人、创建时间。之所以要把“原始输入文本”和“判断结果”分开存是为了后续在文本管理界面能回看每一次判断的来源和依据也为以后扩充训练数据做准备。MySQL 在这类场景下非常合适数据量不大关系型结构清晰多用户并发查询也有保障。创建数据库表的 SQL 语句可以这样写CREATE DATABASE sentiment_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE admin_user ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE sentiment_record ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, content_text TEXT NOT NULL, sentiment_result VARCHAR(10) NOT NULL, creator VARCHAR(50), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );这段建表逻辑有几个关键参数值得说明。数据库字符集指定 utf8mb4而不是直接使用默认字符集是为了让中文文本能够完整存储也兼容 Emoji 符号这个细节在部署到 Windows 或 Linux 时经常能避免一场乱码事故。sentiment_result 字段预留 VARCHAR(10)足够存放“积极”“消极”两个字如果你后续想把分类扩展到“中性”甚至更细粒度只需要加一个模型输出映射不需要改动表结构。Django 实际开发时我们一般直接借助 ORM 的 migrate 来自动建表但保留一份手写 SQL 在论文里做数据字典对答辩展示更直观。2.3 初始化 Django 项目并接入 MySQL从 startproject 到跑通登录页环境准备阶段先创建项目和工作目录。pip install django mysqlclient jieba scikit-learn joblib django-admin startproject sentiment_system cd sentiment_system python manage.py startapp sentiment安装包时建议用虚拟环境不要把包直接装到系统 Python 里这能减少后面实验环境依赖冲突的概率。其中 mysqlclient 是 MySQL 的 Python 驱动安装失败时可以考虑用 PyMySQL 替代这一点在避坑章节会展开讲。创建完应用后需要把 sentiment 加入 INSTALLED_APPS再在 settings.py 里配置数据库连接。DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: sentiment_db, USER: root, PASSWORD: 你的数据库密码, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, }, } }这里的核心参数就三组ENGINE 指定后端数据库类型NAME 对应刚才用 SQL 创建的库名HOST 和 PORT 决定连接地址。OPTIONS 里显式加 charset 是惯用做法可以避免后续读取中文时出现编码不一致的问题。配置完成后执行 python manage.py migrateDjango 会为自带的用户、会话等表自动建表。跑通这一步以后项目就能和 MySQL 正常通信接下来才轮到文本情感分类的核心模块。3. 情感分类模块实现TF-IDF 朴素贝叶斯从训练到调用3.1 算法选型思路为什么先上 TF-IDF 朴素贝叶斯文本情感分类的主角是模型但模型并不是越复杂越好。对于中文短文本分类来说TF-IDF 加朴素贝叶斯组合几乎是入门阶段性价比最高的方案原因有三。词频思路非常直观把每一句话转成词频向量再计算每个词在文档中的重要程度实现成本低sklearn 中几行代码就能完成性能足够在情感倾向这种二分类任务上配合适量数据通常能稳定达到可用水平。比它更复杂的方案——LSTM、BERT、TextCNN——当然效果更好但代价是数据需求大、训练时间长、环境配置重。一个毕业设计系统如果要兼顾算法深度和项目完成度朴素贝叶斯这类经典模型反而更容易把整条链路讲清楚。论文中提及自然语言分类是热点话题且系统设计目标是让机器能判断语义表达是积极还是消极这个任务用 TF-IDF 将文本向量化之后交给朴素贝叶斯分类完全能够满足设计目标。更重要的是这套方案在普通笔记本上就能完成训练不需要 GPU也不涉及复杂的中文预训练模型下载复现门槛非常低。还有一层原因和项目的可解释性有关。朴素贝叶斯本质上是基于条件概率的判别模型它把每个词在类别下出现的概率累计起来最后取最大概率的类别作为判断结果。这种计算逻辑在论文中描述起来非常清晰机器选定一些情感倾向明显的词作为特征词把句子中的这些词加权汇总再对比积极类和消极类的综合得分得出判断。比起深度学习模型的黑匣子特性朴素贝叶斯的决策过程更容易用朴素的语言展示给评委。3.2 训练脚本分词、向量化、模型保存中文文本和英文文本最大的差别在于没有天然空格分词所以任何中文文本分类项目的第一步都是中文分词。这里使用 jieba 分词库它是最常用的开源中文分词工具支持精确模式、全模式和搜索引擎模式默认采用精确模式就能满足大多数短文本分类需求。分好词以后把词用空格拼接再用 TF-IDF 向量化器转换最后喂给朴素贝叶斯模型训练。# train_model.py import jieba import joblib from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB # 样本格式(文本内容, 标签)1 表示积极0 表示消极 raw_data [ (这家酒店环境很好服务到位, 1), (下次还会再来性价比高, 1), (交通方便房间也干净, 1), (卫生特别差不会再住, 0), (环境太差了窗户还漏风, 0), (前台态度很差等了一个小时, 0), ] def cut_words(text): return .join(jieba.cut(text)) X [cut_words(text) for text, _ in raw_data] y [label for _, label in raw_data] vectorizer TfidfVectorizer() X_vec vectorizer.fit_transform(X) model MultinomialNB() model.fit(X_vec, y) joblib.dump(vectorizer, vectorizer.pkl) joblib.dump(model, sentiment_model.pkl) print(模型训练完成并已保存)这段脚本的逻辑链路是先对每一条文本用 jieba.cut 做分词再转成空格分隔的字符串TfidfVectorizer 接收这个字符串列表统计每个词在全部文本中的出现频率和逆文档频率把每条文本变成一个稀疏向量MultinomialNB 对这个稀疏向量做训练学习积极类和消极类各自的特征分布。最后用 joblib 把向量化器和模型分别保存成 pkl 文件供 Django 项目调用。关键的参数调节点是 TfidfVectorizer 的初始化参数。默认情况下它会忽略单个字符的词这对中文场景基本够用但如果希望在短文本上有更好效果可以显式指定 token_pattern 来保留中文上下文特征。另一个值得调整的点是 ngram_range默认值 (1, 1) 只提取单个词改成 (1, 2) 后可以把相邻的两个词当成一个特征比如“环境 差”和“环境 好”就能被区分得更开。需要留意的是ngram_range 提大会成倍增加特征维度在数据集不大的情况下反而可能引入噪声所以这里并不建议一上来就盲目调大。3.3 在 Django View 中加载模型并返回判断结果模型训练完毕以后Django 项目需要做的事情非常纯粹在视图函数里加载 pkl 文件对用户输入做相同流程的分词和向量化然后调用 predict 得到结果最后把结果返回给模板展示。因为训练脚本已经保存了完整的向量化器分类接口不需要重新实现 TfidfVectorizer 逻辑只需要复用同一个 vectorizer.pkl。# sentiment/views.py import jieba import joblib from django.shortcuts import render from .models import SentimentRecord model joblib.load(sentiment_model.pkl) vectorizer joblib.load(vectorizer.pkl) def classify_text(request): if request.method POST: content request.POST.get(content, ).strip() if not content: return render(request, text_classify.html, {error: 请输入文本内容}) words .join(jieba.cut(content)) vec vectorizer.transform([words]) predict model.predict(vec)[0] sentiment 积极 if predict 1 else 消极 SentimentRecord.objects.create( userrequest.user, content_textcontent, sentiment_resultsentiment, creatorrequest.user.username, ) return render(request, text_classify.html, { content: content, sentiment: sentiment, }) return render(request, text_classify.html)这个视图包含三个关键环节。第一个环节是文本预处理从 POST 请求中取到用户输入用 strip 去掉首尾空字符再用 jieba.cut 做分词注意这里分词方式必须和训练脚本完全一致否则向量特征对不上判断结果就会失控。第二个环节是模型预测把分词后的字符串交给 vectorizer.transform 转成向量再交给 model.predict返回结果是整数 1 或 0映射成“积极”“消极”展示给用户。第三个环节是记录入库每次判断完成后把内容、结果、创建人写进 SentimentRecord 表这样文本管理界面就有数据可以展示。还有一个容易被忽略的细节模型加载时机。上面代码把 joblib.load 放在模块顶层服务启动后只加载一次后续所有请求共享内存中的模型对象响应速度会快很多。如果放在视图函数内部每次加载输入一句话要等几秒钟才能出结果论文里描述“经过一段时间的响应”就是这种体验。不过这里也要注意训练脚本每次更新模型后必须重启 Django 服务进程才能让新模型生效这一点在调试时容易踩坑。4. 登录、文本管理、用户管理三个后台功能的 Django 实现4.1 登录模块与 Session 校验后台管理功能建立在登录基础之上Django 提供的 auth 模块可以大幅简化登录逻辑。教科书式做法是直接用 authenticate 和 login 两个内置函数完成认证与登录并在需要权限的视图上使用 login_required 装饰器做访问控制。from django.contrib import auth from django.shortcuts import render, redirect def login_view(request): if request.method POST: username request.POST.get(username, ) password request.POST.get(password, ) user auth.authenticate(usernameusername, passwordpassword) if user: auth.login(request, user) return redirect(index) return render(request, login.html, {error: 用户名或密码错误}) return render(request, login.html)这段代码的逻辑很直白authenticate 负责核对用户名和密码如果验证通过返回用户对象失败则返回 Noneauth.login 将用户状态写入 session后续请求 Django 就能识别当前登录用户。redirect 指向首页也就是论文里提到的管理员登录首页这里还可以顺手把用户信息写进 session方便其他页面读取。要注意的是密码字段在数据库中不能以明文存储创建管理员时应该使用 Django 提供的 set_password 方法处理。管理员登录首页里展示的统计数据通常包括当前系统中的文本数量、分类类别、用户数量以及年份信息。数据来源就是前面建好的 sentiment_record 表和 admin_user 表通过 ORM 的 count 方法聚合统计。左侧菜单栏包含首页、文本分类、文本管理、密码修改、用户信息查看等入口模板逻辑不复杂但需要注意菜单选中态的判断让用户知道当前处在哪个模块中。4.2 文本分类页面从表单提交到记录入库文本分类页面是整套系统里最核心的用户入口。用户在文本框中输入一句话点击开始分类按钮后端调用模型判断情绪并立刻把结果展示在同一页面上。表单提交时采用 POST 方式模板文件中的 form 标签里必须带上 Django 的 CSRF 令牌否则请求会被拦截具体细节在避坑清单中会展开。form methodpost action/classify/ {% csrf_token %} textarea namecontent rows4 placeholder请输入要判断的中文文本/textarea button typesubmit开始分类/button /form {% if sentiment %} p输入内容{{ content }}/p p情感判断{{ sentiment }}/p {% endif %}模板里有两个关键绑定namecontent 的值会被 POST 请求体发到后端视图函数通过 request.POST.get(content) 取出渲染结果用 {{ sentiment }} 和 {{ content }} 占位符输出。如果后端返回 error 字段页面上也应该有对应的错误提示容器。这里的重点是前后端字段名必须一致否则会出现输入了文本但后端取不到值的翻车情况。分类完成写入数据库的动作在视图函数里已经处理过这里需要说明的是记录的用户归属。表结构里 user 字段存的是当前登录用户的 IDcreator 存的是用户名。这样文本管理界面在展示记录时可以直接通过外键关联拿到用户信息也可以直接用 creator 字段显示创建者两个字段分别是逻辑关联和冗余展示后一种写法在简单管理系统中更直观减少一次表连接。4.3 文本管理与用户管理后台维护的两种典型写法文本管理界面需要把 sentiment_record 表里的所有记录以列表形式展示出来展示字段包括记录 ID、输入文本、机器判断结果、创建人并提供删除操作。论文截图里体现了管理员可以对某条信息进行删除这是后台管理模块中最常规的功能。def text_manage(request): records SentimentRecord.objects.all().order_by(-create_time) return render(request, text_manage.html, {records: records}) def delete_record(request, record_id): if request.method POST: SentimentRecord.objects.filter(idrecord_id).delete() return redirect(text_manage) return redirect(text_manage)这里的逻辑要点是删除操作用的是 POST 提交而不是 GET 请求。原因很简单GET 请求会暴露在浏览器地址栏和日志记录中还容易触发误删用 POST 方式配合表单按钮可以大大减少误操作概率。order_by(-create_time) 表示按创建时间倒序排列最新记录显示在最上方这个细节能明显提升用户体验。用户信息管理模块的处理方式和文本管理几乎一致。管理员可以查看用户列表列表中能显示用户名、手机号等信息支持的操作为修改和删除。Django 中可以直接对自带的 User 模型做查询如果需要展示更多字段可以建立 Profile 扩展表。这里要特别提醒一个操作边界删除用户前应该检查该用户是否有历史文本记录以免外键关联引发数据异常。比较稳妥的做法是使用逻辑删除给用户表加一个 is_active 字段将账号置为不可用而不是物理删除这样可以保留完整的历史数据链路对后续做数据分析也更有利。5. 避坑清单部署调试中常见的 5 个问题5.1 中文乱码建库时没指定 utf8mb4现象系统登录后输入中文文本分类结果页面正常显示但打开数据库管理工具或文本管理列表看到的内容变成一串问号或者乱码。原因创建数据库时使用了 MySQL 默认字符集在部分环境下默认是 latin1无法完整表达中文另一种情况是数据库字符集正确但连接时没有指定 charsetDjango 和 MySQL 之间传输编码不一致。解决建库时显式声明 utf8mb4配置 Django 数据库连接时在 OPTIONS 里加上 charset两个位置缺一个都可能出问题。已经建错库的话可以用 ALTER DATABASE sentiment_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 修复同时把存量表也做一次字符集转换。从那以后我每次初始化项目都会先在 SQL 里写好字符集再回头配置 Django 连接顺序反了很容易在后期才爆雷。5.2 启动报错Python 3 下找不到 MySQLdb 模块现象执行 python manage.py runserver 后控制台报 ModuleNotFoundError: No module named MySQLdbDjango 无法连接数据库。原因Django 通过 MySQLdb 模块连接 MySQL但 Python 3 环境中这个模块不是内置的需要安装第三方驱动。最常用的驱动是 mysqlclient但它依赖系统编译环境Windows 上经常因为缺少 MSVC 编译工具而安装失败。解决优先尝试 pip install mysqlclient如果安装失败就改用 PyMySQL。安装完成后在项目init.py 里加一段兼容代码把 PyMySQL 伪装成 MySQLdbimport pymysql pymysql.install_as_MySQLdb()这段代码必须在 Django 正式连接数据库之前执行通常放在项目包的init.py 里。要注意 PyMySQL 和 mysqlclient 不能并存二者同时安装可能导致驱动冲突。5.3 模型预测不准训练集太小且样本不均衡现象输入“环境太差了”这类明显消极的文本模型返回“积极”完全不符合常识。原因训练数据只有几条模型几乎没有学到情感特征只是记忆了训练样本中的孤立词汇。尤其在样本不均衡时积极类样本数量远超消极类模型会倾向把所有输入都猜测为数量占优的类别。解决先把训练集扩大到几百条甚至几千条保持积极和消极样本数量基本均衡。如果短期内没有足够标注数据可以退而求其次使用 SnowNLP 自带的预训练情感模型效果比几条样本强不少。人工检查模型效果时不要只挑自己设置过的句子测试随意找几条真实评论效果会更有参考价值。5.4 页面有结构无样式静态文件加载 404现象登录页能显示输入框和按钮但页面完全没有样式浏览器控制台里 CSS 文件返回 404。原因Django 开发服务器不会自动收集每个应用下的静态文件如果模板中引用的 CSS 路径和实际目录不匹配就会加载失败。更隐蔽的情况是 STATICFILES_DIRS 配置的是当前项目下的目录但实际文件放在应用目录下。解决在 settings.py 里设置 STATIC_URL 为 /static/并配置 STATICFILES_DIRS 指向实际静态文件目录。模板文件开头使用 {% load static %}引用时写 {% static css/login.css %} 而不是硬编码路径。部署环节再执行 python manage.py collectstatic把分散在各应用的静态文件统一收集起来。按照这个顺序配置静态文件基本不会再有幺蛾子。5.5 表单提交 403CSRF 令牌缺失现象点击登录或分类按钮页面显示 CSRF verification failed请求被拒绝执行。原因Django 默认启用 CSRF 防护机制所有 POST 表单都会校验 csrfmiddlewaretoken。模板中如果没有添加令牌字段Django 会判定请求不合法并返回 403。解决在每个 POST 表单的 form 标签内加上 {% csrf_token %}Django 渲染时会自动生成一个隐藏字段并写入 cookie提交时两者不一致会被拦截。如果使用的是 AJAX 请求则需要在发送前从 cookie 读取 csrftoken 并添加到请求头中。这个坑在开发早期遇到会让人一头雾水排查几分钟后基本都是同一个原因。6. 上线前先算清准确率验证方法与一个关键习惯6.1 准备留出法测试集先算准确率再谈效果模型在训练集上表现很好并不代表真实场景可用。稳妥的做法是把标注数据按 8:2 比例划分成训练集和测试集训练脚本完成后把测试集数据喂给模型统计准确率、精确率和召回率。这一步在答辩时非常重要因为评委很可能会问“你这个情感分类的准确率到底是多少”而不是只看页面演示效果。from sklearn.metrics import accuracy_score, precision_score, recall_score y_true [0, 1, 1, 0, 1, 0] y_pred [0, 1, 0, 0, 1, 1] print(准确率:, accuracy_score(y_true, y_pred)) print(精确率:, precision_score(y_true, y_pred)) print(召回率:, recall_score(y_true, y_pred))准确率表示预测正确的样本占总样本的比例精确率表示预测为积极类的样本中真正是积极类的占比召回率表示真实积极类样本中被成功找出来的占比。文本情感分类中消极样本往往较少只看准确率容易掩盖问题把这三个指标一起看才能更客观地判断模型是否真的可用。6.2 扩展思路从朴素贝叶斯到更复杂的分类器如果测试集上的准确率不够理想优先排查数据集质量而不是急着换模型。词数稀疏、情感词被否定词反转、训练样本覆盖的场景过窄这些因素都会让准确率上不去。数据规模扩充到几千条以后再考虑用支持向量机、逻辑回归或者 fastText 替换朴素贝叶斯效果通常会有明显提升。替换算法的成本其实很低因为分词和向量化两个环节不用改动只需要把训练代码中的分类器换掉重新训练模型文件即可。做完这些最后想分享一个习惯那以后我每次拿到这类带模型的 Django 项目都强制自己先跑一遍训练脚本和测试评测再把模型接进视图绝不跳过评测直接演示。文本情感系统最大的风险点不在页面写得好不好而在模型本身到底能不能稳定判断提前算清楚准确率和召回率既是对用户负责也能避免答辩现场翻车。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑