新闻详情

新闻详情

首页 / 资讯中心 / 详情

机器学习文本情感分类系统实战:从语料清洗到Flask部署

发布时间:2026/9/28 1:48:19来源:尧图网络
机器学习文本情感分类系统实战:从语料清洗到Flask部署
简介面向毕业设计、课程设计与期末大作业场景提供一套基于机器学习的文本情感分类完整工程适合具备一定编程基础、希望系统完成分类实验或快速搭建演示系统的学习者。项目覆盖kNN、决策树、朴素贝叶斯、SVM、MLP、CNN、LSTM等常见算法的可运行实现并包含从数据预处理、特征表示到训练评估的完整流程。压缩包共18个文件以7个Python脚本、4个模型文件、3个H5权重为主辅以训练/测试文本、README说明和Git配置整体约65.09MB目录划分便于按算法对照查看。目前已有38人学习浏览。通过代码与已训练模型可直接复现多种情感分类器效果也能在此基础上调整参数、更换数据集为课程报告或毕业设计提供扎实的实践支撑。1. 机器学习文本情感分类系统把课设、毕设和期末大作业做成能演示的项目做机器学习课程设计或期末大作业最怕的不是讲不清算法原理而是拿到一个文本情感分类系统却跑不起来演示环节只能对着 PPT 干讲。这份基于机器学习的文本情感分类系统把“原始评论文本 → 清洗切词 → 特征向量 → 分类模型 → 推理演示”整条人工智能应用流程串起来了是国内高校课设、毕设里最常见也最好答辩的项目形态。它能帮你省掉从零搭系统最耗时的三件事语料怎么处理、模型怎么选怎么调、训练完怎么保存和演示。适合正在做期末大作业和毕业设计选题的同学也适合想快速在本地复现一个完整机器学习项目流程的从业者。下面按本地复现顺序把每一段可执行的步骤和关键参数拆开讲。2. 语料清洗与切词先摸清数据底数再动手建训练集不管后面选哪种机器学习算法第一步永远是处理语料。文本情感分类系统的原始数据形态一般是正面和负面两个目录每个目录下按编号放了一堆 txt 文件。这章先把数据底数摸清再完成清洗、切词和数据集划分这三步做完你才拥有真正能喂给模型的样本。2.1 先摸清语料底数标签分布、样本量与平均长度动手训练之前我建议你花五分钟回答三个问题一共多少条样本、正负比例是否均衡、单条文本平均多长。这三个数字决定后面所有参数——样本太少要考虑扩充数据或做数据增强正负不均衡要动class_weight文本太长要截断、太短要过滤。下面的脚本就是干这个的from pathlib import Path data_dir Path(data/comment) for label_name in [pos, neg]: label_dir data_dir / label_name files list(label_dir.glob(*.txt)) lengths [len(f.read_text(encodingutf-8)) for f in files] print(f{label_name}: {len(files)} 条, 平均长度 {sum(lengths) / len(lengths):.1f})这段代码用glob(*.txt)把目录下所有 txt 文件列出来read_text必须指定encodingutf-8否则在 Windows 上大概率踩编码坑。平均长度如果只有几十个字说明是短文本后面TfidfVectorizer的ngram_range建议直接开到(1, 2)如果是几千字的长文本要做截断处理建模时只取前 200 到 300 字。另外说一句经验统计脚本和训练脚本最好共用data_dir这个路径常量别在代码里散落一堆绝对路径。课设项目打包换机器时最烦的就是到处找写死的路径去改。2.2 清洗、切词与停用词保留情感词丢掉干扰词中文切词和英文最大的区别在于没有天然空格常见做法是 jieba 精确模式配合停用词表再挂一个领域用户词典。像“拉胯”“踩雷”“种草”这类网络词直接写进userdict.txt否则会被拆成单字情感信息就丢了。下面是一份可以直接用的清洗和切词函数import re import jieba def clean_text(raw: str) - str: text re.sub(r[^], , raw) # 去 HTML 标签 text re.sub(rhttps?://\S|www\.\S, , text) # 去链接 text re.sub(r\d, , text) # 去数字 return re.sub(r\s, , text) # 去空白 jieba.load_userdict(userdict.txt) with open(stopwords.txt, encodingutf-8) as f: stopwords {line.strip() for line in f} def cut_words(text: str) - list: words jieba.lcut(clean_text(text), cut_allFalse) return [w for w in words if w not in stopwords and len(w) 1]clean_text里我去掉了 HTML 标签、链接、数字和空白这些内容对情感倾向贡献很小。jieba.lcut的cut_allFalse是精确模式不会把“不错”切成“不错/错”这种碎片。最后一行len(w) 1会把“好”“差”这类单字情感词也过滤掉所以我在构造停用词表时会把这两个字单独挑出来保留——过滤单字和过滤停用词是两件事不能用一个条件一刀切。stopwords.txt每行一个词编码必须是 UTF-8网上能直接找到哈工大停用词表做底子再往里追加领域词。注意别把文件存成带 BOM 的格式否则第一个词前面会藏一个\ufeff字符匹配永远失败这是切词阶段最容易翻车的小坑。2.3 打标签与训练集划分先划分再 fit顺序错了全是假高分接下来给每条样本打标签并划分训练集。这里最关键的纪律划分必须先于任何特征统计TfidfVectorizer的 fit 只能看到训练集。清洗和切词是逐条独立的操作放在划分之前没问题但凡是涉及整个数据集统计信息的操作比如计算词表、IDF 值、均值方差一律放到划分之后。from sklearn.model_selection import train_test_split X_texts, y [], [] for label, name in [(1, pos), (0, neg)]: for f in (data_dir / name).glob(*.txt): X_texts.append(clean_text(f.read_text(encodingutf-8))) y.append(label) X_train, X_test, y_train, y_test train_test_split( X_texts, y, test_size0.2, random_state42, stratifyy ) X_train_words [ .join(cut_words(t)) for t in X_train] X_test_words [ .join(cut_words(t)) for t in X_test]stratifyy会让正负样本在训练集和测试集中保持相同比例避免恰好把某一类全分到测试集里。random_state42固定随机种子不然每次跑划分结果都不一样后面网格搜索的结果也没法复现。最后两行把切词结果用空格拼回字符串这是TfidfVectorizer的标准输入格式。提示先划分原始文本再对训练集做特征提取的 fit这是文本分类防数据泄漏的核心操作。顺序错了交叉验证分数再高都不能信。3. 特征表示与模型选型TF-IDF、Word2Vec 与两类分类器的对比实战特征怎么造决定了模型的上限。文本情感分类最经典的特征表示还是 TF-IDF尤其面对几千到几万条的中文短文本。这章先讲 TF-IDF 参数怎么设再用 Word2Vec 做一个对照实验最后用混淆矩阵和 F1-score 决定哪个模型进最终系统。3.1 TF-IDF 的四个关键参数max_features、ngram_range、min_df 与 sublinear_tfTF-IDF 的原理可以一句话讲清一个词在当前文档里出现次数越多越重要TF但在越多文档里都出现就越没区分度IDF 会拉低它的权重。中文短文本情感分类我一般用它做默认起点原因只有三个训练快、效果稳、参数直观。实际使用中真正影响结果的参数就四个from sklearn.feature_extraction.text import TfidfVectorizer vectorizer TfidfVectorizer( max_features5000, ngram_range(1, 2), min_df2, sublinear_tfTrue, ) X_train_vec vectorizer.fit_transform(X_train_words) X_test_vec vectorizer.transform(X_test_words)参数取值作用max_features5000只保留文档频率靠前的 5000 个特征控制向量维度ngram_range(1, 2)同时保留单词和双词“不/错”和“不错”都能进特征min_df2去掉只在一条评论里出现过的词减少噪声sublinear_tfTrue词频取对数压缩抑制“的”“了”这类高频词注意fit_transform只在训练集上调用测试集只走transform。因为fit在统计整个词表和 IDF如果测试集也参与统计模型在训练阶段就看到了测试集信息这就是数据泄漏。很多人第一版代码准确率虚高问题基本都出在这一行。3.2 自训练 Word2Vec 做对照均值句向量为什么只能当 baseline如果课设要求做算法对比常见做法是补一个 Word2Vec 平均句向量。直接在训练语料上用 gensim 训练词向量再把一句话里所有词的向量取均值作为这句话的向量表示。这么做会丢掉词序和词的重要程度所以效果一般不如 TF-IDF但作为对照实验足够有说服力。from gensim.models import Word2Vec import numpy as np train_word_list [t.split() for t in X_train_words] w2v Word2Vec( sentencestrain_word_list, vector_size128, window5, min_count2, workers4, seed42, ) def sentence_vec(words: list) - list: vecs [w2v.wv[w] for w in words if w in w2v.wv] return list(np.mean(vecs, axis0)) if vecs else [0.0] * 128 X_train_w2v np.array([sentence_vec(w) for w in train_word_list]) X_test_w2v np.array([sentence_vec(w.split()) for w in X_test_words])vector_size128是句向量维度语料小就开小一点太大训练慢而且容易过拟合。min_count2过滤只在极少数评论里出现的生僻词window5表示上下文窗口大小。最后用零向量兜底空句子否则np.mean在空列表上会直接报 nan。这里用的是自己语料现训的小词向量和网上预训练词向量差距不小课设报告里如实写“Word2Vec 均值弱于 TF-IDF”就行不必强行调优。3.3 用混淆矩阵和 F1-score 定稿别让准确率骗了你模型选型这一步直接按对比实验结论定稿。在多数中文短评数据上LinearSVC TF-IDF往往比朴素贝叶斯略好训练速度也快朴素贝叶斯作为 baseline 写进报告更稳妥。到底选哪个以你自己数据上的混淆矩阵为准别听别人拍脑袋。from sklearn.naive_bayes import MultinomialNB from sklearn.svm import LinearSVC from sklearn.metrics import classification_report, confusion_matrix nb_model MultinomialNB(alpha0.5).fit(X_train_vec, y_train) svc_model LinearSVC(max_iter2000).fit(X_train_vec, y_train) for name, model in [(MultinomialNB, nb_model), (LinearSVC, svc_model)]: y_pred model.predict(X_test_vec) print(name) print(classification_report(y_test, y_pred, target_names[neg, pos], digits3)) print(confusion_matrix(y_test, y_pred))alpha0.5是拉普拉斯平滑系数主要影响小样本词的概率估计。看报告时重点看 neg 这一行的 recall——如果明显低于 precision说明模型把大量差评学成了好评这是情感分类最常见的偏置。这时先别急着换模型回检查语料里有没有反讽和否定结构比调参有效得多。课设答辩时老师一般会追问“为什么选 SVM 不用朴素贝叶斯”把这份分类报告打印出来贴在报告里比背八股文管用。4. 训练与调参Pipeline、网格搜索与模型持久化的完整流程对比实验做完最终模型定为LinearSVC TF-IDF。接下来把特征器和分类器绑成一条 Pipeline做网格搜索调参、模型持久化最后写一个可直接用的预测函数。这也是从“训练出模型”到“交付能用系统”的关键一步。4.1 先把特征器和分类器绑成 Pipeline防泄漏也防预测时丢配件Pipeline 在这里的真正作用有两个防止数据泄漏、防止丢失配件。很多同学训练完只把分类器存下来测试时重新建一个TfidfVectorizer重新 fit维度对不上直接报错。把特征器和分类器绑定成一条链路fit、predict、保存三件事就统一了。from sklearn.pipeline import Pipeline from sklearn.svm import LinearSVC pipeline Pipeline([ (tfidf, TfidfVectorizer(max_features5000, ngram_range(1, 2), min_df2, sublinear_tfTrue)), (clf, LinearSVC(C1.0, max_iter2000)), ]) pipeline.fit(X_train_words, y_train)LinearSVC的C是正则化强度值越小对误分类的惩罚越轻模型越平滑。max_iter2000是我建议的起步值默认的 1000 在中文稀疏高维特征上经常不收敛训练时会刷一堆ConvergenceWarning虽然不影响最终结果好看但答辩时被问到底气不足。4.2 网格搜索怎么配参数网格设计比搜索本身更花时间网格搜索本身是暴力遍历真正花时间的是参数网格怎么设计。我在这个项目上常用的网格组合如下from sklearn.model_selection import GridSearchCV param_grid { tfidf__ngram_range: [(1, 1), (1, 2)], tfidf__max_features: [3000, 5000], clf__C: [0.1, 1.0, 10.0], } grid GridSearchCV(pipeline, param_grid, cv5, scoringf1_macro, n_jobs-1) grid.fit(X_train_words, y_train) print(grid.best_params_) print(grid.best_score_)参数名里用双下划线__连接 pipeline 步名和参数名这是 sklearn 的固定写法。cv5表示五折交叉验证scoringf1_macro表示对正负两类的 F1 取平均比准确率更能反映模型对少数的判断能力。n_jobs-1用满 CPU 所有核几万条语料大概跑几分钟。防止内存爆炸的技巧先固定ngram_range(1, 2)调C拿到结果后再放开 ngram不要一上来全组合一起跑。语料规模建议网格小于 5000 条ngram_range用(1, 1)和(1, 2)C只搜[1.0]5000 到 5 万条ngram_range(1, 2)max_features搜[3000, 5000]C搜[0.1, 1.0, 10.0]大于 5 万条先用min_df5降维再套上面的中语料网格4.3 模型持久化只保存 pipeline别分开存特征器训练结束后最重要的动作是把完整 pipeline 存盘。不要单独 dump 分类器要 dump 整个grid.best_estimator_因为里面同时包含了训练好的 TF-IDF 特征器。加载回来直接预测不会再出现维度对不上。import joblib best_model grid.best_estimator_ joblib.dump(best_model, models/sentiment_model.pkl)训练完成后你手上应该有一套这样的文件清单文件内容谁在使用models/sentiment_model.pkl完整 pipelineTF-IDF LinearSVC预测脚本、演示程序userdict.txt自定义用户词典切词阶段stopwords.txt停用词表切词阶段data/comment原始正负语料训练脚本4.4 预测函数没有 predict_proba 时怎么算置信度模型存好后写一个单条文本的预测函数供后续演示和接口调用。注意LinearSVC本身没有predict_proba只有decision_function输出的是样本点到超平面的距离。我们取符号定类别取绝对值当置信度。def predict_one(text: str) - dict: words .join(cut_words(text)) score best_model.decision_function([words])[0] label pos if score 0 else neg return {label: label, score: abs(float(score)), text: text}[words]外面套一层列表因为decision_function接收的是样本列表哪怕只有一个样本也要保持二维结构。如果答辩老师问概率输出如实说这里用距离代替概率即可也可以包一层CalibratedClassifierCV得到真正的概率但会牺牲一点准确率课设一般不推荐。写好之后拿一条训练集里没出现过的新评论跑一遍确认返回的 label 符合直觉再继续。5. 常见问题与避坑编码报错、数据泄漏与情感偏置的排障记录下面这五条是我在复现和调试这类系统时最容易翻车的点按现象、原因、解决列出来。前三条是环境与编码类后两条是效果与数据类覆盖了从“跑不起来”到“跑起来但不准”的常见故障。5.1 环境与编码类UnicodeDecodeError、维度报错与不收敛警告现象直接执行open(data/comment/pos/1.txt).read()抛UnicodeDecodeError或者在 Windows 命令行里打印评论全是乱码。原因语料文件是 UTF-8 编码而 Windows 下 Python 默认按 GBK/cp936 解码两边对不上。解决所有文件读写统一显式指定encodingutf-8。更稳的是写一个带兜底的加载函数def load_text(path: Path) - str: try: return path.read_text(encodingutf-8) except UnicodeDecodeError: return path.read_text(encodinggbk, errorsignore)GBK 只是兜底errorsignore让个别坏字符不会打断整个训练脚本。如果两种编码都解不开说明文件本身已经损坏别硬解回源头重新导出。现象重新打开项目joblib.load之后对新文本预测报shape mismatch维度不一致。原因保存的是clf而不是完整 pipeline。TfidfVectorizer重新 fit 后词表变了特征维度对不上。解决保存整个grid.best_estimator_加载后直接用。这是最典型的“我明明保存了模型为什么不能用”的翻车现场十次有九次是只存了分类器。现象训练时刷一整屏ConvergenceWarning: Line search skipped模型结果看着正常但心里没底。原因LinearSVC默认max_iter1000在稀疏高维中文特征上经常不收敛。解决把max_iter提到 2000 到 3000tol从默认的 1e-4 放宽到 1e-3。课设够用不建议调太大训练慢且对效果提升有限。5.2 效果与数据类假高分、情感偏置与转折误判现象交叉验证准确率 0.98拿真实新评论一测效果完全不对。原因TfidfVectorizer在划分之前对整个数据集fit_transform或者停用词表是从测试集上统计来的。测试集的信息在训练阶段就泄漏进模型了。解决先train_test_split再对训练集fit_transform把向量器和分类器放同一条 pipeline交叉验证直接交给GridSearchCV的cv参数。这一步错位会让报告里所有准确率失真是数据类问题里危害最大的一种。现象混淆矩阵里 neg 的 recall 明显低差评被大量判成好评。原因一是训练语料正负不均衡二是“质量不错但服务拉胯”这类转折加反讽结构被切词拆散模型只看到前半句的“不错”三是单字情感词“好”“差”被len(w) 1过滤掉了。解决切词阶段保留“好”“差”等单字情感词但停用词表不要误伤它们ngram_range开到(1, 2)保留“不错”“但服务”这类双词组合效果还不够就设class_weightbalanced或补充更多差评样本。这套排查顺序比盲目换模型有效得多建议先打印混淆矩阵再决定动哪里。6. 进阶把模型包成一个约 30 行的 Flask 推理服务模型能预测单条文本后下一步就是给课设答辩做演示。常见做法是拿 Flask 包一个本地服务用命令行或网页发一条评论返回标签和置信度演示效果比 Jupyter Notebook 直观得多。下面是最小实现适合直接跑from flask import Flask, request, jsonify import joblib # 复用第 2 章写好的 cut_words 函数 from text_utils import cut_words app Flask(__name__) model joblib.load(models/sentiment_model.pkl) app.route(/predict, methods[POST]) def predict(): data request.get_json() text data.get(text, ) words .join(cut_words(text)) score model.decision_function([words])[0] return jsonify({label: pos if score 0 else neg, score: abs(float(score))}) if __name__ __main__: app.run(host127.0.0.1, port5000)这里只写一个接口演示足够。启动方式是在项目目录执行python app.py另开一个终端用curl -X POST http://127.0.0.1:5000/predict -H Content-Type: application/json -d {text:这家店太差劲了}验证。最容易漏的是cut_words所在模块和userdict.txt要在同一目录下接口层报“词典不存在”基本都是路径问题。进阶一点的做法是给 jieba 动态加词。比如用户新评论里出现“踩雷”这种词典外词不用改文件在服务启动时读一个extra_words.txt逐行jieba.add_word(w)即可。一个不被拆散的领域词对情感判别的提升往往比换模型更直接。交付前我习惯做一个快速冒烟测试从训练集里抽正负样本各 20 条跑一遍predict_one统计错误条数低于阈值才打包交付。从那以后我每次交付这类课设项目都会强制走一遍启动服务、发真实差评、看返回 label 的完整流程确认无误再压缩打包。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从 CHANGELOG.md 到插件指纹:WPScan 如何用变更日志精准识别 WordCamp Dashboard Widget 版本 2026/9/28 2:46:03

