AutoModelForSequenceClassification训练Loss不下降问题求助
解决RoBERTa文本分类Loss不下降、精度接近随机的问题
针对你用RoBERTa-base做文本分类时出现的Loss不下降甚至上升、验证精度接近随机的问题,结合你的代码分析,给出以下排查和修复方案:
关键问题与修复方法
1. 分类头初始化与预训练层冻结
RoBERTa预训练模型本身不带分类头,AutoModelForSequenceClassification会随机初始化一个分类头。直接全量训练时,随机分类头的大幅梯度会干扰预训练层参数,导致模型退化。
修复:
先冻结预训练层,单独训练分类头1-2轮,再解冻全量微调:
# 初始化模型时显式指定类别数,冻结预训练层 model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2) for param in model.roberta.parameters(): param.requires_grad = False model = model.cuda() # 训练1-2轮后解冻预训练层,重新初始化优化器 # for param in model.roberta.parameters(): # param.requires_grad = True # optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01)
2. 优化器与学习率策略优化
你使用的torch.optim.AdamW默认配置不适合预训练模型微调,建议调整:
- 降低学习率至
2e-5 ~ 1e-5,加入权重衰减(0.01) - 添加学习率预热,避免初始阶段学习率过大冲垮模型
- 加入梯度裁剪,防止梯度爆炸
修复代码:
from transformers import get_linear_schedule_with_warmup # 初始化优化器 optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01) # 设置学习率预热调度器 total_steps = len(train_dataloader) * num_epochs scheduler = get_linear_schedule_with_warmup( optimizer, num_warmup_steps=int(total_steps * 0.1), # 预热10%的训练步数 num_training_steps=total_steps ) # 修改训练函数,加入梯度裁剪和调度器更新 def train_one_epoch(model, dataloader, optimizer, scheduler): model.train() loss_list = [] for batch in tqdm(dataloader): batch_data = { 'input_ids': batch['input_ids'], 'attention_mask': batch['attention_mask'], 'labels': batch['labels'] } loss = model(**batch_data).loss loss.backward() # 梯度裁剪 torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) optimizer.step() scheduler.step() # 更新学习率 optimizer.zero_grad() loss_list.append(loss.detach().item()) avg_loss = sum(loss_list) / len(loss_list) print('avg loss in epoch:', avg_loss)
3. 修正准确率计算的Tensor设备问题
当前代码中存储的标签和预测结果是CUDA Tensor,建议转成CPU列表,避免潜在的设备不匹配问题:
def evaluate(model, dataloader): model.eval() all_labels = [] all_predictions = [] for batch in dataloader: with torch.no_grad(): batch_data = { 'input_ids': batch['input_ids'], 'attention_mask': batch['attention_mask'] } logits = model(**batch_data).logits predictions = torch.argmax(logits, dim=-1) labels = batch['labels'] all_labels.extend(labels.cpu().numpy().tolist()) all_predictions.extend(predictions.cpu().numpy().tolist()) accuracy = compute_accuracy(all_predictions, all_labels) print("Accuracy", accuracy) return accuracy
额外建议
- 调整batch_size:当前用8,可尝试16/32(根据显存容量)
- 检查数据加载:打印少量batch的
input_ids和labels,确认数据格式正确 - 尝试更小的初始学习率(如
1e-5),观察Loss变化
内容的提问来源于stack exchange,提问作者naivebird
相关产品推荐
相关产品推荐

