人脸识别 损失函数 centerloss arcfaceloss pytorch实现

本文介绍了人脸识别技术,从Softmax loss到Center loss、Triplet loss,再到L-softmax loss、SphereFace、CosFace和ArcFace等损失函数的发展,并通过PyTorch展示了它们的实现。ArcFace因其优化角度距离的优势在人脸识别中得到广泛应用。最后,概述了基于MTCNN和Arcface loss的人脸识别流程。
摘要由CSDN通过智能技术生成

人脸识别介绍

MTCNN 实现人脸检测,回答了“是不是人脸”和“人脸在哪”的问题,接下来人脸识别要解决的就是“人脸是谁”。
人脸识别是目标识别中的一种,本质上也是分类问题,只不过是同类(人脸)中的细分,因为人脸之间相似度很大,这对损失函数的分类能力提出了更高的要求。

损失函数发展

下面介绍分类损失函数的主要类型和发展历程,及部分pytorch代码。
效果图来自 MNIST 数据集,将网络模型倒数第二层输出通道数设为2,将二维分类特征可视化即可。

Softmax loss

在这里插入图片描述

经典的分类损失 Softmax loss,将正确类别的预测概率最大化。但这种方式只考虑了能否正确分类,没有考虑类间距离。

Center loss

在这里插入图片描述
在这里插入图片描述
Center loss 在 Softmax loss 基础上增加了 L C L_C LC项,给每个类都设置一个中心 c y i c_{yi} cyi,让该类尽量向中心靠拢,在保证分类的同时,最小化类内距离。

需要注意的是:

  1. Center loss 本身没有分类功能,需要配合 Softmax loss,不能单独使用。
  2. 中心 c y i c_{yi} cyi初始化是随机值,之后随着学习到的特征进行实时更新。
  3. 计算每一类的中心损失时,需要除以该类样本数计算均值,防止因样本失衡导致的不同类别梯度更新不同步。
  4. 参数 λ \lambda λ控制中心损失优化力度, λ \lambda λ越大区分度越高,但在人脸识别中,经验值一般取0.003即可。


Center loss 在人脸识别上的效果还是不错的,但还有许多不足

  1. 类内距优化效果还不理想。
    类内距还是较大,当类别较多时,无法清晰区分特征。
  2. 类别多时,对硬件要求较高。
    每个类别需要维护一个中心点,当类别很多时计算量大。
  3. L2范数的离群点难以优化。
    因为中心损失计算的是每一类损失的均值,离群点导致loss较大,难以下降,同理在loss下降过程中,离群点的优化力度不够,相对仍然离中心很远。
  4. 只适用于同类样本间差异较小的数据。
    将同类样本向一个中心点优化的前提是,这一类样本间相似度较大,中心点可以代表这一类样本的特征,如果差异很大,就相当于有很多离群点,自然难以优化。可以抽象理解为:一个人的一堆人脸取均值大概还能看出是人脸,而各种类别的狗取均值就完全认不出是什么了。
def center_loss(feat
  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是使用PyTorch实现Center Loss的代码示例: ```python import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F class CenterLoss(nn.Module): def __init__(self, num_classes, feat_dim, loss_weight=0.5): super(CenterLoss, self).__init__() self.num_classes = num_classes self.feat_dim = feat_dim self.loss_weight = loss_weight self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim)) def forward(self, x, labels): batch_size = x.size(0) # 计算当前batch中每个样本对应的中心 centers_batch = self.centers[labels] # 计算当前batch中每个样本与其对应中心之间的距离 dist = torch.sum((x - centers_batch) ** 2, dim=1) # 计算center loss center_loss = torch.mean(dist) # 更新中心 diff = centers_batch - x unique_label, unique_idx = torch.unique(labels, return_inverse=True) appear_times = torch.bincount(unique_idx, minlength=self.num_classes).float() appear_times = appear_times.unsqueeze(1) centers_update = torch.zeros_like(self.centers) centers_update.scatter_add_(0, labels.view(-1, 1).expand(batch_size, self.feat_dim), diff) centers_update = centers_update / (appear_times + 1e-8) self.centers.data = self.centers.data - self.loss_weight * centers_update.data return center_loss class Net(nn.Module): def __init__(self, num_classes, feat_dim): super(Net, self).__init__() self.fc1 = nn.Linear(feat_dim, 512) self.fc2 = nn.Linear(512, num_classes) self.center_loss = CenterLoss(num_classes, feat_dim) def forward(self, x, labels): x = self.fc1(x) x = F.relu(x) x = self.fc2(x) center_loss = self.center_loss(x, labels) return x, center_loss ``` 在这里,我们首先定义了一个`CenterLoss`类来计算中心损失。`CenterLoss`的`__init__`函数中包含中心矩阵`centers`,其大小为`(num_classes, feat_dim)`,其中`num_classes`为类别数,`feat_dim`为特征维度。`forward`函数接受输入的特征张量`x`和对应的标签`labels`,计算`x`和每个样本对应的中心之间的距离,然后计算中心损失并更新中心矩阵。在`Net`类中,我们将`CenterLoss`作为一个模块集成到模型中,同时在模型的前向传播中计算中心损失。 接下来,我们可以使用以下代码来训练模型: ```python net = Net(num_classes, feat_dim) optimizer = optim.SGD(net.parameters(), lr=lr, momentum=momentum) for epoch in range(num_epochs): for batch_idx, (data, labels) in enumerate(train_loader): data, labels = data.to(device), labels.to(device) optimizer.zero_grad() outputs, center_loss = net(data, labels) softmax_loss = F.cross_entropy(outputs, labels) loss = softmax_loss + center_loss loss.backward() optimizer.step() ``` 在每个batch的训练中,我们首先将输入数据和标签送入设备中,然后将模型参数的梯度清零。接着,我们计算前向传播的结果和中心损失,然后使用交叉熵损失计算总损失,并进行反向传播和参数更新。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值