bert的trick

模型选型

根据下游任务的领域选择合适的模型,另外区分好语言。如果算力足够的话优先选用large模型。

中文:hfl/chinese-roberta-wwm-ext以及hfl/chinese-macbert-base,这两个在中文上的效果都非常不错

英文:microsoft/deberta-v3-base

预训练

领域内预训练,就是在自己的训练集文本(或相似领域的训练集文本)上执行预训练,训练结束后模型便更贴合自己的任务了,在训练的时候收敛速度加快,效果一般来说也能带来百分位点的提升。

训练任务:

  1. mlm预训练,简单来说完形填空。

  2. simcse预训练,对比学习的预训练。(适用场景:主要考量embedding嵌入的相似度)

对抗训练

对抗训练的方式是对输入的embedding进行攻击,这样的好处便是不用自己再人为制定策略来对数据进行增强(对某个词进行删除替换等),而可以在训练过程中让攻击和防守自然而然的发生,具体的做法是这样的:

  1. 攻击:在输入的embedding上进行梯度上升,使得loss变大

  2. 防守:在参数上进行梯度下降,使得loss减少

这一过程会贯穿每一个训练step,因此便使得对抗的过程自然而然的发生,模型也会训练的越来越强。如FGM:将因子*参数的梯度作为原有模型参数以外的参数用于学习,从而增大了学习难度。

class FGM():
    def __init__(self, model):
        self.model = model
        self.backup = {}

    def attack(self, epsilon=1., emb_name='emb.'):
        # emb_name这个参数要换成你模型中embedding的参数名
        for name, param in self.model.named_parameters():
            if param.requires_grad and emb_name in name:
                self.backup[name] = param.data.clone()
                norm = torch.norm(param.grad)
                if norm != 0 and not torch.isnan(norm):
                    r_at = epsilon * param.grad / norm
                    param.data.add_(r_at)

    def restore(self, emb_name='emb.'):
        # emb_name这个参数要换成你模型中embedding的参数名
        for name, param in self.model.named_parameters():
            if param.requires_grad and emb_name in name: 
                assert name in self.backup
                param.data = self.backup[name]
        self.backup = {}
# 初始化
fgm = FGM(model)
for batch_input, batch_label in data:
    # 正常训练
    loss = model(batch_input, batch_label)
    loss.backward() # 反向传播,得到正常的grad
    # 对抗训练
    fgm.attack() # 在embedding上添加对抗扰动
    loss_adv = model(batch_input, batch_label)
    loss_adv.backward() # 反向传播,并在正常的grad基础上,累加对抗训练的梯度
    fgm.restore() # 恢复embedding参数
    # 梯度下降,更新参数
    optimizer.step()
    model.zero_grad()

但是这样增加扰动的方式往往需要大量的训练数据,而且增加的点大概只有两三点,在打比赛的时候更适合。

Rdrop

dropout在训练和推理的时候存在不一致性,训练的时候存在drop,推理的时候不存在。因此,存在影响模型效果的可能性。为了减小dropout带来的扰动,除了调整系数外,还可以将两次输出的logits过KL散度的计算。(感觉划不来

可以直接在bert微调的时候去掉dropout,因为dropout本质上是一种缓解过拟合的方法,可能并不适合微调的场景,如果在bert的每一层都增加了扰动,最终会引发相对较大的不稳定。

在文本分类的微调中,做了实验,发现去掉dropout能有所提升。

学习率

bert微调学习率大概都是e-5。bert顶层是task specific的,因此从顶到底可以实现学习率的递减。对不同层采用不一样的学习率策略。

长文本处理
  1. 选取文本,标题、第一段内容、最后一段内容包含大量有用信息。

  2. 拆分句子多次过bert,最后pooling。

Pooling方式

除了max_pooling和mean_pooling,还有attention_pooling

class AttentionPooling(nn.Module):
    def __init__(self, in_dim):
        super().__init__()
        self.attention = nn.Sequential(
        nn.Linear(in_dim, in_dim),
        nn.LayerNorm(in_dim),
        nn.GELU(),
        nn.Linear(in_dim, 1),
        )
    def forward(self, last_hidden_state, attention_mask):
        w = self.attention(last_hidden_state).float()
        w[attention_mask==0]=float('-inf')
        w = torch.softmax(w,1)
        attention_embeddings = torch.sum(w * last_hidden_state, dim=1)
        return attention_embeddings

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值