PyTorch Autograd内部实现

原文:

克補 爆炸篇 25s (youtube.com)

必应视频 (bing.com)icon-default.png?t=N7T8https://www.bing.com/videos/riverview/relatedvideo?&q=PyTorch+autograd&qpvt=PyTorch+autograd&mid=1B8AD76943EFADD541E01B8AD76943EFADD541E0&&FORM=VRDGAR

前面只要有一个node的requires_grad为True,则后面所有node都要为True:

forward阶段,ctx里存放其backward操作需要的值,也就是forward时的部分input或output值;

requires_grad为False的(Tensor b),不会计算其梯度;

requires_grad为True,且is_leaf为Tree的,会将梯度累积到其grad成员上;

优化:如果is_leaf=False,则说明不需要该Tensor的grad,所以,grad_fn直接将output梯度传递给下一个grad_fn了,绕开对该Tensor的grad的更新;(节省一步梯度加和操作的时间,也节省一个grad数据存储空间)

用_version号来防止backward时用到的activation在之前发生改动;如果_version号跟本次backward源头的_version号不同了,则报错;

我:Pipeline并行,如果直接做,就会有这种报错出现;

如果是Add操作这种,压根不需要某些activation的值,所以这种值发生改动,不影响backward传递参数,因此就不会报错

每个运算,是一个独立的operator,对应backward也是独立的:

