约束 PyTorch 张量中的元素相等

问题描述 投票:0回答:1

我有一个 PyTorch 张量,并且想 在优化时对其元素施加等式约束。下面显示了一个 2 * 9 张量的示例,其中相同的颜色表示元素应该始终相等。

我们做一个1 * 4的最小例子,分别初始化前两个和后两个元素相等

import torch
x1 = torch.tensor([1.2, 1.2, -0.3, -0.3])
print(x1)
# tensor([ 1.2000,  1.2000, -0.3000, -0.3000])

如果我直接做一个简单的最小二乘,等式肯定不存在了

y = torch.arange(4)
opt_1 = torch.optim.SGD([x1], lr=0.1)
opt_1.zero_grad()
loss = (y - x1).pow(2).sum()
loss.backward()
opt_1.step()
print(x1)
# tensor([0.9600, 1.1600, 0.1600, 0.3600], requires_grad=True)

我试图将这个张量表示为掩码的加权和.

def weighted_sum(c, masks):
    return torch.sum(torch.stack([c[0] * masks[0], c[1] * masks[1]]), axis=0)

c = torch.tensor([1.2, -0.3], requires_grad=True)
masks = torch.tensor([[1, 1, 0, 0], [0, 0, 1, 1]])
x2 = weighted_sum(c, masks)
print(x2)
# tensor([ 1.2000,  1.2000, -0.3000, -0.3000])

这样优化后等式依然存在

opt_c = torch.optim.SGD([c], lr=0.1)
opt_c.zero_grad()
y = torch.arange(4)
x2 = weighted_sum(c, masks)
loss = (y - x2).pow(2).sum()
loss.backward()
opt_c.step()
print(c)
# tensor([0.9200, 0.8200], requires_grad=True)
print(weighted_sum(c, masks))
# tensor([0.9200, 0.9200, 0.8200, 0.8200], grad_fn=<SumBackward1>)

但是,这个解决方案最大的问题是当输入维度很高时,我必须维护一大组masks;肯定会导致内存不足。假设输入张量的形状是

d_0 * d_1 * ... * d_m
,相等块的个数是
k
,那么就会有一个巨大的
k * d_0 * d_1 * ... * d_m
形状的mask,这是不可接受的。


另一个解决方案可能是升采样这个这样的低分辨率张量。但是,它不能应用于不规则的相等块,例如,

tensor([[ 1.2000,  1.2000,  1.2000, -3.1000, -3.1000],
        [-0.1000,  2.0000,  2.0000,  2.0000,  2.0000]])

那么...有没有更聪明的方法在 PyTorch 张量中实现这种等式约束?

python pytorch tensor
1个回答
1
投票

如果您希望它们始终相等,为什么不从

x
y
中删除第一个和最后一个值?额外的值可以在训练后需要时从模型输出中导出,因为无论如何它们都应该等于它们的邻居。无需学习相同值的两个副本。

如果你想更近似地了解它们是相同的,你可以将

some_weight * (torch.abs(x[0]-x[1]) + torch.abs(x[-1] - x[-2]))
添加到你的损失函数中。那么你的损失将是试图了解这些预计是相同的。

或者,如果您对每个值都有计数,而不是掩码,也许您正在寻找这样的东西?

def convert(tensor, counts):
     return torch.cat( [v.repeat(count) for (v, count) in zip(tensor, counts) ] )

convert( torch.arange(4), [3,2,1,3])
tensor([0, 0, 0, 1, 1, 2, 3, 3, 3])
© www.soinside.com 2019 - 2024. All rights reserved.