模型中的关键(小tricks)

在模型中,除了问题的表示方法要尽可能与最终目标挂钩外,其次,loss函数与一些其他的小的操作技巧也是十分重要的
比如:
最近看到的focal loss,这是一个焦点损失函数,目标就是为了解决正类多而负类少的问题,(最直接的想法,就是在BCE loss中加权重,对于正类的损失权重大一些,负例则小一些),但是,不同的类别,数量多少也是不一致的(这里在NLP中是否可以理解为长尾分布,就是不同类别下出现的概率是不同的),因此,在损失函数中考虑了不同类别下的出现概率,形成了最终的焦点损失函数。
在这里插入图片描述

上边的公式展开的话:先说明的是,当y=1(正类),p_{t}=p,others情况下,p_{t}=(1-p)
− α ( 1 − p ) γ l o g ( p ) − ( 1 − α ) p γ l o g ( 1 − p ) -\alpha(1-p)^\gamma log(p)-(1-\alpha)p^\gamma log(1-p) α(1p)γlog(p)(1α)pγlog(1p)
在这里插入图片描述
但是,在针对长尾分布时,2022年的文章提到了适应性焦点损失函数(源码还没有给出),具体是在《Document-Level Relation Extraction
with Adaptive Focal Loss and Knowledge Distillation》
具体来说,它添加了一类,TH作为可调整的适应性阈值。
loss如下:P(ri)为正例概率,P(rTH)为负例概率,仔细观察的话,这是focal loss的前面一部分,(1-P(ri)是为了适应类别不均衡的情况)

这个,源码公开后,需要在详细看看

在这里插入图片描述
focal loss的实现(https://zhuanlan.zhihu.com/p/308290543

#--------------二分类
class BCEFocalLoss(torch.nn.Module):
    def __init__(self, gamma=2, alpha=0.25, reduction='mean'):
        super(BCEFocalLoss, self).__init__()
        self.gamma = gamma
        self.alpha = alpha
        self.reduction = reduction

    def forward(self, predict, target):
        pt = torch.sigmoid(predict) # sigmoide获取概率
        #在原始ce上增加动态权重因子,注意alpha的写法,下面多类时不能这样使用
        loss = - self.alpha * (1 - pt) ** self.gamma * target * torch.log(pt) 
- (1 - self.alpha) * pt ** self.gamma * (1 - target) * torch.log(1 - pt)

        if self.reduction == 'mean':
            loss = torch.mean(loss)
        elif self.reduction == 'sum':
            loss = torch.sum(loss)
        return loss
#------------多分类
class MultiCEFocalLoss(torch.nn.Module):
    def __init__(self, class_num, gamma=2, alpha=None, reduction='mean'):
        super(MultiCEFocalLoss, self).__init__()
        if alpha is None:
            self.alpha = Variable(torch.ones(class_num, 1))
        else:
            self.alpha = alpha
        self.gamma = gamma
        self.reduction = reduction
        self.class_num =  class_num

    def forward(self, predict, target):
        pt = F.softmax(predict, dim=1) # softmmax获取预测概率
        class_mask = F.one_hot(target, self.class_num) #获取target的one hot编码
        ids = target.view(-1, 1) 
        alpha = self.alpha[ids.data.view(-1)] # 注意,这里的alpha是给定的一个list(tensor
#),里面的元素分别是每一个类的权重因子
        probs = (pt * class_mask).sum(1).view(-1, 1) # 利用onehot作为mask,提取对应的pt
        log_p = probs.log()
# 同样,原始ce上增加一个动态权重衰减因子
        loss = -alpha * (torch.pow((1 - probs), self.gamma)) * log_p

        if self.reduction == 'mean':
            loss = loss.mean()
        elif self.reduction == 'sum':
            loss = loss.sum()
        return loss

另外,最近比较关注的是:CNN相关的操作,我本来是认为CNN卷积核能够包络邻近信息,这对于长实体识别也许是一定优势(毕竟,现在的方法多是只考虑[head_information,tail_information]的cat),但发现,这里的好多改进,在于pool,出现了max_pool,average_pool,动态最小、最大池化、softpool,还有对角线那种的pool等等。https://blog.csdn.net/weixin_42764932/article/details/112515715https://blog.csdn.net/qq_41487299/article/details/105815782
这种从左向右,从上到下的pool方式,这符合了langauge的习惯,我觉得,是可以借鉴的,无奈水平有限,没有实现。(源码是可以找到的,C++编译的,我环境还没有配置好,所以,搁浅了)
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YingJingh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值