在Pytorch(Triplet网络)上实现变化损耗系数

时间:2020-06-30 19:43:55

标签: python pytorch

我最近一直在从事有监督的对比学习。在使用triplet loss进行图像分类的几次实验之后,我决定实现一个新功能,以增加此三重态损失的额外损失。此函数使用变异系数(stddev / mean),我的想法是基于本文的:

Learning 3D Keypoint Descriptors for Non-Rigid Shape Matching

他们的GitHub存储库是here,但我认为它的文档记录不是很好。

去年我一直在研究Pytorch,但仍然很难完全理解如何正确创建损失函数。这是我写的损失函数:

class CoefficientVariationLoss(nn.Module):
    def __init__(self, class_to_idx, weighted=False):
        super(CoefficientVariationLoss, self).__init__()
        self.class_to_idx = class_to_idx
        self.weighted = weighted

    def forward(self, x, labels):
        total_coeff_variation = 0
        l2_norm_positive = F.pairwise_distance(x[0], x[1],2)

        for c in self.class_to_idx.values():
            count_label_pos = torch.sum(labels[0]==c).float()
            if count_label_pos <= 1:
                class_cv = 0
            else:
                class_pos = l2_norm_positive[labels[0]==c]

                if self.weighted:
                    weight = count_label_pos/labels[0].shape[0]
                    class_cv = (torch.std(class_pos)/torch.mean(class_pos))*weight
                else:
                    class_cv = (torch.std(class_pos)/torch.mean(class_pos))
                
                # if torch.isnan(class_cv):
                #     class_cv = 0

            total_coeff_variation += class_cv

        return total_coeff_variation

此功能的两个输入是:

  • x:x [0],x [1]和x [2]是三元组(锚,正,负)的嵌入
  • labels:labels [0],labels [1]和labels [2]是三元组中每个元素的类别(锚,正,负)

我的自定义数据加载器正在将数据作为字典提供:

sample = {'images': [...], 'labels': [...]}

和我的模型(三重态网络)的输出是张量的列表,其顺序相同:锚,正和负。

最终损失最终计算为

loss = loss_triplet + FACTOR * loss_coeffVariation

我是否正确地造成了这种损失?由于差异性问题,我不知道是否可以在损失函数中使用索引...

谢谢!

0 个答案:

没有答案