资讯动态

中文谣言检测实战:数据预处理、特征工程与模型选型全流程

发布时间:2026/9/15 2:04:22 来源:尧图企业网站定制
简介面向自然语言处理方向的本科毕业设计项目围绕中文谣言检测构建文本二分类模型综合运用分词、停用词过滤、TF-IDF与主题模型特征提取并采用逻辑回归、支持向量机等算法完成建模与评估适合正在开展文本分类、虚假信息识别相关课题的学生参考。压缩包共28个文件包括12个Python脚本、11个TXT文本、4个JSON数据和1个Markdown说明文档Python脚本覆盖数据清洗、特征建模、聚类分析、最终模型训练等完整流程TXT与JSON文件存放停用词、标签、中间结果及处理后的数据集README清晰说明了项目结构与使用方法。整个资源仅4.93MB轻量易用目前已有59人学习。项目从原始中文谣言数据集出发给出了从数据预处理到模型评估的完整链路代码并附带可运行的中间数据与标签文件既能帮助入门者理解中文文本分类的每个环节也可为毕业设计复现和算法改进提供直接参考。1. 中文谣言检测毕业设计从 zip 包里看得到和看不到的东西收到“中国谣言识别 本科毕业设计论文-中文谣言检测.zip”这类文件第一反应通常是解压翻目录有没有训练脚本、准确率记录、模型权重。中文谣言检测落成工程本质是一个社交短文本二分类任务——输入微博、贴吧、新闻评论区里长短不一的句子输出“谣言/非谣言”两个标签。它真正难的地方不在模型选型而在标注质量、样本不均衡和短文本特征稀疏这三件事上论文里往往一句话带过代码里却藏得最细。把这个 zip 当待复现的实验工程而不是答案才不容易踩坑。别人的指标换数据分布会掉代码换环境缺依赖、路径写死是常态。我一般会按这条路线走先校验数据、重建基线再用预训练模型提指标最后把评估和演示接口一起交付。看过不少课程设计和毕设包之后能跑通并解释清楚的基本都符合这个流程。2. 数据校验与中文文本预处理中文谣言检测的地基工程2.1 解压后先查三样东西不要直接跑 train.py解压 zip 之前我习惯先用 unzip -l 或 WinRAR 列一遍文件清单确认没有../这类路径穿越前缀。Windows 自带解压器对这类条目一般不拦从网上下载的毕设包虽然基本安全但这个检查一分钟就能完成。解压后的第一眼看目录里有没有 requirements.txt、data/、checkpoints/ 这三个东西。缺 requirements.txt 的代码包后续能不能在新环境复现基本凭运气你无法知道自己应该装 transformers 3.x 还是 4.x而不同大版本之间 Tokenizer 和 Trainer 的 API 差异很大。接着用 pandas 加载训练数据这一步要同时看分布和长度import pandas as pd df pd.read_csv(data/train.csv, sep\t, names[id, text, label]) print(行数, df.shape[0]) print(标签分布) print(df[label].value_counts(normalizeTrue)) lengths df[text].str.len() print(lengths.describe(percentiles[0.5, 0.9, 0.99])) empty_ratio (df[text].str.strip().eq()).mean() print(f空文本比例{empty_ratio:.2%})这段代码从四个角度给后续建模设定边界。第一非谣言和谣言的比例差超过 10 倍就必须考虑类别加权或重采样第二0.99 分位数的文本长度决定模型 max_len常见微博类数据大概在 100-200新闻评论更短直接设 512 只会加重训练负担第三空文本比例超过 3% 说明采集环节有问题模型可能把“空”当成隐性特征需要先过滤第四把训练集和验证集的 text 字段做 set 交集重复文本会直接导致验证指标虚高。2.2 中文短文本清洗不是越干净越好谣言检测的清洗规则和普通文档分类相反。文档分类想尽可能去掉语气词谣言检测要保留语气和情绪线索。我一般按这个顺序处理import re def clean_rumor_text(t): if not isinstance(t, str): return t re.sub(rhttps?://\S|www\.\S, , t) # 去链接 t re.sub(r回复\s*\S:, , t) # 去回复引用 t re.sub(r\S, , t) # 去 用户 t re.sub(r#.?#, , t) # 去话题标签 t re.sub(r\s, , t).strip() return t链接、用户、话题标签在文本分类里是弱特征删掉可以降维度。但标点符号不能整体删除。谣言文本里感叹号和问号的密度通常显著高于普通文本“”这类连续问号在统计特征里是最有判别力的几维之一。比清洗更关键的是分词策略直接按模型类型选择模型类型切分方式说明TF-IDF 线性模型jieba 精确模式配合 bigram词表控制 5 万以内TextCNN / BiLSTM字符粒度或 jieba字符粒度免 OOV适合“哈哈哈”“yyds”BERT/RoBERTa/ERNIEBertTokenizer全词掩码不要接 jieba规则基线jieba.analyse只吐 top-k 关键词不进模型口语化谣言文本里“yyds”“绝了”“哈哈哈哈”这类词用词级切分很容易落到未知词表字符级反而稳定。2.3 标签质量和数据增强的两个取舍谣言数据集的标注一致性普遍在 0.7 左右也就是说约两成样本由不同人打会得到相反标签。工程上有两种处理噪声的策略一是用置信学习筛掉低置信度样本二是随机抽 100 条预测概率在 0.4-0.6 区间的文本人工复核。数据增强不建议用回译谣言里的“据说”“听说”“内部消息”经回译后语气可能变强或消失。更稳的做法是随机制裁片段、同义词替换增强后的样本先离线看 20 条再进训练集不然引入的噪声比提升还大。3. 特征工程与经典基线先让中文谣言检测跑出可解释结果3.1 为什么第一个模型选 TF-IDF 加逻辑回归毕业设计里最常见的错误是一上来就调 BERT。没有基线后续提升来自数据清洗还是模型结构就说不清楚。中文谣言检测的经典起点是内容特征加线性模型内容特征包括词频、TF-IDF、文本长度、感叹号数量、问号数量、表情符号数量配合 bigram 后喂给逻辑回归。逻辑回归在几千到几万条的数据量级上训练快、建议还停留在纸面上。另一处容易被忽略的是谣言表达里的欺骗性经常藏在短语中“内部消息”“紧急通知”“马上删”如果用 unigram 会被拆成互相独立的三维特征切到 bigram 后共现关系才显出来。3.2 用 scikit-learn 实现最小可复现基线import jieba from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline from sklearn.metrics import classification_report def jieba_tokenize(text): return [w for w in jieba.cut(text) if w.strip()] pipeline Pipeline([ (tfidf, TfidfVectorizer( tokenizerjieba_tokenize, ngram_range(1, 2), max_features50000, min_df2, max_df0.9, )), (clf, LogisticRegression(max_iter1000, C1.0, class_weightbalanced)), ]) pipeline.fit(X_train, y_train) print(classification_report(y_val, pipeline.predict(X_val), target_names[非谣言, 谣言]))这段代码里影响最大的四个参数ngram_range(1,2)是必须的只开 unigramF1 通常掉 3-5 个点max_features50000对短文本语料已经足够大再往上只是增加噪声min_df2去掉只在一条文本里出现的词class_weightbalanced在正负样本不均时是关键否则模型倾向把所有文本判成多数类。跑完先看验证集 F1 和 ROC-AUCAUC 低于 0.7 时问题大概率在数据而不在模型先回头查标签和清洗不要急着上深度学习。3.3 看特征权重模型到底学了什么逻辑回归的权重可以直接解释这是它适合做毕设第一个模型的原因。把区分性最强的特征打印出来import numpy as np from sklearn.metrics import roc_auc_score proba pipeline.predict_proba(X_val)[:, 1] print(AUC:, roc_auc_score(y_val, proba)) feature_names pipeline.named_steps[tfidf].get_feature_names_out() coef pipeline.named_steps[clf].coef_[0] for i in np.argsort(coef)[-20:]: print(f{feature_names[i]:30s} {coef[i]:.3f})打印结果里如果权重最高的一批词全是“的”“了”“我”说明停用词和min_df没处理干净如果出现“转发”“扩散”“求证实”这类动作动词说明模型已经学习到谣言的传播性特征。这一步在论文里能直接作为错误分析章节的素材比只贴一个 accuracy 有信息量得多。提示调大 min_df 到 3 或 5 再回看特征权重往往比直接换模型更有效。3.4 基线的调参边界参数建议范围说明ngram_range(1,2)上到 (1,3) 在小数据量时容易过拟合C0.1-1.0数据量低于 5000 时用 0.1max_features20000-100000按词表覆盖曲线选不拍脑袋类别权重balanced 或手动比例超 10:1 时手动设TF-IDF 加逻辑回归在公开中文谣言语料上的典型 F1 是 0.75-0.82如果清洗和加权后还低于这个区间回到数据检查标注分布而不是继续调参。4. 深度学习与预训练模型把中文谣言检测的指标顶上去4.1 TextCNN短文本分类的中间站TextCNN 用不同尺寸卷积核抓取局部 n-gram 模式对短文本分类速度比 BERT 快一个数量级是深度模型的合理中间选择。对中文谣言这种短文本常见配置是 filter_sizes[2,3,4]对应字符级别的二元、三元、四元窗口。核心代码骨架如下import torch import torch.nn as nn class TextCNN(nn.Module): def __init__(self, vocab_size, embed_dim200, num_filters128, filter_sizes(2, 3, 4), num_classes2): super().__init__() self.embedding nn.Embedding(vocab_size, embed_dim, padding_idx0) self.convs nn.ModuleList([ nn.Conv1d(embed_dim, num_filters, size) for size in filter_sizes ]) self.dropout nn.Dropout(0.5) self.fc nn.Linear(num_filters * len(filter_sizes), num_classes) def forward(self, x): x self.embedding(x) # (B, L, E) x x.transpose(1, 2) # (B, E, L) pooled [] for conv in self.convs: h torch.relu(conv(x)) # (B, C, L - size 1) pooled.append(torch.max_pool1d(h, h.size(2)).squeeze(2)) out torch.cat(pooled, dim1) # (B, C * len(filter_sizes)) return self.fc(self.dropout(out))两个容易出错的地方padding_idx0必须和词表里 padding 的 id 对应否则 padding 位置学到的向量偏移会污染 max pooling 结果Dropout 加在 fc 之前不加在 embedding 之后小数据量下 embedding 层后的 dropout 容易欠拟合。训练时 monitor 验证集 F1前 3 个 epoch 不涨就把学习率调低一半。4.2 用 transformers 微调中文 BERT最小可行代码TextCNN 的典型区间是 F1 0.78-0.85BERT 类模型能把公开中文谣言数据集的 F1 带到 0.84-0.90。用 HuggingFace transformers 微调的路径已经非常标准化from datasets import Dataset from transformers import AutoTokenizer, AutoModelForSequenceClassification from transformers import Trainer, TrainingArguments import evaluate checkpoint bert-base-chinese tokenizer AutoTokenizer.from_pretrained(checkpoint) def tokenize_fn(batch): return tokenizer(batch[text], truncationTrue, paddingmax_length, max_length128) train_ds Dataset.from_dict({text: X_train, label: y_train}).map(tokenize_fn, batchedTrue) val_ds Dataset.from_dict({text: X_val, label: y_val}).map(tokenize_fn, batchedTrue) args TrainingArguments( output_dir./ckpt, learning_rate2e-5, per_device_train_batch_size16, per_device_eval_batch_size64, num_train_epochs3, warmup_ratio0.1, eval_strategyepoch, save_strategyepoch, load_best_model_at_endTrue, metric_for_best_modelf1, ) def compute_metrics(eval_pred): logits, labels eval_pred preds logits.argmax(-1) f1 evaluate.load(f1) return f1.compute(predictionspreds, referenceslabels) trainer Trainer( modelAutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels2), argsargs, train_datasettrain_ds, eval_datasetval_ds, compute_metricscompute_metrics, ) trainer.train()关键参数的解释学习率 2e-5 是 BERT 微调的典型值超过 5e-5 容易灾难性遗忘max_length128 根据谣言短文本分布确定没必要设 512warmup_ratio0.1 缓解小数据集前几个 step 的 loss 震荡显存不足把 batch_size 降到 8 或 4同时学习率相应下调到 1e-5 附近。这套代码在单张消费级显卡上跑中文谣言数据集数千条样本3 个 epoch 一般十分钟内完成。4.3 把用户特征和时间特征拼进模型创新点常用做法BERT 只吃文本但数据里通常还有转发数、粉丝数、发布时间等字段模型对此一无所知。要把这些线索合进模型常见做法是取出 BERT 的 pooler_output再和数值特征拼接模型推理速度典型 F1适用数据量TF-IDF LR毫秒级0.75-0.82千到万条TextCNN毫秒级0.78-0.85千到万条BERT 微调十毫秒级0.84-0.90千条以上from transformers import AutoModel base AutoModel.from_pretrained(bert-base-chinese) with torch.no_grad(): hidden base(**encoded)[pooler_output] # (B, 768) meta torch.tensor(numeric_feats, dtypetorch.float32) # (B, m) concat torch.cat([hidden, meta], dim1) # (B, 768 m) out nn.Linear(768 m, 2)(concat)拼接时元特征必须做归一化。粉丝数和转发数是长尾分布不取 log 或不归一化会直接压过 768 维的语义向量。我一般做分箱发布时段分 24 箱转发数取 log1p再全部标准化到零均值单位方差。这类特征融合在高基线模型上还能提升 1-2 个点 F1足够支撑毕业论文里的“多模态特征增强”章节。5. 评估、打包与演示让中文谣言检测模型能一键复现5.1 用混淆矩阵和阈值判断模型是否合格谣言检测的类别代价不对称漏放一条谣言的代价通常大于误报所以判断模型先看 F1 和混淆矩阵from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score print(Precision:, precision_score(y_val, y_pred)) print(Recall:, recall_score(y_val, y_pred)) print(F1:, f1_score(y_val, y_pred)) print(confusion_matrix(y_val, y_pred))如果召回率明显低于精确率说明模型把大多数样本判成了多数类。先把阈值扫一遍找到 F1 最大的切分点proba pipeline.predict_proba(X_val)[:, 1] for th in [0.3, 0.4, 0.5, 0.6, 0.7]: pred (proba th).astype(int) print(th, f1_score(y_val, pred), recall_score(y_val, pred))概率集中在 0.4-0.6 说明模型对谣言本身不敏感这时回到训练侧做重采样不要靠压阈值硬撑。5.2 用 FastAPI 打一个最小演示接口from fastapi import FastAPI from pydantic import BaseModel import joblib app FastAPI() pipeline joblib.load(models/pipeline.pkl) class Item(BaseModel): text: str app.post(/predict) def predict(item: Item): p pipeline.predict_proba([item.text])[0, 1] return {prob_rumor: round(float(p), 4), label: 谣言 if p 0.5 else 非谣言}pipeline.pkl 内部包含 TfidfVectorizer 和 jieba 的分词状态换机器后 jieba 词典可能与训练时不一致建议保存模型时同时录制 jieba 版本在 README 里注明。若要部署 BERT 模型把 trainer 的 best_model 路径存到 models/ckpt加载后包一层同样的 predict 函数即可。5.3 交付 zip 前最后两个检查最终目录建议这样组织data/ 放划分好的训练验证测试集models/ 放基线模型 pkl 和 BERT checkpoints根目录放 README.md、requirements.txt 和论文 PDF。压缩前跑一遍预测脚本然后检查压缩包完整性python -m pytest tests/ -q unzip -t final.zip python -c import joblib; joblib.load(models/pipeline.pkl)这三条命令分别验证数据管线、压缩包结构和模型文件可加载正常应在一分钟内全部通过。本文还有配套的精品资源点击获取

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

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

免费获取报价