从 CHANGELOG.md 到插件指纹:WPScan 如何用变更日志精准识别 WordCamp Dashboard Widget 版本

网络安全漏洞扫描渗透测试应用安全CLI 【免费下载链接】wpscan WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contactwpscan.com 项目地址: ht…

阅读更多 →
区块链做网站避坑指南:3步省下50%冤枉钱 2026/9/28 2:46:03

区块链做网站避坑指南:3步省下50%冤枉钱

区块链做网站避坑指南:3步省下50%冤枉钱 找建站公司报价时,你是不是也心里直打鼓?对方张口就是“区块链概念”、“去中心化架构”,报价单上全是看不懂的术语,总价轻松破万甚至破十万。你明明只是想要个展示项目或者落地页,却担心自己不懂行被当成“…

阅读更多 →
Webiny React 依赖审计与现代化迁移指南:基于 dependencies/react.md 的完整解读 2026/9/28 2:46:03

Webiny React 依赖审计与现代化迁移指南:基于 dependencies/react.md 的完整解读

CMS后端前端 【免费下载链接】webiny-js Open-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at…

阅读更多 →
NoneBot2 中的 aiohttp 驱动适配器:纯客户端 HTTP/WebSocket 连接的实现与使用 2026/9/28 2:46:03

NoneBot2 中的 aiohttp 驱动适配器:纯客户端 HTTP/WebSocket 连接的实现与使用

