摘要:
合集:AI案例-NLP-传媒业
赛题:疫情微博情绪识别挑战赛
主办方:科大讯飞、Datawhale
AI问题:文本分类
主页:https://challenge.xfyun.cn/topic/info?type=epidemic-weibo&ch=j4XWs7V
数据集:正向情绪和负面情绪的微博文本
数据集价值:识别微博文本的情绪。
解决方案:TF-IDF、bert-base-chinese模型
一、赛题描述
背景
疫情发生对人们生活生产的方方面面产生了重要影响,并引发了国内舆论的广泛关注,众多网民也参与到了疫情相关话题的讨论中。大众日常的情绪波动在疫情期间会放大,并寻求在自媒体和社交媒体上发布和评论。
为了掌握真实社会舆论情况,科学高效地做好防控宣传和舆情引导工作,针对疫情相关话题开展网民情绪识别是重要任务。本次我们重点关注微博平台上的用户情绪,希望各位选手能搭建自然语言处理模型,对疫情下微博文本的情绪进行识别。
任务
本次赛题需要选手对微博文本进行情绪分类,分为正向情绪和负面情绪。数据样例如下:
正向情绪:集体加班的感觉真壮观,办公室全是脑袋【嘻嘻】
负面情绪:当医生不容易啊!感慨万千!【汗】【晕】【衰】
二、数据集描述
数据说明
赛题数据由训练集和测试集组成。
数据集版权许可协议
BY-NC-SA 4.0
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans
三、解决方案样例
工作原理介绍
1. TF-IDF(Term Frequency-Inverse Document Frequency)
一种广泛应用于自然语言处理(NLP)和信息检索的技术,用于评估一个词语在文档集合或语料库中的重要性。
TF(Term Frequency,词频)
- 定义:某个词在文档中出现的次数。
- 公式:TF(t,d)=文档 d 中的总词数词 t 在文档 d 中出现的次数
- 作用:衡量词语在单篇文档中的常见程度。例如,在文档“苹果香蕉苹果”中,“苹果”的TF值为 32。
IDF(Inverse Document Frequency,逆文档频率)
- 定义:衡量词语在文档集合中的稀有程度。罕见词具有更高的IDF值。
- 公式:IDF(t)=log(包含词 t 的文档数总文档数)
- 作用:降低常见词的权重,突出重要词汇。例如,若“的”出现在所有文档中,则其IDF值趋近于0。
2. BERT-base-Chinese
bert-base-chinese
是谷歌发布的 中文预训练BERT模型,基于Transformer架构,专门针对中文文本进行优化。- 预训练:在大规模中文语料(如维基百科、新闻、书籍)上训练,学习语言的通用表示。
- 模型规模:
- Base版:12层Transformer,768隐藏维度,12个注意力头,约110M参数。
- 无
bert-large-chinese
官方版本,但社区有类似扩展模型。
- 核心特点:
- 支持中文分词(基于字或词,实际以字为单位处理)。
- 双向上下文建模(通过Masked Language Model任务)。
- 适用于多种下游任务(分类、NER、问答等)。
运行环境
外部库名称 | 版本号 |
---|---|
python | 3.12.8 |
sklearn-crfsuite | 0.5.0 |
jieba | 1.4.0 |
transformers | 4.49.0 |
torch | 2.6.0+cu126 |
部署大语言模型:bert-base-chinese在当前目录下。
源码逻辑
源码:NLP_Weibo_Emotion_Recognition.ipynb。该代码实现了基于 TF-IDF + 逻辑回归 和 BERT 的微博文本情绪分类任务。任务目标:
- 输入:微博文本(含疫情相关话题)。
- 输出:情绪标签(
0
或1
)。 - 评估指标:准确率(代码中未显式计算,但通过提交文件可推断)。
(1) 数据加载与预处理
- 数据格式:
- 训练集:
text
(微博文本) +label
(情绪标签)。 - 测试集:仅
text
。
- 训练集:
- 分词处理:
- 使用
jieba
对中文文本分词,并用空格连接(便于 TF-IDF 处理)。
- 使用
(2) 传统方法:TF-IDF + 逻辑回归
- 流程:
- TF-IDF 向量化:将分词后的文本转换为数值特征。
- 逻辑回归分类:基于 TF-IDF 特征训练分类器。
TfidfVectorizer(),
LogisticRegression()
)
pipline.fit(
train_df[‘words’].tolist(),
train_df[‘label’].tolist()
) - 结果:提交文件
lr_submit.csv
,准确率约 86%。
(3) 深度方法:BERT 微调
- 模型加载:
- 使用
bert-base-chinese
预训练模型,添加分类头(num_labels=2
)。
- 使用
- 数据编码:
- 使用
BertTokenizer
对文本进行编码(生成input_ids
和attention_mask
)。
train_encoding = tokenizer(train_df[‘text’].tolist(), truncation=True, padding=True, max_length=128) - 使用
- 训练流程:
- 自定义数据集类
NewsDataset
:封装编码后的数据和标签。 - 训练循环:
- 批量输入数据,计算损失并反向传播。
- 使用
AdamW
优化器,学习率2e-5
。 - 每 50 步打印损失和进度。
def train():
model.train()
total_train_loss = 0
iter_num = 0
total_iter = len(train_loader)
for batch in train_loader:
# 正向传播
optim.zero_grad()
input_ids = batch[‘input_ids’].to(device)
attention_mask = batch[‘attention_mask’].to(device)
labels = batch[‘labels’].to(device)
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs[0]
total_train_loss += loss.item()
# 反向梯度信息
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
# 参数更新
optim.step()
iter_num += 1
if (iter_num % 50 == 0):
print(“Epoth: %d, iter_num: %d, loss: %.4f, progress: %.2f%%” % (epoch, iter_num, loss.item(), iter_num/total_iter*100))
print(“Epoch: %d, Average training loss: %.4f”%(epoch, total_train_loss/len(train_loader)))
for epoch in range(1):
print(“———— Epoch: %d —————-” % epoch)
train()
- 自定义数据集类
- 预测与提交:
- 对测试集生成预测结果,保存为
bert_submit.csv
,准确率约 96%。
- 对测试集生成预测结果,保存为
运行结果
------------ Epoch: 0 ----------------
Epoth: 0, iter_num: 20, loss: 0.5663, 0.53%
Epoth: 0, iter_num: 40, loss: 0.4880, 1.07%
Epoth: 0, iter_num: 60, loss: 0.0696, 1.60%
Epoth: 0, iter_num: 80, loss: 0.1796, 2.13%
Epoth: 0, iter_num: 100, loss: 0.0104, 2.67%
Epoth: 0, iter_num: 120, loss: 0.0093, 3.20%
Epoth: 0, iter_num: 140, loss: 0.0731, 3.73%
Epoth: 0, iter_num: 160, loss: 0.0475, 4.27%
Epoth: 0, iter_num: 180, loss: 0.1766, 4.80%
Epoth: 0, iter_num: 200, loss: 0.2458, 5.33%
Epoth: 0, iter_num: 220, loss: 0.0086, 5.87%
Epoth: 0, iter_num: 240, loss: 0.0103, 6.40%
Epoth: 0, iter_num: 260, loss: 0.0040, 6.93%
Epoth: 0, iter_num: 280, loss: 0.0448, 7.47%
Epoth: 0, iter_num: 300, loss: 0.0425, 8.00%
Epoth: 0, iter_num: 320, loss: 0.0050, 8.53%
Epoth: 0, iter_num: 340, loss: 0.0148, 9.07%
Epoth: 0, iter_num: 360, loss: 0.2996, 9.60%
Epoth: 0, iter_num: 380, loss: 0.2961, 10.13%
Epoth: 0, iter_num: 400, loss: 0.0185, 10.67%
Epoth: 0, iter_num: 420, loss: 0.0192, 11.20%
Epoth: 0, iter_num: 440, loss: 0.0072, 11.73%
Epoth: 0, iter_num: 460, loss: 0.1827, 12.27%
Epoth: 0, iter_num: 480, loss: 0.2058, 12.80%
...
Epoth: 0, iter_num: 3700, loss: 0.1949, 98.67%
Epoth: 0, iter_num: 3720, loss: 0.2355, 99.20%
Epoth: 0, iter_num: 3740, loss: 0.0280, 99.73%
Epoch: 0, Average training loss: 0.1407
输出数据样例:对应于两种方式 lr_submit.csv 和 bert_submit.csv
label
0
0
0
1
0
0
0
0
1
...
源码开源协议
GPL-v3