我有一个网络输出的tensor张量矩阵z,现在想对这个矩阵做如下约束:
矩阵大小为BCH*W,理想状况下,每行每个元素H(i)应该大于之前的元素(H0~H(i-1)),设为1;如果不是最大,则设为0.
我将这个算法转到numpy实现了一下,但不知道如何直接在tenosr下实现,因为在numpy下无法反向传播回去。
def cal_shadow(h,z,x_ij):
tan_sigma=x_ij/(h-z)
tan_sigma=tan_sigma.cpu().detach().numpy()
shadow=np.copy(tan_sigma)
for k in range(tan_sigma.shape[0]):
for i in range(tan_sigma.shape[2]):
max_sigma = -100000
for j in range(tan_sigma.shape[3]):
if tan_sigma[k, 0, i, j] > max_sigma:
shadow[k, 0, i, j] = 1
max_sigma = tan_sigma[k, 0, i, j]
else:
shadow[k, 0, i, j] = 0 #阴影都设为0
shadow = torch.from_numpy(shadow)
shadow = shadow.type(torch.FloatTensor)
shadow=shadow.to(z.device)
return shadow
import torch
def cal_shadow(h, z):
# 计算每个元素和之前的元素的最大值
cummax = torch.cummax(z, dim=-1).values
# 创建一个大小相同的零张量
shadow = torch.zeros_like(z)
# 如果元素大于等于之前的最大值,则将其设置为1,否则为0
shadow[z >= cummax] = 1
# 将张量类型转换为与输入张量相同的类型,并将其发送到相同的设备
shadow = shadow.type(z.dtype).to(z.device)
return shadow
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下。
您可以尝试使用PyTorch的torch.where和torch.cummax函数实现这个约束。以下是一个示例实现:
import torch
def cal_shadow(h, z, x_ij):
tan_sigma = x_ij / (h - z)
# 计算每个位置的累计最大值
cum_max, _ = torch.cummax(tan_sigma, dim=-1)
# 将tan_sigma与cum_max逐元素比较,如果tan_sigma大于cum_max中的前一个元素,则设为1,否则设为0
shadow = torch.where(tan_sigma > torch.cat([torch.zeros_like(cum_max[..., :1]), cum_max[..., :-1]], dim=-1), 1, 0)
return shadow.type(torch.FloatTensor)
这个实现中,我们首先计算了tan_sigma,然后使用torch.cummax函数计算每个位置的累计最大值。接下来,我们使用torch.where逐元素比较tan_sigma与cum_max中的前一个元素,如果tan_sigma大于前一个元素,则设为1,否则设为0。
这个实现仅使用了PyTorch的张量操作,因此可以在计算图中保留梯度信息,从而实现反向传播。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
torch.from_numpy(ndarry)
注:生成返回的tensor会和ndarry共享数据,任何对tensor的操作都会影响到ndarry,
反之亦然
a = numpy.array([1, 2, 3])
t = torch.from_numpy(a)
t
tensor([ 1, 2, 3])
t[0] = -1
a
array([-1, 2, 3])