You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在已训练BERT模型基础上仅用FP、FN样本完成重训练

仅用FP/FN样本微调已训练BERT分类模型的PyTorch实现方案

你要做的操作属于难例微调(Hard Example Fine-tuning),核心是在保留原有100万数据训练成果的基础上,小幅度调整模型对错分样本的拟合能力,避免过拟合即可,具体操作步骤如下:

1. 前期准备

  • 完整加载已训练好的模型权重,不要做任何层的随机初始化,参考代码:
import torch
from transformers import BertForSequenceClassification, BertTokenizer

# 路径替换为你自己的模型保存路径,初始化逻辑和之前训练时保持完全一致
model = BertForSequenceClassification.from_pretrained("your_trained_model_path")
tokenizer = BertTokenizer.from_pretrained("your_trained_model_path")
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
  • 整理所有FP、FN样本为标准训练格式,每条包含原始文本、真实标签;如果难例样本量少于1000条,可以做少量轻量数据增强(比如同义替换、短文本语序微调),降低过拟合风险。

2. 训练策略设置

这部分是核心,绝对不能用之前全量训练的大学习率,否则会直接冲掉原有训练成果:

  • 学习率设置为之前全量训练学习率的1/10 ~ 1/5,比如之前全量训练用的是2e-5,现在就用2e-6 ~ 4e-6即可
  • 建议冻住BERT底层的前6~8层Transformer,只微调顶层Transformer和分类头,保留底层通用语义特征能力,避免通用分类能力退化,冻层参考代码:
# 冻住BERT前8层,不更新权重
for name, param in model.bert.named_parameters():
    if "layer." in name:
        layer_num = int(name.split("layer.")[1].split(".")[0])
        if layer_num < 8:
            param.requires_grad = False
# 分类头默认开启梯度,不需要额外设置
  • 训练轮次控制在3~5轮即可,每轮结束可以用之前的全量验证集跑一次效果,如果出现整体准确率下跌就提前停止训练
  • 损失函数沿用你之前分类任务用的交叉熵损失即可,不需要修改

3. 训练流程

和常规PyTorch训练流程一致,仅把训练集替换为整理好的FP/FN样本即可,参考代码片段:

from torch.utils.data import DataLoader, Dataset
import torch.nn.functional as F

# 自定义数据集类,逻辑和你之前训练时保持一致即可
class HardExampleDataset(Dataset):
    def __init__(self, texts, labels, tokenizer, max_len=128):
        self.texts = texts
        self.labels = labels
        self.tokenizer = tokenizer
        self.max_len = max_len
    def __len__(self):
        return len(self.texts)
    def __getitem__(self, idx):
        text = self.texts[idx]
        label = self.labels[idx]
        encoding = self.tokenizer.encode_plus(
            text,
            truncation=True,
            add_special_tokens=True,
            max_length=self.max_len,
            return_token_type_ids=False,
            padding='max_length',
            return_attention_mask=True,
            return_tensors='pt',
        )
        return {
            'input_ids': encoding['input_ids'].flatten(),
            'attention_mask': encoding['attention_mask'].flatten(),
            'label': torch.tensor(label, dtype=torch.long)
        }

# 初始化数据集、加载器,batch size可以设小一点,比如8、16均可
dataset = HardExampleDataset(fp_fn_text_list, fp_fn_label_list, tokenizer)
dataloader = DataLoader(dataset, batch_size=8, shuffle=True)

# 优化器仅更新开启了梯度的参数
optimizer = torch.optim.AdamW(filter(lambda p: p.requires_grad, model.parameters()), lr=2e-6)

# 训练循环
model.train()
for epoch in range(3):
    total_loss = 0
    for batch in dataloader:
        input_ids = batch['input_ids'].to(device)
        attention_mask = batch['attention_mask'].to(device)
        labels = batch['label'].to(device)
        
        outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
        loss = outputs.loss
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        total_loss += loss.item()
    print(f"Epoch {epoch+1} average loss: {total_loss/len(dataloader)}")

4. 效果校验

训练结束后必须同时做两项校验,避免过拟合:

  • 用本次训练用的FP/FN样本测试,确认大部分难例已经可以正确分类
  • 用之前全量数据的验证集跑一遍整体准确率、召回率、F1值,确保整体效果没有出现大幅下跌,如果下跌就减少训练轮次或者进一步降低学习率。

额外提示:如果你的FP/FN样本总量少于500条,建议直接只微调分类头,不改动BERT任何Transformer层,过拟合风险会大幅降低。

内容的提问来源于stack exchange,提问作者Patricia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:36:02