科大讯飞2022疫情微博情绪识别挑战赛

摘要:

合集: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、问答等)。

运行环境

外部库名称版本号
python3.12.8
sklearn-crfsuite0.5.0
jieba1.4.0
transformers4.49.0
torch2.6.0+cu126

部署大语言模型:bert-base-chinese在当前目录下。

源码逻辑

源码:NLP_Weibo_Emotion_Recognition.ipynb。该代码实现了基于 TF-IDF + 逻辑回归 和 BERT 的微博文本情绪分类任务。任务目标:

  • 输入:微博文本(含疫情相关话题)。
  • 输出:情绪标签(01)。
  • 评估指标:准确率(代码中未显式计算,但通过提交文件可推断)。

(1) 数据加载与预处理

  • 数据格式
    • 训练集:text(微博文本) + label(情绪标签)。
    • 测试集:仅 text
  • 分词处理
    • 使用 jieba 对中文文本分词,并用空格连接(便于 TF-IDF 处理)。
    train_df[‘words’] = train_df[‘text’].apply(lambda x: ‘ ‘.join(jieba.lcut(x)))

(2) 传统方法:TF-IDF + 逻辑回归

  • 流程:
    1. TF-IDF 向量化:将分词后的文本转换为数值特征。
    2. 逻辑回归分类:基于 TF-IDF 特征训练分类器。
    pipline = make_pipeline(
       TfidfVectorizer(),
       LogisticRegression()
    )

    pipline.fit(
       train_df[‘words’].tolist(),
       train_df[‘label’].tolist()
    )
  • 结果:提交文件 lr_submit.csv,准确率约 86%。

(3) 深度方法:BERT 微调

  • 模型加载
    • 使用 bert-base-chinese 预训练模型,添加分类头(num_labels=2)。
    model = BertForSequenceClassification.from_pretrained(‘bert-base-chinese’, num_labels=2)
  • 数据编码
    • 使用 BertTokenizer 对文本进行编码(生成 input_idsattention_mask)。
    tokenizer = BertTokenizer.from_pretrained(‘./bert-base-chinese/’)
    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

四、获取案例套装

需要登录后才允许下载文件包。登录 需要登录后才允许下载文件包。登录

发表评论