当前位置: 首页 > news >正文

基于 Transformer robert的情感分类任务实践总结之二——R-Drop

基于 Transformer robert的情感分类任务实践总结之一

核心改进点

1. R-Drop正则化
  • 原理:通过在同一个输入上两次前向传播(利用Dropout的随机性),强制模型对相同输入生成相似的输出分布,避免过拟合。
  • 实现
    • 对同一文本输入,两次通过RoBERTa模型(Dropout层随机失活不同神经元),得到两组logits。
    • 损失函数由**交叉熵损失(CE)KL散度损失(KL)**组成:
      Loss = CE ( l o g i t s 1 , l a b e l s ) + CE ( l o g i t s 2 , l a b e l s ) + α × KL ( l o g i t s 1 , l o g i t s 2 ) \text{Loss} = \text{CE}(logits_1, labels) + \text{CE}(logits_2, labels) + \alpha \times \text{KL}(logits_1, logits_2) Loss=CE(logits1,labels)+CE(logits2,labels)+α×KL(logits1,logits2)
      其中,(\alpha)为KL损失权重(本文设为5.0)。
2. 标签平滑(Label Smoothing)
  • 作用:缓解模型对标签的过度自信,通过向独热标签中添加均匀噪声(本文系数为0.1),提升泛化能力。

评价指标

  • 准确率(Accuracy)、F1分数(F1)、ROC-AUC值,全面评估分类性能。

实验结果与总结

  • 性能提升:相比基础RoBERTa,改进后模型在测试集上的F1分数提升约1.2%,AUC提升约0.8%,过拟合现象明显缓解。
  • 核心价值:R-Drop通过强制模型输出一致性,有效增强了预测稳定性;标签平滑则降低了模型对硬标签的依赖,两者结合显著提升了泛化能力。
  • 适用场景:文本分类、情感分析等任务,尤其适合标注数据有限或需提升模型鲁棒性的场景。

代码

#!/usr/bin/env python
# 改进版 RoBERTa 情感分类器 v2
import os
import random
import numpy as np
import torch
import torch.nn as nn
from transformers import (AutoTokenizer,AutoModelForSequenceClassification,Trainer,TrainingArguments,DataCollatorWithPadding,get_cosine_schedule_with_warmup,set_seed,EarlyStoppingCallback,
)
from datasets import load_dataset
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"# 设置随机种子
set_seed(42)# 配置
MODEL_NAME = "roberta-base"
NUM_LABELS = 2
R_DROP_ALPHA = 5.0  # R-Drop loss 权重
LABEL_SMOOTHING = 0.1  # 标签平滑系数# 加载数据
dataset = load_dataset("imdb")
train_dataset = dataset["train"]
test_dataset = dataset["test"]# Tokenizer
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)def preprocess_function(examples):return tokenizer(examples["text"], truncation=True)train_dataset = train_dataset.map(preprocess_function, batched=True)
test_dataset = test_dataset.map(preprocess_function, batched=True)# 数据整理器
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)# 加载模型
model = AutoModelForSequenceClassification.from_pretrained(MODEL_NAME, num_labels=NUM_LABELS
)# 改进版 Loss R-Drop + Label Smoothing)
class RDropLoss(nn.Module):def __init__(self, alpha=1.0, label_smoothing=0.0):super(RDropLoss, self).__init__()self.alpha = alphaself.label_smoothing = label_smoothingself.ce = nn.CrossEntropyLoss(label_smoothing=label_smoothing)self.kl = nn.KLDivLoss(reduction="batchmean")def forward(self, logits1, logits2, labels):# CrossEntropy Lossce_loss1 = self.ce(logits1, labels)ce_loss2 = self.ce(logits2, labels)ce_loss = 0.5 * (ce_loss1 + ce_loss2)# KL散度 Lossp = torch.log_softmax(logits1, dim=-1)q = torch.log_softmax(logits2, dim=-1)p_softmax = torch.softmax(logits1, dim=-1)q_softmax = torch.softmax(logits2, dim=-1)kl_loss = 0.5 * (self.kl(p, q_softmax) + self.kl(q, p_softmax))return ce_loss + self.alpha * kl_loss# 评价指标
def compute_metrics(eval_pred):logits, labels = eval_predprobs = torch.softmax(torch.tensor(logits), dim=-1).numpy()predictions = np.argmax(logits, axis=-1)acc = accuracy_score(labels, predictions)f1 = f1_score(labels, predictions)try:auc = roc_auc_score(labels, probs[:, 1])except:auc = 0.0return {"accuracy": acc, "f1": f1, "auc": auc}# 自定义 Trainer,支持 R-Drop
class RDropTrainer(Trainer):def __init__(self, *args, alpha=1.0, label_smoothing=0.0, **kwargs):super().__init__(*args, **kwargs)self.rdrop_loss_fn = RDropLoss(alpha=alpha, label_smoothing=label_smoothing)def compute_loss(self, model, inputs, return_outputs=False, **kwargs):labels = inputs.pop("labels")# forward twice (Dropout 不同)# model.train()#没有必要。重复了。outputs1 = model(**inputs)outputs2 = model(**inputs)logits1 = outputs1.logitslogits2 = outputs2.logitsloss = self.rdrop_loss_fn(logits1, logits2, labels)return (loss, outputs1) if return_outputs else loss# Trainer 参数
training_args = TrainingArguments(output_dir="./results_rdrop",eval_strategy="epoch",save_strategy="epoch",learning_rate=2e-5,per_device_train_batch_size=16,per_device_eval_batch_size=16,num_train_epochs=5,weight_decay=0.01,warmup_ratio=0.1,lr_scheduler_type="cosine",  # CosineAnnealinglogging_dir="./logs_rdrop",#tensorboard --logdir ./logs_rdroplogging_steps=50,load_best_model_at_end=True,metric_for_best_model="f1",fp16=True,save_total_limit=2,
)
early_stopping_callback = EarlyStoppingCallback(early_stopping_patience=3, early_stopping_threshold=0.01)# 初始化 Trainer
trainer = RDropTrainer(model=model,args=training_args,train_dataset=train_dataset,eval_dataset=test_dataset,processing_class=tokenizer, data_collator=data_collator,compute_metrics=compute_metrics,callbacks=[early_stopping_callback], alpha=R_DROP_ALPHA,label_smoothing=LABEL_SMOOTHING,
)# 训练
trainer.train()# 评估
trainer.evaluate()

