Python 用PyTorch中的向量替换对角线元素

Python 用PyTorch中的向量替换对角线元素,python,pytorch,diagonal,Python,Pytorch,Diagonal,我一直在到处寻找类似于PyTorch的东西,但我什么也找不到 L_1 = np.tril(np.random.normal(scale=1., size=(D, D)), k=0) L_1[np.diag_indices_from(L_1)] = np.exp(np.diagonal(L_1)) 我想没有办法用Pytork以如此优雅的方式替换对角线元素。我认为目前还没有实现这样的功能。但是,您可以使用mask实现相同的功能,如下所示 # Assuming v to be the vector

我一直在到处寻找类似于PyTorch的东西,但我什么也找不到

L_1 = np.tril(np.random.normal(scale=1., size=(D, D)), k=0)
L_1[np.diag_indices_from(L_1)] = np.exp(np.diagonal(L_1))

我想没有办法用Pytork以如此优雅的方式替换对角线元素。

我认为目前还没有实现这样的功能。但是,您可以使用
mask
实现相同的功能,如下所示

# Assuming v to be the vector and a be the tensor whose diagonal is to be replaced
mask = torch.diag(torch.ones_like(v))
out = mask*torch.diag(v) + (1. - mask)*a
因此,您的实现将类似于

L_1 = torch.tril(torch.randn((D, D)))
v = torch.exp(torch.diag(L_1))
mask = torch.diag(torch.ones_like(v))
L_1 = mask*torch.diag(v) + (1. - mask)*L_1

没有numpy那么优雅,但也不算太糟糕。

有一种更简单的方法

dest_matrix[range(len(dest_matrix)), range(len(dest_matrix))] = source_vector
事实上,我们必须自己生成对角线索引

用法示例:

dest_matrix = torch.randint(10, (3, 3))
source_vector = torch.randint(100, 200, (len(dest_matrix), ))
print('dest_matrix:\n', dest_matrix)
print('source_vector:\n', source_vector)

dest_matrix[range(len(dest_matrix)), range(len(dest_matrix))] = source_vector

print('result:\n', dest_matrix)

# dest_matrix:
#  tensor([[3, 2, 5],
#         [0, 3, 5],
#         [3, 1, 1]])
# source_vector:
#  tensor([182, 169, 147])
# result:
#  tensor([[182,   2,   5],
#         [  0, 169,   5],
#         [  3,   1, 147]])
如果
dest\u矩阵
不是正方形,则必须在
range()中取
min(dest\u矩阵.size())
而不是
len(dest\u矩阵)

不像
numpy
那样优雅,但这不需要存储新的索引矩阵


是的,这将保留渐变

您可以使用
对角线()
提取对角线元素,然后将转换后的值指定给:

new_diags=L_1.diagonal().exp()
L_1.对角线().复制(新对角线)

事实上,我希望有更优雅的东西,但这也行得通。如果张量和向量都需要梯度,这个解决方案会保持梯度要求吗?是的。我想是的,因为所有使用的函数在PyTorch中都是可微的。您可以使用此选项查看是否出现任何错误。更简单的常量情况: