拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

中文谣言检测毕设完整代码包:从数据预处理到模型部署的七步流水线

中文谣言检测毕设完整代码包:从数据预处理到模型部署的七步流水线 简介这份本科毕业设计论文资源聚焦中文谣言检测面向自然语言处理方向的学生与研究者帮助理解如何用机器学习与深度学习构建谣言识别系统。压缩包共26个文件约4.93MB包含12个Python脚本、9个文本文件、4个JSON数据文件及1份说明文档脚本覆盖数据预处理、分词、停用词处理、特征工程、聚类与最终建模等环节文本与JSON文件则承载词表、标签、评分及数据集配置信息。论文围绕数据集构建、特征工程、朴素贝叶斯与SVM等模型训练评估、谣言演化分析及实时检测机制展开并讨论人工审核与自动检测结合的应对策略。已有125人学习适合作为毕业设计参考或NLP入门实践素材读者可据此梳理从数据清洗到模型落地的完整流程理解中文谣言识别的技术难点与实现思路。1. 中文谣言检测毕设拆包一份能跑通的完整流水线长什么样网上搜「中文谣言检测」出来的大多是论文摘要和算法综述真正能落地的代码包少得可怜。我拿到这个Chinese Rumor Recognition 本科毕业设计论文-中文谣言检测.zip的时候第一反应是——终于有人把从原始数据到最终模型的整条链路都打包了。它不是那种只丢一个模型文件让你自己猜预处理怎么做的半成品而是从1_wholedataProcess.py一路排到8_finalModel.py中间分词、去停用词、TF-IDF 特征、卡方特征选择、聚类、分类全都有独立脚本。适合两类人一是正在做中文谣言检测方向毕设、需要一份可复现基线的人二是想快速理解「中文文本分类从零到一」完整工程流程的 NLP 入门者。整个包的核心逻辑是先把原始 JSON 数据清洗成统一格式再走 jieba 分词和停用词过滤然后用 TF-IDF 做向量化接着用卡方检验筛特征最后分别跑聚类和无监督/有监督分类模型做对比。数据文件、中间产物、模型脚本分层清晰不是一锅粥。2. 数据流水线拆解从 data.json 到 tfidfPro.txt 的七步走2.1 原始数据长什么样为什么要先过一遍 wholedataProcess包里的data.json、data_1.json、data_2.json和alldata.json是不同阶段的原始数据快照。data.json是最初爬下来或收集的原始格式字段可能不统一alldata.json是合并后的全量数据。1_wholedataProcess.py干的事就是把这些 JSON 读进来统一成「文本 标签」的结构输出给后续脚本用。我一般会先看一眼alldata.json的结构再动手因为不同来源的谣言数据集字段名差异很大——有的用text有的用content有的标签是label有的是is_rumor。这个脚本里大概率做了字段映射和去重。如果你拿到的数据格式和脚本里写死的字段名对不上直接跑会报 KeyError这是第一个要改的地方。# 1_wholedataProcess.py 核心逻辑还原根据文件名和常见做法推断 import json def load_and_unify(path): with open(path, r, encodingutf-8) as f: raw json.load(f) unified [] for item in raw: # 常见做法是把不同来源的字段统一成 text 和 label text item.get(text) or item.get(content) or item.get(weibo_text, ) label item.get(label) or item.get(is_rumor) or item.get(tag, 0) if text.strip(): # 过滤空文本 unified.append({text: text.strip(), label: int(label)}) return unified data load_and_unify(alldata.json) with open(data_processed.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2)逻辑说明这段代码的核心是「字段归一化 空值过滤」。参数上注意encodingutf-8必须加中文 JSON 不加会乱码ensure_asciiFalse保证写回去的中文可读。如果你的数据里标签是字符串比如 rumor/non-rumor需要在这里加一层映射转成 0/1。2.2 分词、停用词、TF-IDF三个脚本的串联关系5_3_jiebaTM.py、5_2_stopwordTM.py、5_1_preTM.py这三个脚本从编号看是预处理阶段的三个步骤但执行顺序应该是5_1_preTM.py→5_3_jiebaTM.py→5_2_stopwordTM.py编号可能是按功能模块排的不是按执行顺序。5_1_preTM.py做基础清洗去 URL、去 、去特殊符号5_3_jiebaTM.py调 jieba 做分词5_2_stopwordTM.py加载stop_word.txt或stopword.txt过滤停用词。这里有个容易翻车的地方stop_word.txt和stopword.txt两个文件同时存在说明作者可能在不同阶段用了不同的停用词表或者一个是通用表一个是自定义表。跑之前先 diff 一下两个文件确认哪个是最终生效的。我一般会在分词后手动检查前 20 条结果看看有没有把「不是」「没有」这类否定词误删——谣言检测里否定词往往是强信号停用词表里如果包含它们准确率会掉得莫名其妙。import jieba def preprocess(text): # 基础清洗去 URL、、话题标签符号 import re text re.sub(rhttp\S, , text) text re.sub(r\S, , text) text re.sub(r#\S#, , text) return text.strip() def tokenize(text, stopwords): words jieba.lcut(text) return [w for w in words if w not in stopwords and len(w) 1] with open(stopword.txt, r, encodingutf-8) as f: stopwords set(line.strip() for line in f) sample 网传某地发生严重事故官方尚未回应 cleaned preprocess(sample) tokens tokenize(cleaned, stopwords) print(tokens) # [网传, 某地, 发生, 严重, 事故, 官方, 尚未, 回应]逻辑说明len(w) 1过滤单字这是中文文本分类的常见做法因为单字噪声大。但注意「谣」「假」这类单字在特定场景下有意义如果你的数据集里这类信号多可以把阈值改成 1再对比效果。停用词表加载用set而不是list查询复杂度从 O(n) 降到 O(1)数据量大时差别明显。2.3 TF-IDF 向量化和卡方特征选择tfidfPro.txt 和 scoreList.txt 怎么来的5_4_tfidfTM.py是 TF-IDF 向量化的核心脚本输出tfidfPro.txtTF-IDF 矩阵和scoreList.txt特征得分列表。6_1_preFM.py和6_2_logisticFM.py是特征选择阶段从文件名看preFM做特征预处理logisticFM可能用逻辑回归做特征重要性排序。3_2_featureProcess.py和3_1_rumorProcess.py则是更早的特征工程步骤。TF-IDF 在中文谣言检测里的作用是把每条文本转成一个高维稀疏向量每个维度对应一个词值是该词的 TF-IDF 权重。tfidfPro.txt大概率是稀疏矩阵的文本存储格式比如(row, col) value三元组。scoreList.txt则是每个特征的卡方得分用来做特征筛选——卡方检验衡量的是「词和类别之间的相关性」得分越高说明这个词对区分谣言和非谣言越有用。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.feature_selection import chi2 import numpy as np corpus [网传某地发生事故, 官方辟谣称消息不实, 紧急扩散寻人启事, 经核实该信息为谣言] labels [1, 0, 1, 0] # 1谣言, 0非谣言 vectorizer TfidfVectorizer(max_features5000, ngram_range(1, 2)) X vectorizer.fit_transform(corpus) chi_scores, p_values chi2(X, labels) # 按卡方得分排序取 top-k 特征 feature_names vectorizer.get_feature_names_out() sorted_idx np.argsort(chi_scores)[::-1] for i in sorted_idx[:5]: print(f{feature_names[i]}: chi2{chi_scores[i]:.2f})逻辑说明max_features5000控制词表大小太大容易过拟合太小会丢信息毕设场景下 30008000 是常见区间。ngram_range(1, 2)表示同时考虑单字词和双字词组合中文里「谣言」「辟谣」这类双字词信息量比单字大。卡方检验的p_values可以用来做显著性过滤一般保留 p 0.05 的特征。3. 模型脚本怎么跑聚类和分类两条线的实操路径3.1 7_clusterModel.py无监督聚类能验证什么7_clusterModel.py是聚类模型脚本大概率用的是 K-Means 或层次聚类。在谣言检测里聚类的价值不是直接做分类而是验证「谣言和非谣言在特征空间里是否天然可分」。如果聚类结果和真实标签的 ARI调整兰德指数很低说明你的特征工程有问题后面换什么分类器都白搭。跑这个脚本之前确保tfidfPro.txt已经生成且格式正确。常见做法是用sklearn.cluster.KMeansn_clusters 设成 2谣言/非谣言然后用adjusted_rand_score和normalized_mutual_info_score评估聚类质量。from sklearn.cluster import KMeans from sklearn.metrics import adjusted_rand_score, normalized_mutual_info_score import numpy as np # 假设 tfidfPro.txt 是稀疏矩阵的 npz 格式或从 pickle 加载 # 这里用随机数据模拟 X np.random.rand(100, 50) y_true np.random.randint(0, 2, 100) kmeans KMeans(n_clusters2, random_state42, n_init10) y_pred kmeans.fit_predict(X) print(fARI: {adjusted_rand_score(y_true, y_pred):.3f}) print(fNMI: {normalized_mutual_info_score(y_true, y_pred):.3f})逻辑说明n_init10让 K-Means 跑 10 次不同初始化取最优避免陷入局部最优。ARI 的取值范围是 [-1, 1]0 表示随机水平大于 0.3 才算有一定聚类结构。如果 ARI 接近 0先别急着调聚类参数回去检查 TF-IDF 矩阵是不是太稀疏或者停用词过滤过度了。3.2 8_finalModel.py最终分类模型的训练和评估8_finalModel.py是整个流水线的终点大概率集成了多个分类器做对比朴素贝叶斯、SVM、逻辑回归输出准确率、召回率、F1。从6_2_logisticFM.py的存在来看逻辑回归至少是其中一个基线。这个脚本的典型结构是加载特征矩阵 → 划分训练集/测试集 → 训练多个模型 → 输出评估指标。中文谣言检测数据集通常有类别不平衡问题非谣言远多于谣言所以 accuracy 会虚高必须看 F1 和召回率。from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import classification_report import numpy as np X np.random.rand(200, 100) y np.random.randint(0, 2, 200) X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42, stratifyy) models { LogisticRegression: LogisticRegression(max_iter1000, class_weightbalanced), SVM: SVC(kernellinear, class_weightbalanced), NaiveBayes: MultinomialNB() } for name, model in models.items(): model.fit(X_train, y_train) y_pred model.predict(X_test) print(f--- {name} ---) print(classification_report(y_test, y_pred, digits3))逻辑说明class_weightbalanced是处理不平衡数据的关键参数它让模型对少数类谣言的误分类惩罚更大。stratifyy保证训练集和测试集的类别比例一致避免随机划分导致测试集里谣言样本过少。max_iter1000是因为 TF-IDF 特征维度高逻辑回归默认的 100 次迭代经常不收敛。3.3 2_addtag.py 和 tagList.txt标签体系的设计逻辑2_addtag.py和tagList.txt是标签管理模块。tagList.txt存的是标签列表可能包括「谣言」「非谣言」「待定」等2_addtag.py负责给数据打标签。这个模块的存在说明作者的数据来源可能不止一个需要统一标签体系。我一般会在这个阶段做一件事统计每个标签的样本数如果某个标签少于总样本的 5%要么合并到相近类别要么在训练时用重采样处理。标签体系的设计直接决定了模型能学什么——如果标签只有「谣言/非谣言」二分类那模型学到的边界很粗如果有「政治谣言」「健康谣言」「社会谣言」等多级标签可以做层次分类但需要更多数据支撑。4. 避坑与排查跑这份代码时最容易翻车的五个地方4.1 文件路径写死导致 FileNotFoundError现象跑任何一个脚本都报FileNotFoundError: [Errno 2] No such file or directory: xxx.txt。原因毕设代码常见问题是作者在自己机器上用了绝对路径或者相对路径的层级和你的不一致。比如脚本里写的是open(data/tfidfPro.txt)但你解压后文件就在当前目录。解决全局搜一遍所有.py文件里的open(和read_csv、load调用把路径统一改成基于脚本所在目录的相对路径。我一般会在每个脚本开头加import os; os.chdir(os.path.dirname(os.path.abspath(__file__)))这样不管从哪个目录执行工作目录都是脚本所在目录。4.2 jieba 分词结果里混入大量空格和特殊符号现象分词后得到的 token 列表里有很多空字符串、单个标点、或者\u3000全角空格。原因原始文本里的不可见字符没清洗干净jieba 会把它们当成独立 token 返回。解决在分词后加一层过滤用re.match(r[\u4e00-\u9fa5a-zA-Z0-9], w)只保留中文、英文、数字开头的 token。另外strip()只能去首尾空白中间的全角空格要用replace(\u3000, )处理。4.3 TF-IDF 矩阵维度爆炸导致内存不够现象跑5_4_tfidfTM.py时内存飙升或者报MemoryError。原因如果没设max_featuresTF-IDF 会为每个出现过的词建一个维度中文词汇量大几万条文本就能产生几十万维的稀疏矩阵。解决在TfidfVectorizer里强制设max_features5000或10000同时开min_df2忽略出现次数少于 2 的词和max_df0.95忽略出现在 95% 以上文档里的词通常是停用词没滤干净。这三个参数一加矩阵大小能降一个数量级。4.4 类别不平衡导致模型全预测为多数类现象训练完模型accuracy 有 0.85但召回率只有 0.1混淆矩阵里少数类几乎全错。原因谣言样本远少于非谣言样本模型学会了「全猜非谣言」就能拿高准确率。解决三管齐下——class_weightbalanced、用 SMOTE 做训练集过采样、评估指标从 accuracy 换成 F1 和 AUC。如果用的是 SVMclass_weightbalanced效果最明显如果是朴素贝叶斯考虑用ComplementNB替代MultinomialNB它对不平衡数据更鲁棒。4.5 随机种子没固定导致每次跑结果都不一样现象同一个脚本跑两次准确率差 35 个百分点没法复现。原因train_test_split、KMeans、LogisticRegression等都有随机成分没设random_state就会每次不同。解决在所有涉及随机的函数里加random_state42包括train_test_split、KMeans、SVCprobabilityTrue时、RandomForest等。另外numpy和random的全局种子也建议在脚本开头设一下np.random.seed(42)和random.seed(42)。5. 进阶技巧用 scoreList.txt 做特征回溯和模型可解释性验证跑通整条流水线只是第一步真正让这份毕设代码产生价值的是用scoreList.txt做特征回溯。scoreList.txt里存的是每个特征的卡方得分你可以把它和tfidfPro.txt的维度对齐找出对分类贡献最大的 top-20 词然后人工检查这些词是否合理。具体做法加载scoreList.txt和 TF-IDF 的feature_names按得分排序输出 top 词。如果 top 词里出现「转发」「扩散」「紧急」这类传播行为词说明模型学到了谣言的传播特征如果出现的是「某地」「某人」这类实体词说明模型可能在靠实体记忆而非语义泛化换一个数据集就会崩。import numpy as np # 假设 scoreList.txt 每行是 词 得分 with open(scoreList.txt, r, encodingutf-8) as f: scores [line.strip().split() for line in f if line.strip()] # 按得分降序排列 scores.sort(keylambda x: float(x[1]), reverseTrue) print(Top-20 高区分度特征) for word, score in scores[:20]: print(f {word}: {float(score):.4f}) # 同时看底部特征确认没有把噪声词选进来 print(\nBottom-10 低区分度特征) for word, score in scores[-10:]: print(f {word}: {float(score):.4f})逻辑说明卡方得分高说明该词与类别的相关性统计显著但不代表因果。如果 top 词里出现明显的「数据集偏差词」比如某个特定事件的关键词需要手动把这些词加入停用词表重新跑。我一般会做两轮第一轮看 top-50第二轮把明显是偏差的词去掉后再跑一次对比 F1 变化。如果去掉后 F1 掉超过 5 个点说明模型严重依赖这些偏差词泛化能力堪忧。另一个进阶用法是用6_2_logisticFM.py的逻辑回归系数做可解释性分析。逻辑回归的每个特征权重直接对应「该词对谣言判定的贡献方向」——正权重表示该词出现时更可能是谣言负权重则相反。把权重最高的正负各 10 个词列出来和卡方得分交叉验证如果两个方法选出的词高度重叠说明特征选择是稳定的。from sklearn.linear_model import LogisticRegression import numpy as np # 假设 X_train, y_train 已加载 model LogisticRegression(max_iter1000, class_weightbalanced) model.fit(X_train, y_train) # 获取特征名和系数 feature_names vectorizer.get_feature_names_out() coefs model.coef_[0] # 正权重 top-10谣言信号词 top_pos np.argsort(coefs)[::-1][:10] print(谣言信号词正权重) for i in top_pos: print(f {feature_names[i]}: {coefs[i]:.4f}) # 负权重 top-10非谣言信号词 top_neg np.argsort(coefs)[:10] print(\n非谣言信号词负权重) for i in top_neg: print(f {feature_names[i]}: {coefs[i]:.4f})逻辑说明model.coef_[0]取的是二分类逻辑回归的系数向量长度等于特征维度。np.argsort返回的是索引正序是升序[::-1]反转后取前 10 就是最大正权重。这个方法比卡方更直观的地方在于方向性——卡方只告诉你「相关」逻辑回归告诉你「正相关还是负相关」。从那以后我每次拿到一个新的文本分类数据集都会先跑一遍特征回溯确认 top 特征不是数据集偏差词再继续调模型。这个习惯帮我省了很多「模型在测试集上表现很好但换数据就崩」的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表