Tensor.detach(),用在什么情况:想保留结果值,但又想把原始计算图垃圾回收释放掉;新Tensor和老Tensor共享数据内存(data),但不在hold指向计算图的reference了(grad_fn=None)

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 中心损失(Center Loss)是一种用于人脸识别和人体姿态估计等任务中的监督学习方法。其主要目的是将同一类别的特征向量在特征空间中聚集起来,同时能够保持类间的可分性。下面将使用PyTorch实现中心损失。 首先,我们需要导入PyTorch库以及其他必要的工具包: ``` import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F from torch.autograd import Variable ``` 接下来,定义一个类来构建我们的中心损失模型: ``` class CenterLoss(nn.Module): def __init__(self, num_classes, feat_dim): super(CenterLoss, self).__init__() self.num_classes = num_classes self.feat_dim = feat_dim # 初始化中心 self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim)) def forward(self, feat, labels): # 计算欧氏距离 batch_size = feat.size(0) expanded_centers = self.centers[labels].unsqueeze(0).expand(batch_size, -1, -1) expanded_feat = feat.unsqueeze(1).expand_as(expanded_centers) distances = torch.sqrt(torch.sum((expanded_feat - expanded_centers) ** 2, dim=2) + 1e-8) # 计算center loss center_loss = torch.sum(distances) / 2.0 / batch_size # 更新中心 unique_labels = labels.unique() unique_counts = labels.bincount(minlength=self.num_classes).float().unsqueeze(1) mask = torch.zeros(self.num_classes, self.feat_dim).cuda() mask[unique_labels] = 1 updated_centers = torch.zeros(self.num_classes, self.feat_dim).cuda() updated_centers = Variable(updated_centers) updated_centers[unique_labels] = torch.sum(feat.data[labels==unique_labels], dim=1) updated_centers[unique_labels] /= unique_counts[unique_labels] updated_centers = updated_centers * mask self.centers.data = 0.9 * self.centers.data + 0.1 * updated_centers.data return center_loss ``` 在上面的代码中,我们首先定义了`CenterLoss`类,其中`num_classes`表示类别的数量,`feat_dim`表示特征向量的维度。在构造函数中,我们使用`nn.Parameter`来初始化中心(centers),并将其变为可训练的参数。 然后,我们重写了`forward`方法,用于计算中心损失。首先,我们根据输入特征向量`feat`和对应的标签`labels`,计算特征向量与中心之间的欧氏距离。接着,我们根据距离计算center loss,并根据标签更新中心。最后,返回center loss。 需要注意的是,在更新中心时,我们首先获取唯一的标签和对应的样本数量,并创建一个mask来选择更新的中心。然后,我们计算标签对应样本的特征向量的和,并除以数量得到更新后的中心。最后,根据更新公式`tl = alpha * tl + (1 - alpha) * tl'`来更新中心。 最后,我们可以使用这个中心损失模块来训练我们的网络,例如: ``` num_classes = 10 feat_dim = 256 model = CenterLoss(num_classes, feat_dim) criterion_cls = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001) for epoch in range(10): for data, labels in dataloader: optimizer.zero_grad() feat = model(data) cls_loss = criterion_cls(feat, labels) center_loss = model(feat, labels) total_loss = cls_loss + center_loss total_loss.backward() optimizer.step() # 输出损失 print("Epoch: {}, Cls Loss: {:.4f}, Center Loss: {:.4f}".format(epoch+1, cls_loss.item(), center_loss.item())) ``` 在训练过程中,我们使用`model(data)`获取特征向量,然后使用交叉熵损失和中心损失来计算总损失,并进行反向传播和参数更新。 以上就是使用PyTorch实现中心损失的方法,希望对你有帮助! ### 回答2: 中心损失是一种在人脸识别和人脸验证任务中广泛应用的损失函数,它的目标是增强不同类别之间的区分度并减小同一类别内部的差异。 在PyTorch中,可以通过自定义网络模型以及定义损失函数来实现中心损失。具体步骤如下: 1.定义网络模型:使用PyTorch定义一个卷积神经网络模型,可以使用预训练的模型如ResNet等作为基础网络,然后在最后添加一个全连接层。 2.定义损失函数:除了传统的交叉熵损失函数,还需要定义中心损失函数。中心损失函数的计算包含两个部分,分别是类别中心的更新和样本特征与类别中心的距离。通过计算样本特征与类别中心的欧式距离,将每个样本追加到对应类别的中心中。 3.定义优化器:选择Adam、SGD等优化算法,并指定学习率。 4.训练模型:使用训练数据集,将输入数据通过网络模型前向传播得到特征表示,然后计算中心损失函数,并与传统的交叉熵损失函数进行相加,得到总的损失。使用反向传播算法更新网络参数,不断迭代优化。 5.评估模型:使用验证数据集对训练好的模型进行评估,并计算准确率、精确率等评价指标。 通过以上步骤,可以实现中心损失的PyTorch实现,并应用于人脸识别和人脸验证等相关任务中,提高模型的性能和准确率。 ### 回答3: 中心损失(center loss)是一种用于人脸识别或者人脸验证等任务的损失函数,其主要作用是将相同身份的人脸图片的特征向量尽可能地聚集在类别中心,从而使得同一类别的特征向量更加紧凑,不同类别之间的特征向量则相对分散。 中心损失的PyTorch实现如下: 首先,我们需要定义一个类别中心的变量,来保存每个类别的中心向量。这个类别中心的变量可以使用PyTorch中的torch.Tensor创建。 ``` class CenterLoss(nn.Module): def __init__(self, num_classes, feature_dim): super(CenterLoss, self).__init__() self.num_classes = num_classes self.feature_dim = feature_dim self.centers = nn.Parameter(torch.randn(num_classes, feature_dim)) def forward(self, features, labels): batch_size = features.size(0) features = features.view(batch_size, -1) centers_batch = self.centers.index_select(0, labels) criterion = nn.MSELoss() loss = criterion(features, centers_batch) return loss ``` 在类别中心的计算过程中,我们使用labels将每个样本对应到对应的类别中心,然后通过特征向量与类别中心之间的欧氏距离来计算损失值。在这里,我们使用MSELoss作为损失函数。 最后,我们可以在训练模型的过程中将中心损失添加到总的损失函数中,以便进行反向传播和参数更新。 ``` # 定义模型 model = ResNet() # 定义中心损失 center_loss = CenterLoss(num_classes, feature_dim) # 定义优化器 optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9) # 在代码的训练循环中,加入中心损失的计算 for images, labels in dataloader: # 前向传播 features = model(images) # 计算中心损失 loss_center = center_loss(features, labels) # 计算总损失 total_loss = loss_classification + lambda_center * loss_center # 反向传播和参数更新 optimizer.zero_grad() total_loss.backward() optimizer.step() ``` 以上就是中心损失的PyTorch实现过程,通过计算损失函数,使得特征向量更加紧凑,从而提升人脸识别或者验证任务的准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值