对于通道数只有1,长度为L 的向量,大小是 1*L ,计算这样的两个向量之间的距离,拓展到一个batch 共有n个样本向量,也即向量的大小是 n*1*L , 计算两个batch之间的距离(大小是[-1,1])
import torch
import torch.nn as nn
from torch_geometric.data import DataLoader
def D1(p,z):
norm = nn.InstanceNorm1d(1)
p = norm(p)
print(f'D1 norm P: {p}')
# z = torch.instance_norm(z,dim=1)
z = norm(z)
print(f'D1 z: {z}')
return -(p*z).sum(dim=1).mean()
def D2(p,z):
# norm = nn.InstanceNorm1d(1)
# manually mormalization
N,C = p.size(0),p.size(1)
p_t = p.reshape(N * C, -1)
p_mean = p_t.mean(dim=1).reshape(N,C,-1)
p_std = p_t.std(dim=1,unbiased=False).reshape(N,C,-1)
p = (p-p_mean)/p_std
print(f'p_mean: {p_mean},\n p_std: {p_std},\n D2 p_norm: {p}')
z_t = z.reshape(N * C, -1)
z_mean = z_t.mean(dim=1).reshape(N, C, -1)
z_std = z_t.std(dim=1, unbiased=False).reshape(N, C, -1)
z = (z - z_mean) / z_std
print(f'z_mean: {z_mean}, \n z_std: {z_std},\n D2 z_norm: {z}')
return -(p*z).sum(dim=1).mean()
if __name__ == '__main__':
# similarity function D(p,z)
torch.manual_seed(3)
p = torch.randn(2,5)
z = torch.randn(2, 5)
print(f'p:{p}, \n z:{z}')
N,C = p.size(0),p.size(1)
p = p.reshape(N, 1, -1)
z = z.reshape(N,1,-1)
print(D1(p,z))
print(D2(p,z))
两种方法计算结果是一样的:
p:tensor([[ 0.8033, 0.1748, 0.0890, -0.6137, 0.0462],
[-1.3683, 0.3375, 1.0111, -1.4352, 0.9774]]),
z:tensor([[ 0.5220, 1.2379, -0.8646, 0.2990, 0.4192],
[-0.0799, 0.9264, 0.8157, 0.4952, -0.1643]])
D1 norm P: tensor([[[ 1.5629, 0.1665, -0.0243, -1.5857, -0.1194]],
[[-1.1640, 0.3960, 1.0120, -1.2252, 0.9812]]])
D1 z: tensor([[[ 0.2941, 1.3503, -1.7518, -0.0350, 0.1424]],
[[-1.0658, 1.1756, 0.9290, 0.2151, -1.2539]]])
tensor(-0.1918)
p_mean: tensor([[[ 0.0999]],
[[-0.0955]]]),
p_std: tensor([[[0.4500]],
[[1.0934]]]),
D2 p_norm: tensor([[[ 1.5630, 0.1665, -0.0243, -1.5858, -0.1194]],
[[-1.1640, 0.3960, 1.0120, -1.2252, 0.9812]]])
z_mean: tensor([[[0.3227]],
[[0.3986]]]),
z_std: tensor([[[0.6778]],
[[0.4489]]]),
D2 z_norm: tensor([[[ 0.2941, 1.3503, -1.7518, -0.0350, 0.1424]],
[[-1.0658, 1.1757, 0.9290, 0.2151, -1.2540]]])
tensor(-0.1918)