tensorboard

在这里插入图片描述

参考资料

  • R-Drop论文:《R-Drop: Regularized Dropout for Neural Networks》

相关文章:

  • model.classifier 通常指模型的分类头 是什么,详细举例说明在什么部位,发挥什么作用
  • 多模型协同:基于 SAM 分割 + YOLO 检测 + ResNet 分类的工业开关状态实时监控方案
  • Modbus RTU/TCP 协议详解与Spring Boot集成指南
  • 什么是异步 I/O?深入解析从基础到实践
  • 20250607-在Ubuntu中使用Anaconda创建新环境并使用本地的备份文件yaml进行配置
  • similarsites网页版入口,一键查询相似网站
  • Go 并发编程深度指南
  • 【MATLAB代码】基于MCC(最大相关熵)的EKF,一维滤波,用于解决观测噪声的异常|附完整代码,订阅专栏后可直接查看
  • mariadb5.5.56在centos7.6环境安装
  • JVM 垃圾回收器 详解
  • Python网页自动化测试,DrissonPage库入门说明文档
  • Spring Boot 3.3 + MyBatis 基础教程:从入门到实践
  • Android座舱系统Agent改造方案
  • cmake编译LASzip和LAStools
  • CVE-2023-25194源码分析与漏洞复现(Kafka JNDI注入)
  • Java优化:双重for循环
  • 2023年ASOC SCI2区TOP,随机跟随蚁群优化算法RFACO,深度解析+性能实测
  • B站Miachael_ee——蓝牙教程笔记
  • 又是一年高考季
  • Redis 与 MySQL 数据一致性保障方案
  • 如何打开建设网站后台/如何网络媒体推广
  • 专业的广州商城网站建设/iis搭建网站
  • 西樵网站建设公司/电脑培训机构
  • 武夷山景区网站建设特点/提高关键词排名的软文案例
  • 做伊朗的外贸公司网站/在线制作网页网站
  • 门户网站定制服务器/软文推广软文营销