百度框架paddlepaddle实现改进三元组损失batch hard Triplet Loss

 

import paddle.fluid as fluid

def batch_hard_triplet_loss(input, y_true, margin,batch_size):
    """
    :param input: shape:[batch,feacture]
    :param y_true:shape:[batch,1],y_true is label
    :param margin:float
    :param batch_size:batch大小
    :return:tript_loss,shape:float
    """
    # y_true shape [64, 1]
    # y_true.t() shape [1, 64]
    # pos_mask shape [64, 64], 矩阵中对角线上值为1
    # pos_mask矩阵中 若[2,3]位置为1,代表labels中第2个值和第3个值得label相同
    y_true_trans = fluid.layers.transpose(y_true, [1, 0])
    y_true_trans_matrix = fluid.layers.concat([y_true_trans] * batch_size, axis=0)
    pos_mask = fluid.layers.cast(
        fluid.layers.equal(y_true_trans_matrix, y_true), "float32")

    def _mask_max(input_tensor, mask, axis=None, keepdims=False):
        # mask = 1(相同) 距离=input_tensor - 0
        # mask = 0(不同) 距离=input_tensor - 1
        # 距离最远的pos对
        input_tensor = input_tensor-(1-mask)*1e6
        _max = fluid.layers.reduce_max(input_tensor, dim=axis, keep_dim=keepdims)
        return _max

    def _mask_min(input_tensor, mask, axis=None, keepdims=False):
        input_tensor=input_tensor+mask*1e6
        _min = fluid.layers.reduce_min(input_tensor, dim=axis, keep_dim=keepdims)
        return _min


    a=fluid.layers.reduce_sum(fluid.layers.pow(input, 2.0), dim=1, keep_dim=True)
    b=fluid.layers.reduce_sum(fluid.layers.pow(fluid.layers.transpose(input, [1, 0]), 2.0), dim=0,keep_dim=True)
    b_matrix=fluid.layers.concat([b]*batch_size,axis=0)

    dist_squared=(b_matrix+a)-2*fluid.layers.matmul(input, input,transpose_y=True)
    dist=fluid.layers.elementwise_max(dist_squared,fluid.layers.fill_constant([1],dtype='float32',value=1e-16))
    dist = fluid.layers.sqrt(dist)#欧式距离

    pos_max = _mask_max(dist, pos_mask, axis=-1,keepdims=True)#pos_max.shape:(batch_size,1)
    neg_min = _mask_min(dist, pos_mask, axis=-1,keepdims=True)#neg_min.shape:(batch_size,1)

    basic_loss = (pos_max-neg_min)+margin#曼哈顿距离+margin
    #截断triplet_loss损失一***********************************************
    # clip_loss=fluid.layers.relu(basic_loss)
    # loss = fluid.layers.reduce_mean(clip_loss,dim=0)

    #log(1+exp(x))triplet_loss损失二**************************************
    loss = fluid.layers.reduce_mean(
        fluid.layers.log(1+fluid.layers.exp(basic_loss)), dim=0)
    # loss=fluid.layers.reduce_mean(
    #     fluid.layers.log(fluid.layers.elementwise_add(
    #         fluid.layers.exp(basic_loss),fluid.layers.fill_constant([1],dtype='float32',value=1))),dim=0)

    return loss

函数输入input是神经网络输出层的值,维度为[batch_size,feacture],y_true为标签,即batch_size个输出中每一个输出的类别,维度为[batch_size,1].

batch hard Triplet Loss的数学表述为:

tripletLoss数学公式

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AdaReg Loss是一种用于标签平衡的损失函数,其主要作用是解决类别分布不均匀的问题。在这里,我们以ConvNeXt v2模型为例,介绍如何在PyTorch中实现AdaReg Loss。 首先,我们需要定义AdaReg Loss的公式: $$ \text{AdaRegLoss} = \frac{1}{N}\sum_{i=1}^{N}\left(\alpha\cdot\frac{\text{CELoss}(x_i, y_i)}{1 + \exp(-\beta\cdot(p_i - \gamma))} + (1 - \alpha)\cdot\frac{\text{FocalLoss}(x_i, y_i)}{1 + \exp(\beta\cdot(p_i - \gamma))}\right) $$ 其中,CELoss表示交叉熵损失函数,FocalLoss表示Focal Loss函数,$x_i$表示模型的输出,$y_i$表示真实标签,$p_i$表示模型对样本$i$属于正类的预测概率,$\alpha$表示交叉熵损失函数的权重,$\beta$和$\gamma$是两个超参数,用于调整AdaReg Loss的形状。 接着,我们可以按照以下步骤实现AdaReg Loss: 1. 从PyTorch中导入所需的库和模块: ```python import torch import torch.nn as nn import torch.nn.functional as F ``` 2. 定义AdaReg Loss类,并继承自nn.Module: ```python class AdaRegLoss(nn.Module): def __init__(self, alpha=0.5, beta=4, gamma=0.5, reduction='mean'): super(AdaRegLoss, self).__init__() self.alpha = alpha self.beta = beta self.gamma = gamma self.reduction = reduction self.ce_loss = nn.CrossEntropyLoss(reduction='none') self.focal_loss = FocalLoss(reduction='none') ``` 在这里,我们定义了三个超参数alpha、beta和gamma,以及一个reduction参数,用于指定如何对batch中的损失进行平均。我们还定义了两个损失函数:交叉熵损失函数和Focal Loss函数。 3. 实现AdaReg Loss的前向传播函数: ```python def forward(self, inputs, targets): ce_loss = self.ce_loss(inputs, targets) pt = torch.exp(-ce_loss) focal_loss = self.focal_loss(inputs, targets) alpha_t = self.alpha * pt / (1 + torch.exp(-self.beta * (pt - self.gamma))) loss = alpha_t * ce_loss + (1 - alpha_t) * focal_loss if self.reduction == 'mean': loss = torch.mean(loss) elif self.reduction == 'sum': loss = torch.sum(loss) return loss ``` 在这里,我们首先计算交叉熵损失函数和Focal Loss函数。然后,我们计算每个样本的权重alpha_t,并将其应用于交叉熵损失函数和Focal Loss函数。最后,我们根据reduction参数将batch中的损失进行平均或求和。 4. 将AdaReg Loss应用于ConvNeXt v2模型中: ```python class ConvNeXtV2(nn.Module): def __init__(self, num_classes=10): super(ConvNeXtV2, self).__init__() # define the model architecture ... # define the loss function self.loss_fn = AdaRegLoss(alpha=0.5, beta=4, gamma=0.5, reduction='mean') def forward(self, x, targets=None): # define the forward pass ... if targets is not None: loss = self.loss_fn(output, targets) return output, loss else: return output ``` 在这里,我们定义了一个ConvNeXt v2模型,并将AdaReg Loss作为其损失函数。在模型的前向传播函数中,如果传入了真实标签,我们就计算AdaReg Loss,并返回输出和损失;否则,我们只返回输出。 最后,我们可以使用类似以下的代码来训练ConvNeXt v2模型,并使用AdaReg Loss作为其损失函数: ```python model = ConvNeXtV2(num_classes=10) optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) for epoch in range(num_epochs): for images, labels in train_loader: images = images.to(device) labels = labels.to(device) optimizer.zero_grad() output, loss = model(images, labels) loss.backward() optimizer.step() ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值