如何理解与看待在cvpr2020中提出的circle loss?与triplet loss的关系

总结

这篇在Arcface loss之后出的,比Arcface多了对正负样本的balance策略

\mathcal{L}_{\text{circle}} = \log \left[ 1 + \sum_{i=1}^{K} \sum_{j=1}^{L} \exp(\gamma (\alpha_n^j s_n^j - \alpha_p^i s_p^i )) \right] \\ = \log \left[ 1 + \sum_{j=1}^{L} \exp(\gamma \alpha_n^j s_n^j ) \sum_{i=1}^{K} \exp(-\gamma \alpha_p^i s_p^i ), \right]

\mathcal{L}_{\text{circle}} = \log \left[ 1 + \sum_{j=1}^{L} \exp (\gamma \alpha_n^j (s_n^j - \Delta_n)) \sum_{i=1}^{K} \exp (-\gamma \alpha_p^i (s_p^i - \Delta_p)) \right]

公式里的ap,sp,delta_n,delta_p和代码里一样,sp和sn表示正负样本的Embedding,ap和an是sp和sp前面的加权系数,为了balance正负样本,delta_n和delta_p是为了拉开正负样本的间距

代码摘自https://github.com/layumi/Person_reID_baseline_pytorch/blob/478c70923f40945c68fea3b34064998a8af2ba69/circle_loss.py#L22

#from https://github.com/TinyZeaMays/CircleLoss/blob/master/circle_loss.py 

from typing import Tuple

import torch
from torch import nn, Tensor


def convert_label_to_similarity(normed_feature: Tensor, label: Tensor) -> Tuple[Tensor, Tensor]:
    similarity_matrix = normed_feature @ normed_feature.transpose(1, 0)
    label_matrix = label.unsqueeze(1) == label.unsqueeze(0)

    positive_matrix = label_matrix.triu(diagonal=1) # 主对角线上移一位
    negative_matrix = label_matrix.logical_not().triu(diagonal=1)

    similarity_matrix = similarity_matrix.view(-1)
    positive_matrix = positive_matrix.view(-1)
    negative_matrix = negative_matrix.view(-1)
    # import pdb; pdb.set_trace();
    return similarity_matrix[positive_matrix], similarity_matrix[negative_matrix]


class CircleLoss(nn.Module):
    def __init__(self, m: float, gamma: float) -> None:
        super(CircleLoss, self).__init__()
        self.m = m
        self.gamma = gamma
        self.soft_plus = nn.Softplus() # \text{Softplus}(x) = \frac{1}{\beta} \log(1 + \exp(\beta x)),可以看成是relu的平滑版本

    def forward(self, sp: Tensor, sn: Tensor) -> Tensor:
        # 0和1相似,所以sp的shape是size(1);0和1,0和2不相似,所以sn的shape是size(2)
        print('sp={} sn={}'.format(sp, sn))  # sp=tensor([0.4792], grad_fn=<IndexBackward0>) sn=tensor([0.7567, 0.7183], grad_fn=<IndexBackward0>)
        ap = torch.clamp_min(-sp.detach() + 1 + self.m, min=0.) #ap是sp的衰减因子,非常粗暴的用clip(1-sp+margin)来定
        an = torch.clamp_min(sn.detach() + self.m, min=0.) #同理,an是sn的衰减因子
        print('ap={} an={}'.format(ap, an))  # ap=tensor([0.3570]) an=tensor([1.1160, 1.2385])
        

        delta_p = 1 - self.m
        delta_n = self.m

        logit_p = - ap * (sp - delta_p) * self.gamma
        logit_n = an * (sn - delta_n) * self.gamma
        import pdb; pdb.set_trace();
        loss = self.soft_plus(torch.logsumexp(logit_n, dim=0) + torch.logsumexp(logit_p, dim=0))

        return loss


if __name__ == "__main__":
    feat = nn.functional.normalize(torch.rand(3, 4, requires_grad=True))
    # lbl = torch.randint(high=4, size=(3,))
    lbl = torch.LongTensor([1,1,0]) 
    
    inp_sp, inp_sn = convert_label_to_similarity(feat, lbl)

    criterion = CircleLoss(m=0.25, gamma=256)
    circle_loss = criterion(inp_sp, inp_sn)

    print(circle_loss) # 输出 tensor(239.7694, grad_fn=<SoftplusBackward0>)

triplet loss

以上转载自: Triplet loss学习笔记 - 知乎

circle loss

以下转载自: 如何理解与看待在cvpr2020中提出的circle loss? - 知乎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值