后端即时通讯 【免费下载链接】nonebot2 跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python 项目地址: https://gitcode.com/gh_mirrors/no/nonebot2 点击查看 免费下载 NoneBot2 的 nonebot.drivers.aiohttp …

阅读更多 →
动物图像数据集清洗实战:从28K原始图到生产级训练数据 2026/9/28 2:46:03

动物图像数据集清洗实战:从28K原始图到生产级训练数据

简介:本资源是一个面向计算机视觉初学者与AI实践者的动物图像分类数据集,适用于图像识别、数据增强、模型训练与迁移学习等典型CV任务。数据集涵盖狗、猫、马、蜘蛛、蝴蝶、鸡、羊、牛、松鼠、大象共10类常见动物,总计约28,000张中等质量JPG/…

阅读更多 →
mGBA 贡献指南:从 Issue 提报到编码规范与 MPL 2.0 许可合规的完整实践 2026/9/28 2:45:56

mGBA 贡献指南:从 Issue 提报到编码规范与 MPL 2.0 许可合规的完整实践

游戏开发 【免费下载链接】mgba mGBA Game Boy Advance Emulator 项目地址: https://gitcode.com/gh_mirrors/mg/mgba 点击查看 免费下载 mGBA 是一个以 C 和 C 编写的 Game Boy Advance 模拟器,同时支持 Game Boy / Game Boy Color 与 Super Game Boy&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