|
# ArcFace loss(加性角度间隔损失)解惑:特征向量按行归一化,权重按列归一化
# ArcFace loss:Additive Angular Margin Loss(加性角度间隔损失函数),
# 对特征向量和权重归一化,对θ加上角度间隔m,角度间隔比余弦间隔在对角度的影响更加直接。
# 几何上有恒定的线性角度margin
# torch.nn.Parameter是继承自torch.Tensor的子类,其主要作用是作为nn.Module中的可训练参数使用。
# 它与torch.Tensor的区别就是nn.Parameter会自动被认为是module的可训练参数,
# 即加入到parameter()这个迭代器中去;
# 而module中非nn.Parameter()的普通tensor是不在parameter中的。
# 注意到,nn.Parameter的对象的requires_grad属性的默认值是True,即是可被训练的,
# 这与torh.Tensor对象的默认值相反
- # -*- coding: utf-8 -*-
- __author__ = u'东方耀 微信:dfy_88888'
- __date__ = '2020/6/5 上午8:41'
- __product__ = 'PyCharm'
- __filename__ = 'dfy_demo01'
- import torch
- import torch.nn.functional as F
- from torch.nn.parameter import Parameter
- import numpy as np
- import math
- import torch.nn as nn
- class dfy_model(nn.Module):
- def __init__(self, in_feature, out_feature):
- super(dfy_model, self).__init__()
- print("自定义的模型:就一个简单的二维矩阵!")
- # self.fc = nn.Linear(in_feature, out_feature, bias=False)
- self.kernel = Parameter(torch.Tensor(in_feature, out_feature))
- # initial kernel 初始化时就已经l2归一化了 这里是按列的
- # self.kernel.data.uniform_(-1, 1).renorm_(p=2, dim=1, maxnorm=1e-5).mul_(1e5)
- self.kernel.data.uniform_(-1, 1)
- # pytorch在torch.nn.init中提供了常用的初始化方法函数
- # torch.nn.init.eye_(self.kernel) # 单位矩阵
- def forward(self, x):
- # for W in self.fc.parameters():
- # # 权重归一化 这样好像fc层的参数没有被归一化啊
- # # pytorch归一化fc层的参数
- # # 带out参数 不支持可微分的 differentiable
- # # F.normalize(W, p=2, dim=1, out=W)
- # W = F.normalize(W, p=2, dim=1)
- kernel_norm = F.normalize(self.kernel, p=2, dim=0)
- # 发现了:特征向量x的归一化(按行 dim=1) 权重矩阵的归一化(按列 dim=0)
- x = F.normalize(x, p=2, dim=1)
- # out2 = self.fc(x)
- # out1:没有归一化weight
- out1 = torch.mm(x, self.kernel)
- # out2: 归一化weight
- out2 = torch.mm(x, kernel_norm)
- return out1, out2
- my_model = dfy_model(3, 10)
- embed = torch.from_numpy(np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32))
- print(embed.size(), embed)
- with torch.no_grad():
- result1, result2 = my_model(embed)
- print("没有归一化weight=", result1, result1.size())
- print("归一化weight=", result2, result2.size())
复制代码
- from torch.nn.parameter import Parameter
- import torch
- kernel = Parameter(torch.Tensor(2, 3))
- kernel.data.uniform_(-1, 1).renorm_(p=2, dim=1, maxnorm=1e-5).mul_(1e5)
- print(kernel)
- kernel = torch.nn.functional.normalize(kernel, p=2, dim=0)
- print(kernel)
- # 输出的值是一样的
- # tensor([[-0.7415, -0.2698, 0.9620],
- # [ 0.6709, 0.9629, 0.2729]], requires_grad=True)
- # tensor([[-0.7415, -0.2698, 0.9620],
- # [ 0.6709, 0.9629, 0.2729]], grad_fn=<DivBackward0>)
复制代码
|
|