精华内容
下载资源
问答
  • CenterLoss
    2021-01-26 14:20:15

    CenterLoss

    CenterLoss是干嘛的?

    我们知道:对于图像的分类问题,我们通常使用softmax来计算损失在这里插入图片描述

    上图就是我们使用softmax对手写数字图像进行不同数字进行颜色的分类

    如果我们在softmax损失的基础上添加上一个centerloss损失,那么对于手写数字图像的分类就如下图所示了

    更多相关内容
  • crnn_ctc-centerloss 2020.12.27更新 使用最后一层全连接层输入的功能作为处理对象,即缩小这一功能的类内距离 实现功能和标签的对齐,主要解决了预测重复,预测漏字时的对齐问题(需要tf1.15) 增加对关键指标的...
  • MNIST特征提取解释图像识别之CenterLoss 一、提出问题  在图像识别中,一个很关键的要素就是图像中提取出来的特征,它关乎着图像识别的精准度。而通常用的softmax输出函数提取到的特征之间往往接的很紧,无太大的...
  • center loss

    2020-03-09 18:20:57
    论文:A Discriminative Feature Learning Approach for Deep Face Recognition 0 摘要 本文为人脸识别任务提出了center loss,可以为每一...将center loss和softmax loss结合,可以得到类内聚合、类间远离的深度特...

    论文:A Discriminative Feature Learning Approach for Deep Face Recognition

    0 摘要

    本文为人脸识别任务提出了center loss,可以为每一个人脸类别学习特征中心并惩罚远离中心点的离群样本。center loss使用CNN训练时易于收敛。将center loss和softmax loss结合,可以得到类内聚合、类间远离的深度特征,用于完成人脸识别任务。实验证明center loss取得了在当时领先的人脸验证和识别结果。

    1 简介

    在这里插入图片描述人脸识别任务是开集识别,不可能所有要识别的人脸都参与了训练,所以学习到的深度特征不能够仅仅是可分的,还应该是有判别力的。softmax损失仅仅保证了特征可分,这对于人脸识别任务来说是不够的。

    由于训练CNN的时候,使用的SGD是基于一个mini-batch来计算梯度的,并不能够反映全局的特征分布情况。但是训练集又很大,计算全部样本的梯度进行迭代也不现实。前面提出了对比损失和三元组损失来计算样本对和样本三元组的损失值,但是构建样本对和三元组会增加训练样本的数量,减慢了模型的训练过程,并且构建三元组的技巧性也比较强。

    本文作者提出的center loss,在最小化样本特征和其隶属的类中心距离的同时更新样本类的特征中心。训练CNN的时候同时使用softmax loss和center loss,使用一个额外的超参数控制两项损失的加权。物理意义是,softmax loss负责让不同的类可分,而center loss负责让同一类的样本的特征尽可能靠近类别中心。通过联合使用,不仅类间距离变大,类内的变化也在减小,加强了特征的判别能力

    2 本文方法

    2.1 A toy example

    使用MNIST数据集,使用修改后的LeNet网络,网络的最后一个全连接层的输出神经元数量为2以方便可视化,使用softmax损失,绘制不同图像前向计算后的特征的分布情况。结果如下图:
    在这里插入图片描述在这里插入图片描述从上图可以得到两个结论:

    • softmax损失的确可以使得学习的特征可分;
    • 但使用softmax损失学习的特征类内变化很大,不适合于人脸识别任务。

    2.2 center loss

    鉴于上面softmax loss的缺点,作者想到改进的损失应该是在保证特征可分的情况下最小化同类特征的类内变化。因此,提出了center loss,如下式:

    在这里插入图片描述 C y i C_{y_i} Cyi表示第 y i y_i yi类的特征中心。这个公式的目的是为了减少类内的变化。

    理想情况下, C y i C_{y_i} Cyi应该随着特征的改变而改变,也就是说需要计算整个训练样本集的特征,然后根据每个样本的类别才能计算得到类别中心 C y i C_{y_i} Cyi,但这样计算类别中心的方式效率低,不现实。因此,类别中心不可以直接使用。

    作者提出了两项修改

    1. 不是基于整个训练样本集计算类别中心 C y i C_{y_i} Cyi,而是基于各mini-batch去计算类别中心,就是基于当前mini-batch中所包含的样本去修正其对应的类别的中心;
    2. 为了避免少数误标记样本造成的类别中心的扰动,使用一个标量 α \alpha α控制类别中心的学习率

    在这里插入图片描述 δ \delta δ是示性函数。

    总的损失为:
    在这里插入图片描述整个的算法过程为:
    在这里插入图片描述不同 λ \lambda λ值时学习到的特征的分布情况,可以看出 λ \lambda λ值越大,越强调center loss,学习到的特征越内聚。

    在这里插入图片描述

    2.3 讨论

    使用两项损失联合学习的必要性:如果只使用softmax loss,学习到的特征内聚程度不足;如果只使用center loss,学习到的各类特征和其类别中心会收敛到0(此时center loss值最小,为0)。单独使用任一个loss都不会取得好的结果,因此需要两个损失联合使用;
    center loss和对比损失、三元组损失比较:对比损失和三元组损失构建的训练样本对会指数级增长,center loss不需要有这个担心。

    3 实验

    不同 λ \lambda λ α \alpha α值的影响
    在这里插入图片描述 λ = 0 \lambda=0 λ=0时,等于只使用softmax loss,从上左图可以看出,结合使用softmax loss和center loss( λ > 0 \lambda > 0 λ>0)时效果要更好,说明了联合使用两个损失的必要性;上面右图反映 α \alpha α值在很大范围内变动时都可以取得比较好的验证准确率。下面使用中设置 λ = 0.003 , α = 0.5 \lambda = 0.003,\alpha=0.5 λ=0.003,α=0.5

    在这里插入图片描述modelA表示只使用softmax loss,modelB表示联合使用softmax loss和contrastive loss,modelC表示联合使用softmax loss和center loss,从上表的结果证明了作者提出的联合使用softmax loss和center loss的先进性。

    在MegaFace上的实验结果
    人脸识别:绘制了在不同规模的gallary set的情况下,识别准确率的CMC曲线:

    在这里插入图片描述左图是在gallary set为1 million规模的情况下,top-1、top-10,…,top-1000000的准确率,可以看到softmax loss + center loss的曲线位于最上方。右图是在gallary set为10000规模的情况下,top-1、top-10,…,top-10000的准确率,可以看到softmax loss + center loss的曲线位于最上方。

    人脸验证
    在这里插入图片描述左图是1百万规模的gallary数据集情况下,不同FAR时的TAR值,右图是1万规模的gallary数据集情况下,不同FAR时的TAR值,可以看出作者提出的softmax loss + center loss的曲线都是位于最上方。

    在这里插入图片描述在这里插入图片描述

    展开全文
  • Hetero-Center Loss for Cross-Modality Person Re-Identification 当前的问题及概述: 目前所有的框架都在解决跨模态差异问题,很少有研究探讨改进类内跨模态相似性。 本文提出了一个新的损失函数,称为异中心损失...
  • Center Loss

    千次阅读 2020-07-09 18:44:17
      可鉴别性的特征学习用于人脸识别,对每个类别维护一个Center vector,然后对损失函数增加一项到Center向量的L2损失。使得各个类别的类内分布变小实现intra-class的compactness,从而特征更具区分性,对于人脸...

    《A Discriminative Feature Learning Approach for Deep Face Recognition》


      可鉴别性的特征学习用于人脸识别,对每个类别维护一个Center vector,然后对损失函数增加一项到Center向量的L2损失。使得各个类别的类内分布变小实现intra-class的compactness,从而特征更具区分性,对于人脸识别来说能够增大识别的把握。


    Key Words:Convolutional neural networks 、Face recognition、Discriminative feature learning、 Center loss


    ECCV, 2016

    作者:Yandong Wen,Kaipeng Zhang,Zhifeng Li…

    https://github.com/jxgu1016/MNIST_center_loss_pytorch

    Agile Pioneer  

    提出问题

      我们在做neural network 训练的时候一般使用的都是softmax loss,softmax loss能够有效的区分开inter-class,让我的分类任务得到解决,但是softmax loss的局限在于它只能get到inter-class的difference。

      softmax loss的问题是不能够get到intra-class的compactness,所以论文中用MNIST为例把deep feature的dimension改成2方便可视化如上图。可以看出我们用softmax loss能够把inter-class的bound找到,但是每个类别仍然存在很大的类内误差,这是不利于我们用这个特征来识别的尤其是对人脸识别来说,验证是困难的,因此作者提出了center loss来解决这个问题。

    softmax loss 和 center loss联合

      通过添加center loss 让简单的softmax 能够训练出更有类内紧密性的特征

      下图是使用softmax loss结合center loss后产生的deep feature的distribution,我们能够发现deep feature在学习到了如果区分类间差异的同时也缩小了类内差异,通过不同的lamada值能够产生不同的效果,看这个图能给出的启示是可以用这个特征利用kmeans做一个完美的聚类分析,得到一个高效的类别,对于细分任务是有帮助的。

    计算Center Vector

      如果想计算一个类别所有样本的中心,那么一定要通过计算该类别所有的样本才行,但是我们在真实的模型训练当中每次都用全量数据去训练是不现实的,都是用mini-batch的方式来训练的,所以我们在每轮迭代计算center loss的同时也要更新center vector。

      给每一个类别都训练出来一个center vector其shape和deep feature要保证一样,然后在训练过程中对比样本的deep feature和center vector,计算欧氏距离得到的loss和softmax loss一起去更新参数。

    MNIST做实验

    Only softmax loss

    Add center loss

    参数设置

    α \alpha α一般取0.5,是CenterVector更新的参数

    λ \lambda λ一般取0.1-0.0001之间,需要实验调参,用于loss中占比的参数

    实现参考https://github.com/KaiyangZhou/pytorch-center-loss

    展开全文
  • 人脸识别算法,结合facenet网络结构和center loss作为损失,基于tensorflow框架,含训练和测试代码,支持从头训练和摄像头测试
  •   ...Center Loss论文:Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. pytorh版本地址:https://github.com/KaiyangZhou/pytorch-center

              最近在测试Center Loss在图像分类上的性能,以此记录一下学习历程。

    Center Loss论文:Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016.
    pytorh版本地址:https://github.com/KaiyangZhou/pytorch-center-loss

    我使用的图像分类算法是EfficientNet-V2-L版本,使用SoftMax+Center Loss进行图像分类。具体代码为:

    1、模型结构

    efficient_v2_model.py

    from collections import OrderedDict
    from functools import partial
    from typing import Callable, Optional
    
    import torch.nn as nn
    import torch
    from torch import Tensor
    
    
    def drop_path(x, drop_prob: float = 0., training: bool = False):
        """
        Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).
        "Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdf
        This function is taken from the rwightman.
        It can be seen here:
        https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/layers/drop.py#L140
        """
        if drop_prob == 0. or not training:
            return x
        keep_prob = 1 - drop_prob
        shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets
        random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
        random_tensor.floor_()  # binarize
        output = x.div(keep_prob) * random_tensor
        return output
    
    
    class DropPath(nn.Module):
        """
        Drop paths (Stochastic Depth) per sample  (when applied in main path of residual blocks).
        "Deep Networks with Stochastic Depth", https://arxiv.org/pdf/1603.09382.pdf
        """
        def __init__(self, drop_prob=None):
            super(DropPath, self).__init__()
            self.drop_prob = drop_prob
    
        def forward(self, x):
            return drop_path(x, self.drop_prob, self.training)
    
    
    class ConvBNAct(nn.Module):
        def __init__(self,
                     in_planes: int,
                     out_planes: int,
                     kernel_size: int = 3,
                     stride: int = 1,
                     groups: int = 1,
                     norm_layer: Optional[Callable[..., nn.Module]] = None,
                     activation_layer: Optional[Callable[..., nn.Module]] = None):
            super(ConvBNAct, self).__init__()
    
            padding = (kernel_size - 1) // 2
            if norm_layer is None:
                norm_layer = nn.BatchNorm2d
            if activation_layer is None:
                activation_layer = nn.SiLU  # alias Swish  (torch>=1.7)
    
            self.conv = nn.Conv2d(in_channels=in_planes,
                                  out_channels=out_planes,
                                  kernel_size=kernel_size,
                                  stride=stride,
                                  padding=padding,
                                  groups=groups,
                                  bias=False)
    
            self.bn = norm_layer(out_planes)
            self.act = activation_layer()
    
        def forward(self, x):
            result = self.conv(x)
            result = self.bn(result)
            result = self.act(result)
    
            return result
    
    
    class SqueezeExcite(nn.Module):
        def __init__(self,
                     input_c: int,   # block input channel
                     expand_c: int,  # block expand channel
                     se_ratio: float = 0.25):
            super(SqueezeExcite, self).__init__()
            squeeze_c = int(input_c * se_ratio)
            self.conv_reduce = nn.Conv2d(expand_c, squeeze_c, 1)
            self.act1 = nn.SiLU()  # alias Swish
            self.conv_expand = nn.Conv2d(squeeze_c, expand_c, 1)
            self.act2 = nn.Sigmoid()
    
        def forward(self, x: Tensor) -> Tensor:
            scale = x.mean((2, 3), keepdim=True)
            scale = self.conv_reduce(scale)
            scale = self.act1(scale)
            scale = self.conv_expand(scale)
            scale = self.act2(scale)
            return scale * x
    
    
    class MBConv(nn.Module):
        def __init__(self,
                     kernel_size: int,
                     input_c: int,
                     out_c: int,
                     expand_ratio: int,
                     stride: int,
                     se_ratio: float,
                     drop_rate: float,
                     norm_layer: Callable[..., nn.Module]):
            super(MBConv, self).__init__()
    
            if stride not in [1, 2]:
                raise ValueError("illegal stride value.")
    
            self.has_shortcut = (stride == 1 and input_c == out_c)
    
            activation_layer = nn.SiLU  # alias Swish
            expanded_c = input_c * expand_ratio
    
            # 在EfficientNetV2中,MBConv中不存在expansion=1的情况所以conv_pw肯定存在
            assert expand_ratio != 1
            # Point-wise expansion
            self.expand_conv = ConvBNAct(input_c,
                                         expanded_c,
                                         kernel_size=1,
                                         norm_layer=norm_layer,
                                         activation_layer=activation_layer)
    
            # Depth-wise convolution
            self.dwconv = ConvBNAct(expanded_c,
                                    expanded_c,
                                    kernel_size=kernel_size,
                                    stride=stride,
                                    groups=expanded_c,
                                    norm_layer=norm_layer,
                                    activation_layer=activation_layer)
    
            self.se = SqueezeExcite(input_c, expanded_c, se_ratio) if se_ratio > 0 else nn.Identity()
    
            # Point-wise linear projection
            self.project_conv = ConvBNAct(expanded_c,
                                          out_planes=out_c,
                                          kernel_size=1,
                                          norm_layer=norm_layer,
                                          activation_layer=nn.Identity)  # 注意这里没有激活函数,所有传入Identity
    
            self.out_channels = out_c
    
            # 只有在使用shortcut连接时才使用dropout层
            self.drop_rate = drop_rate
            if self.has_shortcut and drop_rate > 0:
                self.dropout = DropPath(drop_rate)
    
        def forward(self, x: Tensor) -> Tensor:
            result = self.expand_conv(x)
            result = self.dwconv(result)
            result = self.se(result)
            result = self.project_conv(result)
    
            if self.has_shortcut:
                if self.drop_rate > 0:
                    result = self.dropout(result)
                result += x
    
            return result
    
    
    class FusedMBConv(nn.Module):
        def __init__(self,
                     kernel_size: int,
                     input_c: int,
                     out_c: int,
                     expand_ratio: int,
                     stride: int,
                     se_ratio: float,
                     drop_rate: float,
                     norm_layer: Callable[..., nn.Module]):
            super(FusedMBConv, self).__init__()
    
            assert stride in [1, 2]
            assert se_ratio == 0
    
            self.has_shortcut = stride == 1 and input_c == out_c
            self.drop_rate = drop_rate
    
            self.has_expansion = expand_ratio != 1
    
            activation_layer = nn.SiLU  # alias Swish
            expanded_c = input_c * expand_ratio
    
            # 只有当expand ratio不等于1时才有expand conv
            if self.has_expansion:
                # Expansion convolution
                self.expand_conv = ConvBNAct(input_c,
                                             expanded_c,
                                             kernel_size=kernel_size,
                                             stride=stride,
                                             norm_layer=norm_layer,
                                             activation_layer=activation_layer)
    
                self.project_conv = ConvBNAct(expanded_c,
                                              out_c,
                                              kernel_size=1,
                                              norm_layer=norm_layer,
                                              activation_layer=nn.Identity)  # 注意没有激活函数
            else:
                # 当只有project_conv时的情况
                self.project_conv = ConvBNAct(input_c,
                                              out_c,
                                              kernel_size=kernel_size,
                                              stride=stride,
                                              norm_layer=norm_layer,
                                              activation_layer=activation_layer)  # 注意有激活函数
    
            self.out_channels = out_c
    
            # 只有在使用shortcut连接时才使用dropout层
            self.drop_rate = drop_rate
            if self.has_shortcut and drop_rate > 0:
                self.dropout = DropPath(drop_rate)
    
        def forward(self, x: Tensor) -> Tensor:
            if self.has_expansion:
                result = self.expand_conv(x)
                result = self.project_conv(result)
            else:
                result = self.project_conv(x)
    
            if self.has_shortcut:
                if self.drop_rate > 0:
                    result = self.dropout(result)
    
                result += x
    
            return result
    
    
    class EfficientNetV2(nn.Module):
        def __init__(self,
                     model_cnf: list,
                     num_classes: int = 1000,
                     num_features: int = 1280,
                     dropout_rate: float = 0.2,
                     drop_connect_rate: float = 0.2):
            super(EfficientNetV2, self).__init__()
    
            for cnf in model_cnf:
                assert len(cnf) == 8
    
            norm_layer = partial(nn.BatchNorm2d, eps=1e-3, momentum=0.1)
    
            stem_filter_num = model_cnf[0][4]
    
            self.stem = ConvBNAct(3,
                                  stem_filter_num,
                                  kernel_size=3,
                                  stride=2,
                                  norm_layer=norm_layer)  # 激活函数默认是SiLU
    
            total_blocks = sum([i[0] for i in model_cnf])
            block_id = 0
            blocks = []
            for cnf in model_cnf:
                repeats = cnf[0]
                op = FusedMBConv if cnf[-2] == 0 else MBConv
                for i in range(repeats):
                    blocks.append(op(kernel_size=cnf[1],
                                     input_c=cnf[4] if i == 0 else cnf[5],
                                     out_c=cnf[5],
                                     expand_ratio=cnf[3],
                                     stride=cnf[2] if i == 0 else 1,
                                     se_ratio=cnf[-1],
                                     drop_rate=drop_connect_rate * block_id / total_blocks,
                                     norm_layer=norm_layer))
                    block_id += 1
            self.blocks = nn.Sequential(*blocks)
    
            head_input_c = model_cnf[-1][-3]
    
            head = OrderedDict()
    
            head.update({"project_conv": ConvBNAct(head_input_c,
                                                   num_features,
                                                   kernel_size=1,
                                                   norm_layer=norm_layer)})  # 激活函数默认是SiLU
    
            head.update({"avgpool": nn.AdaptiveAvgPool2d(1)})
            head.update({"flatten": nn.Flatten()})
    
            if dropout_rate > 0:
                head.update({"dropout": nn.Dropout(p=dropout_rate, inplace=True)})
            head.update({"classifier": nn.Linear(num_features, num_classes)})
    
            self.head = nn.Sequential(head)
    
            # initial weights
            for m in self.modules():
                if isinstance(m, nn.Conv2d):
                    nn.init.kaiming_normal_(m.weight, mode="fan_out")
                    if m.bias is not None:
                        nn.init.zeros_(m.bias)
                elif isinstance(m, nn.BatchNorm2d):
                    nn.init.ones_(m.weight)
                    nn.init.zeros_(m.bias)
                elif isinstance(m, nn.Linear):
                    nn.init.normal_(m.weight, 0, 0.01)
                    nn.init.zeros_(m.bias)
    
        def forward(self, x):
            x = self.stem(x)
            x = self.blocks(x)
            out = self.head(x)
            feat = list(self.head.modules())[0][0:3](x)
            return feat,out
    
    
    def efficientnetv2_s(num_classes: int = 1000):
        """
        EfficientNetV2
        https://arxiv.org/abs/2104.00298
        """
        # train_size: 300, eval_size: 384
    
        # repeat, kernel, stride, expansion, in_c, out_c, operator, se_ratio
        model_config = [[2, 3, 1, 1, 24, 24, 0, 0],
                        [4, 3, 2, 4, 24, 48, 0, 0],
                        [4, 3, 2, 4, 48, 64, 0, 0],
                        [6, 3, 2, 4, 64, 128, 1, 0.25],
                        [9, 3, 1, 6, 128, 160, 1, 0.25],
                        [15, 3, 2, 6, 160, 256, 1, 0.25]]
    
        model = EfficientNetV2(model_cnf=model_config,
                               num_classes=num_classes,
                               dropout_rate=0.2)
        return model
    
    
    def efficientnetv2_m(num_classes: int = 1000):
        """
        EfficientNetV2
        https://arxiv.org/abs/2104.00298
        """
        # train_size: 384, eval_size: 480
    
        # repeat, kernel, stride, expansion, in_c, out_c, operator, se_ratio
        model_config = [[3, 3, 1, 1, 24, 24, 0, 0],
                        [5, 3, 2, 4, 24, 48, 0, 0],
                        [5, 3, 2, 4, 48, 80, 0, 0],
                        [7, 3, 2, 4, 80, 160, 1, 0.25],
                        [14, 3, 1, 6, 160, 176, 1, 0.25],
                        [18, 3, 2, 6, 176, 304, 1, 0.25],
                        [5, 3, 1, 6, 304, 512, 1, 0.25]]
    
        model = EfficientNetV2(model_cnf=model_config,
                               num_classes=num_classes,
                               dropout_rate=0.3)
        return model
    
    
    def efficientnetv2_l(num_classes: int = 1000):
        """
        EfficientNetV2
        https://arxiv.org/abs/2104.00298
        """
        # train_size: 384, eval_size: 480
    
        # repeat, kernel, stride, expansion, in_c, out_c, operator, se_ratio
        model_config = [[4, 3, 1, 1, 32, 32, 0, 0],
                        [7, 3, 2, 4, 32, 64, 0, 0],
                        [7, 3, 2, 4, 64, 96, 0, 0],
                        [10, 3, 2, 4, 96, 192, 1, 0.25],
                        [19, 3, 1, 6, 192, 224, 1, 0.25],
                        [25, 3, 2, 6, 224, 384, 1, 0.25],
                        [7, 3, 1, 6, 384, 640, 1, 0.25]]
    
        model = EfficientNetV2(model_cnf=model_config,
                               num_classes=num_classes,
                               dropout_rate=0.4)
        return model
    

    2、Center Loss损失

    center_loss.py

    import torch
    import torch.nn as nn
    from torch.autograd.function import Function
    import torch.nn.functional as F
    from torch.autograd import Variable
    
    
    class CenterLoss(nn.Module):
        """Center loss.
    
        Reference:
        Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016.
    
        Args:
            num_classes (int): number of classes.
            feat_dim (int): feature dimension.
        """
    
        def __init__(self, num_classes=10, feat_dim=2, use_gpu=False):
            super(CenterLoss, self).__init__()
            self.num_classes = num_classes
            self.feat_dim = feat_dim
            self.use_gpu = use_gpu
    
            if self.use_gpu:
                self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim).cuda())
            else:
                self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim))
    
        def forward(self, x, labels):
            """
            Args:
                x: feature matrix with shape (batch_size, feat_dim).
                labels: ground truth labels with shape (batch_size).
            """
            batch_size = x.size(0)
            distmat = torch.pow(x, 2).sum(dim=1, keepdim=True).expand(batch_size, self.num_classes) + \
                      torch.pow(self.centers, 2).sum(dim=1, keepdim=True).expand(self.num_classes, batch_size).t()
            distmat.addmm_(1, -2, x, self.centers.t())
    
            classes = torch.arange(self.num_classes).long()
            if self.use_gpu: classes = classes.cuda()
            labels = labels.unsqueeze(1).expand(batch_size, self.num_classes)
            mask = labels.eq(classes.expand(batch_size, self.num_classes))
    
            dist = distmat * mask.float()
            loss = dist.clamp(min=1e-12, max=1e+12).sum() / batch_size
    
            return loss
    
    

    3、模型训练

    import argparse
    import os
    import time
    import math
    import torch.optim.lr_scheduler as lr_scheduler
    import torch
    import torch.backends.cudnn as cudnn
    import torchvision
    from utils.image_processing import RandomErasing
    from efficient_v2_model import efficientnetv2_l
    from losses.center_loss import CenterLoss
    parser = argparse.ArgumentParser(description="Train on mydatasets")
    parser.add_argument("--data-dir", default='datasets', type=str)
    parser.add_argument("--no-cuda", action="store_true")
    parser.add_argument("--gpu-id", default=0, type=int)
    parser.add_argument("--lr", default=0.01, type=float)
    parser.add_argument("--interval", '-i', default=20, type=int)
    parser.add_argument('--resume', '-r', action='store_true')
    args = parser.parse_args()
    
    # device
    device = "cuda:{}".format(
        args.gpu_id) if torch.cuda.is_available() and not args.no_cuda else "cpu"
    if torch.cuda.is_available() and not args.no_cuda:
        cudnn.benchmark = True
    
    # data loading
    root = args.data_dir
    train_dir = os.path.join(root, "train")
    test_dir = os.path.join(root, "test")
    transform_train = torchvision.transforms.Compose([
        # ZeroPaddingResize((224, 224)),
        torchvision.transforms.Resize((224, 224)),  # (h,w)
        # torchvision.transforms.Resize((256, 128)),  # (h,w)
        # torchvision.transforms.RandomCrop((256, 128), padding=4),
        torchvision.transforms.RandomHorizontalFlip(),
        torchvision.transforms.ColorJitter(brightness=0.2),
        torchvision.transforms.RandomVerticalFlip(),
        torchvision.transforms.RandomRotation(degrees=30),
        torchvision.transforms.ToTensor(),
        RandomErasing(),
        torchvision.transforms.Normalize(
            [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
    transform_test = torchvision.transforms.Compose([
        # ZeroPaddingResize((224, 224)),
        torchvision.transforms.Resize((224, 224)),
        # torchvision.transforms.Resize((256, 128)),
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize(
            [0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
    trainloader = torch.utils.data.DataLoader(
        torchvision.datasets.ImageFolder(train_dir, transform=transform_train),
        batch_size=32, shuffle=True
    )
    testloader = torch.utils.data.DataLoader(
        torchvision.datasets.ImageFolder(test_dir, transform=transform_test),
        batch_size=32, shuffle=False
    )
    num_classes = max(len(trainloader.dataset.classes),
                      len(testloader.dataset.classes))
    
    # net definition
    start_epoch = 0
    net = efficientnetv2_l(num_classes=81)
    weights_dict = torch.load('pre_model/pre_efficientnetv2-l.pth', map_location=device) #预训练模型
    load_weights_dict = {k: v for k, v in weights_dict.items() if net.state_dict()[k].numel() == v.numel()}
    net.load_state_dict(load_weights_dict,strict=False)
    net.to(device)
    print(net)
    
    # cross loss and optimizer
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(
        net.parameters(), args.lr, momentum=0.9, weight_decay=5e-4)
    # center loss and optimizer
    loss_weight = 0.001
    center_loss = CenterLoss(81, 1280,False)
    optimzer_center = torch.optim.SGD(center_loss.parameters(), lr=0.5)
    
    lf = lambda x: ((1 + math.cos(x * math.pi / 100)) / 2) * (1 - 0.01) + 0.01  # cosine
    scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)
    
    
    
    # train function for each epoch
    
    
    def train(epoch):
        print("\nEpoch : %d" % (epoch+1))
        net.train()
        training_loss = 0.
        train_loss = 0.
        correct = 0
        total = 0
        interval = args.interval
        start = time.time()
        for idx, (inputs, labels) in enumerate(trainloader):
            # forward
            inputs, labels = inputs.to(device), labels.to(device)
            feats,outputs = net(inputs)
            loss = criterion(outputs, labels)+loss_weight*center_loss(feats,labels)
    
            optimizer.zero_grad()
            optimzer_center.zero_grad()
            loss.backward()
            optimizer.step()
            optimzer_center.step()
    
            training_loss += (loss.item())
            train_loss += (loss.item())
            correct += outputs.max(dim=1)[1].eq(labels).sum().item()
            total += labels.size(0)
    
            # print
            if (idx+1) % interval == 0:
                end = time.time()
                print("[progress:{:.1f}%]time:{:.2f}s Loss:{:.5f} Correct:{}/{} Acc:{:.3f}%".format(
                    100.*(idx+1)/len(trainloader), end-start, training_loss /
                    interval, correct, total, 100.*correct/total
                ))
                training_loss = 0.
                start = time.time()
    
    
    
    def test(epoch):
    
        net.eval()
        test_loss = 0.
        correct = 0
        total = 0
        start = time.time()
        with torch.no_grad():
            for idx, (inputs, labels) in enumerate(testloader):
                inputs, labels = inputs.to(device), labels.to(device)
                feats,outputs = net(inputs)
    
                loss = criterion(outputs, labels) + loss_weight * center_loss(labels, feats)
    
                test_loss += loss.item()
                correct += outputs.max(dim=1)[1].eq(labels).sum().item()
                total += labels.size(0)
    
            print("Testing ...")
            end = time.time()
            print("[progress:{:.1f}%]time:{:.2f}s Loss:{:.5f} Correct:{}/{} Acc:{:.3f}%".format(
                100.*(idx+1)/len(testloader), end-start, test_loss /
                len(testloader), correct, total, 100.*correct/total
            ))
    
        # saving checkpoint
        acc = 100.*correct/total
    
        checkpoint = {
            'net_dict': net.state_dict(),
            'acc': acc,
            'epoch': epoch,
        }
        if not os.path.isdir('checkpoint'):
            os.mkdir('checkpoint')
        torch.save(checkpoint, 'checkpoint/ckpt-'+str(acc)+'.t7')
    
    
    
    
    
    # lr decay
    
    def lr_decay():
        global optimizer
        for params in optimizer.param_groups:
            params['lr'] *= 0.1
            lr = params['lr']
            print("Learning rate adjusted to {}".format(lr))
    
    
    def main():
        for epoch in range(start_epoch, start_epoch+100):
            train(epoch)
            scheduler.step()
            test(epoch)
            if (epoch+1) % 20 == 0:
                lr_decay()
    
    if __name__ == '__main__':
        main()
    

    4、训练结果

    在这里插入图片描述

    展开全文
  • CenterLoss原理详解(通透)

    千次阅读 2022-04-29 21:22:06
    Center Loss详解,让你瞬间通透。
  • Convolutional neural networks (CNNs) have been widely used in computer vision community, significantly improving the state-ofthe- art. In most of the ...a new supervision signal, called center loss
  • CenterLoss的实现

    2020-08-15 22:54:02
    如何CenterLoss3.Centerloss 的代码实现 1.为什么要CenterLoss 首先在定义一个简单的全连接神经网络。为了更好的可视化特征,将网络的输出层的前一层的输出变为2,使之输出只有2个特征。接着,在MNIST数据集上进行...
  • Pytorch实现CenterLoss(实战)

    千次阅读 2020-11-24 12:34:13
    文章目录一、定义Center loss函数二、搭建网络模型三、开始训练数据 一、定义Center loss函数 import torch import torch.nn as nn def center_loss(feature, label, lambdas): center = nn.Parameter(torch....
  • LossCenter loss代码详解(pytorch)

    千次阅读 2022-01-04 22:10:24
    **注:**全部代码在最后,此代码不知来自哪位大神。 m:batch size n:class size d:feat dim x=(x0x1...xm−1)=(x00x01...x0(d−1)x10x11...x1(d−1).............x(m−1)0x(m−1)1...x(m−1)(d−1))∈Rm×dx=\begin{...
  • centerloss

    2019-08-17 17:53:09
    self.center_loss_layer = CenterLoss(10, 2) self.crossEntropy = nn.CrossEntropyLoss() def forward(self, xs): hidden = self.hidden_layer(xs) hidden = hidden.view(-1,16*7*7) features = self.fc...
  • Center loss-pytorch代码详解

    千次阅读 2021-08-23 22:54:10
    主要代码如下: ...class CenterLoss(nn.Module): """Center loss. Reference: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. Args:.
  • pytorchOCR之CRNN+centerloss

    千次阅读 热门讨论 2021-03-06 14:19:17
    pytorchOCR之CRNN+centerloss 这是阿里团队提出来用来解决softmax对于形近字表征不足的问题,之前一直想写来着,写了一半被拉去做项目了,偶然逛GitHub,看见一位大佬也做了这个工作,原代码在此,本着我辈不嫖白不...
  • 损失函数:Center Loss

    2022-06-15 21:40:54
    最近几年网络效果的提升除了改变网络结构外,还有一群人在研究损失层的改进,这篇博文要介绍的就是较为新颖的center losscenter loss来自ECCV2016的一篇论文:A Discriminative Feature Learning Approach for ...
  • 损失函数(CenterLoss

    2020-06-17 14:57:46
    特征损失:自定义损失函数(CenterLoss)。 分类损失:交叉熵(CrossEntropyLoss),自带 one-hot 类型和 softmax。 输出:one-hot 类型,结果为最大的索引值。 自定义损失函数(CenterLoss) import torch from ...
  • center loss代码PyTorch

    2021-04-14 10:34:12
    class CenterLoss(nn.Module): """Center loss. Reference: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. Args: num_classes (int): number of classes.
  • class CenterLoss(nn.Module): """Center loss. Reference: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. Args: num_classes (int): number of classes. ...
  • 人脸识别损失函数之Center Loss

    千次阅读 2020-05-28 11:01:31
    self.feature = nn.Linear(128 * 3 * 3, 2) # 2:(x,y) self.output_layer = nn.Linear(2, 10) self.center_loss_layer = CenterLoss(10, 2) # self.center_loss = self.center_loss_layer() def forward(self, ...
  • Center Loss.docx

    2021-05-20 11:53:25
    Center Loss
  • center Loss

    2021-03-29 20:01:27
    class Centerloss(nn.Module): def __init__(self, lambdas, feature_num=2, class_num=10): super().__init__() self.lambdas = lambdas self.center = nn.Parameter(torch.randn(class_num, feature_num), ...
  • Contrastive Loss vs Triplet Loss:Contrastive Loss [1]:Triplet Loss [2]:2. 问题引入:3. Contrastive Loss:对比损失定义:含义:4. Triplet Loss:三元组损失定义:目标:公式:进阶:FaceNet 1. ...
  • Center Loss的Pytorch实现

    千次阅读 2019-01-13 18:20:41
    Center Loss的Pytorch实现开始结果在自己的项目中使用中心损失函数 Center Loss的Pytorch实现: Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. 这个损失函数也被...
  • Triplet LossCenter Loss详解和pytorch实现

    万次阅读 多人点赞 2019-08-01 16:44:41
    最近在学习ReID相关的算法,为了提高ReID的性能通常会采用softmax loss 联合 Triplet LossCenter Loss来提高算法的性能。 本文对Triplet Loss和Cnetr Loss做一个总结,以简洁的方式帮助理解。 Triplet Loss和...
  • 人脸识别辅助损失函数:centerloss

    千次阅读 2020-05-24 10:54:46
    centerloss公式如下: centerloss给每个类设定了一个中心点,在训练的时候,将每个提取到的特征向量与对应类中心点的L2范数的平方作为损失,损失越大,说明特征向量距离对应类的中心点越远。降低此损失,每个类的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,626
精华内容 6,250
关键字:

CenterLoss