资讯动态

疫情舆情两极情感分析:毕业设计资源与机器学习实战

发布时间:2026/10/9 8:14:55 来源:尧图企业网站定制
简介本资源面向希望掌握中文情感分析实战的开发者与高年级学生聚焦疫情期间人民日报与微博话题数据的两极情感倾向判定。内容以机器学习方法为主线与基于情感词典的传统方案形成对照帮助读者理解语义表达丰富性下词典匹配的误差来源以及训练语料质量对模型性能的关键影响。压缩包共约2000个文件整体87.47MB以txt文本语料为主体辅以json、csv结构化数据、html关键词页面、pkl模型文件、py源码脚本及png图表并附论文文档与pdf说明覆盖从数据获取、预处理到建模评估的完整链路。目前已有433人学习下载。读者可据此复现一套可运行的情感分析流程获取原始语料、特征工程脚本与模型持久化文件并借助论文梳理实验设计与结论适合作为课程设计、毕业设计或相关课题的参考方案。1. 疫情舆情两极情感分析一份能跑通的毕业设计资源拆解2020 年那波疫情数据现在回头看是中文 NLP 里少有的「高密度、强情绪、跨平台」语料。微博上情绪外放、用词碎片化人民日报评论区则相对克制、书面化两个源放一起做情感极性分析天然就有对比价值。这份资源就是围绕这个场景打包的一份毕业论文文档加上 Python 项目源码和数据数据文件按日期切分从 2020-02-23 到 2020-03-14 共 10 个 keywords.html覆盖了疫情爆发初期情绪波动最剧烈的三周。它解决的不是「情感分析是什么」这种科普问题而是给你一套已经跑通的二分类流程——把微博和人民日报的文本清洗、分词、向量化再用机器学习模型判正负。适合正在做毕业设计、课程项目或者想拿真实中文语料练手的人。下面我按「资源里有什么 → 怎么复现 → 坑在哪 → 怎么调优」的顺序拆一遍。2. 资源结构与技术选型为什么是机器学习而不是情感词典2.1 文件清单与数据组织方式拿到压缩包先别急着跑代码把目录结构看清楚能省很多事。这份资源的文件组织不算复杂但有几个命名容易让人懵。文件/目录类型说明毕业论文.docx文档完整论文含方法论述、实验设计和结果分析2020-02-23-keywords.html数据按日期抓取的关键词话题页HTML 格式2020-02-26 ~ 2020-03-14-keywords.html数据同上共 10 个日期文件Python 源码代码数据清洗、分词、特征提取、模型训练与评估标注数据数据用于训练和测试的带极性标签语料HTML 文件是原始抓取结果不是清洗好的 CSV。这意味着你拿到手的第一件事不是train_test_split而是解析 HTML、抽正文、去标签。日期跨度从 2 月 23 日到 3 月 14 日正好覆盖了疫情初期舆论从恐慌到逐步理性的一个完整波段做时间序列上的情感趋势观察也有素材。2.2 情感词典 vs 机器学习选型理由要讲清楚论文里花了不少篇幅对比两类方法这个对比不是凑字数它直接决定了你后面代码怎么写。基于情感词典的做法是准备一个正负情感词表常见的有知网 Hownet、台大 NTUSD哈工大《同义词词林》可以用来做扩充然后对文本里的词逐个查表打分累加得到情感倾向。优点是逻辑透明、不需要训练数据、跑起来快。缺点在中文里特别明显——语义表达的丰富性会让词典匹配产生很大误差。「封城」这个词在疫情语境下是中性甚至带防控意味的但词典可能把它归到负面「清零」在不同时间点情感色彩完全不同。词典是静态的语境是动态的。机器学习方法不深入到语法层面它学的是「什么样的词组合在一起倾向于什么标签」。精确度更高但对训练集语料质量依赖很重。如果训练语料针对性不强——比如拿电商评论训练的模型去判疫情舆情——性能会断崖式下跌。这份资源的价值就在于它提供了针对疫情话题的标注语料这是词典方法给不了的。提示如果你只是想快速出一个 baseline词典方法半天能跑通但如果论文要求「方法有对比实验」机器学习这条线必须走通否则实验章节撑不起来。2.3 从 HTML 到可训练数据清洗流程拆解原始 HTML 不能直接喂给模型中间要过几道工序。我一般按这个顺序走import re from bs4 import BeautifulSoup import jieba def parse_html(filepath): 解析单个 keywords.html抽取正文文本 with open(filepath, r, encodingutf-8) as f: soup BeautifulSoup(f.read(), html.parser) # 去掉 script 和 style它们不是正文 for tag in soup([script, style]): tag.decompose() text soup.get_text(separator\n) # 按行切分后去掉空行和纯符号行 lines [ln.strip() for ln in text.split(\n) if ln.strip()] return lines def clean_text(line): 单行清洗去 URL、去 、去话题标签符号但保留话题词 line re.sub(rhttp[s]?://\S, , line) # 去链接 line re.sub(r[\w\u4e00-\u9fa5], , line) # 去 用户 line re.sub(r#(.?)#, r\1, line) # #话题# 保留话题词 line re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9。、], , line) return line.strip() def segment(lines): 结巴分词过滤单字和停用词 stopwords set(open(stopwords.txt, encodingutf-8).read().split()) result [] for ln in lines: words jieba.lcut(ln) words [w for w in words if len(w) 1 and w not in stopwords] if words: result.append( .join(words)) return resultparse_html用 BeautifulSoup 把 HTML 转成纯文本行decompose()先干掉脚本和样式块避免把 JS 代码当成正文。clean_text里几个正则的顺序有讲究先去链接再去 最后统一过滤特殊字符#话题#的处理是保留话题词本身、去掉井号因为话题词往往携带关键情感信息。segment用结巴分词后过滤单字和停用词单字在情感分析里噪声大于信号停用词表需要自己根据语料补充——疫情场景下「确诊」「新增」这类词不能当停用词删掉。2.4 特征工程与模型训练TF-IDF 加朴素贝叶斯的组合清洗完的数据要转成模型能吃的数值特征。中文短文本情感分析里TF-IDF 加线性模型是性价比最高的起点。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report # 假设 texts 是清洗后的文本列表labels 是 0/1 极性标签 X_train, X_test, y_train, y_test train_test_split( texts, labels, test_size0.2, random_state42, stratifylabels ) vectorizer TfidfVectorizer( max_features5000, # 控制特征维度防止稀疏爆炸 ngram_range(1, 2), # 一元二元捕捉「不好」这类组合 min_df2, # 出现少于2次的词直接丢 max_df0.9 # 出现在90%以上文档里的词没有区分度 ) X_train_vec vectorizer.fit_transform(X_train) X_test_vec vectorizer.transform(X_test) # 朴素贝叶斯快适合做 baseline nb MultinomialNB(alpha0.1) nb.fit(X_train_vec, y_train) print(classification_report(y_test, nb.predict(X_test_vec))) # 逻辑回归通常比 NB 稳系数可解释 lr LogisticRegression(C1.0, max_iter1000) lr.fit(X_train_vec, y_train) print(classification_report(y_test, lr.predict(X_test_vec)))TfidfVectorizer的几个参数直接决定模型上限。max_features5000是经验值语料规模不大时够用太大反而引入噪声。ngram_range(1,2)让「不」和「好」能组合成「不 好」这个二元特征对情感极性判断很关键。min_df2过滤掉只出现一次的词这些词大概率是噪声或拼写错误。max_df0.9去掉几乎每篇都有的词它们没有区分能力。模型方面MultinomialNB的alpha是平滑系数设 0.1 比默认的 1.0 在短文本上通常更好因为默认平滑太强会抹掉稀有词的信息。LogisticRegression的C是正则强度C 越大越容易过拟合疫情语料量不大时建议从 0.5 到 1.0 之间试。两个模型都跑一遍做对比论文里的实验章节就有东西写了。3. 避坑与常见问题跑这份资源时最容易翻车的五个地方3.1 编码问题导致 HTML 解析出乱码现象parse_html读出来的文本全是\xe4\xbd\xa0这种字节串或者中文变成问号。原因HTML 文件的编码不一定是 UTF-82020 年抓的数据有可能是 GBK 或 GB2312。用open(filepath, r, encodingutf-8)强行读会报错或乱码。解决先探测编码再读。用chardet库检测或者直接试几种编码import chardet def read_html_safe(filepath): with open(filepath, rb) as f: raw f.read() enc chardet.detect(raw)[encoding] return raw.decode(enc or utf-8, errorsignore)errorsignore是兜底遇到无法解码的字节直接跳过比让程序崩掉强。3.2 分词后单字过多导致特征稀疏现象TF-IDF 矩阵维度爆炸模型训练慢且准确率上不去。原因结巴默认分词会把「的」「了」「是」这类单字也切出来如果没过滤5000 个特征里一大半是噪声。解决在segment函数里加len(w) 1过滤同时维护一份针对疫情语料的停用词表。注意「不」「没」这类否定词不能删它们对情感极性判断至关重要。我一般会把否定词单独存一个列表在过滤时白名单放行。3.3 训练集和测试集分布不一致现象训练时准确率 95%测试时掉到 70%。原因train_test_split默认随机切分如果数据里微博和人民日报的样本混在一起可能训练集里微博多、测试集里人民日报多两个平台的用词风格差异大模型泛化不了。解决用stratify参数按标签分层如果平台差异明显还可以按平台分别切分后再合并。更稳妥的做法是留出一个平台的数据做跨域测试看模型在另一个平台上的表现——这个结果写进论文反而更有说服力。3.4 标签定义模糊导致模型学偏现象模型把明显负面的文本判成正或者反过来。原因两极情感分析的「正/负」边界在疫情语境下不好划。「封城」是负还是中性「新增为零」是正还是中性如果标注时标准不统一模型学到的就是噪声。解决回看论文里的标注规范确认标签定义。如果原文没写清楚自己重新定义一套规则明确哪些词算正面如「治愈」「清零」「加油」哪些算负面如「恐慌」「死亡」「封城」边界情况单独讨论。标注一致性比标注数量更重要。3.5 日期文件读取顺序错乱导致趋势分析出错现象做情感随时间变化的折线图时曲线跳来跳去没有规律。原因文件名是2020-02-23这种格式但用os.listdir()读出来的顺序是文件系统顺序不是日期顺序。2 月 23 日可能排在 3 月 5 日后面。解决读取后按文件名排序import os files [f for f in os.listdir(data_dir) if f.endswith(.html)] files.sort(keylambda x: x.split(-keywords)[0]) # 按日期字符串排序日期格式是YYYY-MM-DD字符串排序就是时间排序不用转 datetime。4. 模型调优与效果验证从能跑到跑好4.1 交叉验证代替单次切分单次train_test_split的结果波动大换一个random_state可能差好几个点。用 K 折交叉验证看模型的稳定表现from sklearn.model_selection import cross_val_score from sklearn.pipeline import Pipeline pipeline Pipeline([ (tfidf, TfidfVectorizer(max_features5000, ngram_range(1, 2), min_df2)), (clf, LogisticRegression(C1.0, max_iter1000)) ]) scores cross_val_score(pipeline, texts, labels, cv5, scoringf1) print(fF1: {scores.mean():.3f} (/- {scores.std():.3f}))用Pipeline把向量化和分类器串起来交叉验证时 TF-IDF 只在训练折上 fit避免数据泄漏。scoringf1比 accuracy 更合适如果正负样本不均衡accuracy 会被多数类带偏。4.2 看混淆矩阵找问题准确率只是一个数混淆矩阵能告诉你模型错在哪from sklearn.metrics import confusion_matrix import seaborn as sns import matplotlib.pyplot as plt cm confusion_matrix(y_test, lr.predict(X_test_vec)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabels[负, 正], yticklabels[负, 正]) plt.xlabel(预测) plt.ylabel(真实) plt.show()如果负面样本被大量判成正说明模型对负面特征学得不够可能是负面语料太少或者负面表达太隐晦。反过来如果正面被判负检查一下是不是把中性表述误标成了正面。4.3 特征权重分析模型到底学到了什么逻辑回归的系数可以直接看哪些词对极性判断贡献最大import numpy as np feature_names vectorizer.get_feature_names_out() coefs lr.coef_[0] # 正面权重最高的 20 个词 top_pos np.argsort(coefs)[-20:] # 负面权重最高的 20 个词 top_neg np.argsort(coefs)[:20] print(正面特征:, [feature_names[i] for i in top_pos]) print(负面特征:, [feature_names[i] for i in top_neg])这个输出直接可以放进论文的特征分析章节。如果正面特征里出现「死亡」「确诊」这种明显负面的词说明标注或清洗有问题得回头查。我一般会把这个列表打印出来人工过一遍比看准确率更能发现问题。4.4 跨平台验证微博模型判人民日报准不准这份资源最大的特点是两个平台的数据都有。一个值得做的实验是用微博数据训练在人民日报数据上测试看跨域性能掉多少。# 假设 weibo_texts/weibo_labels 和 rmrb_texts/rmrb_labels 已分别准备好 pipeline.fit(weibo_texts, weibo_labels) cross_pred pipeline.predict(rmrb_texts) print(classification_report(rmrb_labels, cross_pred))如果 F1 掉得厉害说明两个平台的表达差异大模型没有学到通用的情感特征。这个结果本身就是一个有价值的发现可以在论文里讨论「平台语言风格对情感分析模型泛化能力的影响」。反过来如果跨域表现还不错说明疫情话题下情感表达有一定共性这也是一个结论。4.5 一个容易忽略的细节时间窗口对结果的影响数据按日期切分不同日期的情感分布可能完全不同。2 月底可能是恐慌高峰3 月中旬可能趋于平稳。如果直接把所有日期混在一起训练模型学到的是平均情感看不出时间趋势。我的习惯是先按日期分组统计正负比例画一条时间线确认数据里确实有趋势变化再决定要不要在特征里加入日期相关的特征比如「距 1 月 23 日的天数」。如果趋势明显但不加入时间特征模型在早期数据上的表现会明显差于晚期数据这个偏差在写论文时得解释清楚。从那以后我每次拿到带时间戳的语料都会先画一条情感均值的时间线再动手建模——这条线能告诉你数据里有没有「故事」比直接跑模型有意思得多。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