【问题标题】:How to right shift each row of a matrix?如何右移矩阵的每一行?
【发布时间】:2020-12-04 04:25:59
【问题描述】:

我有一个形状为(TxKK << T)的矩阵。我想将它扩展成TxT 的形状,并用i 步骤右移i-th 行。

举个例子:

inputs: T= 5, and K = 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3

expected outputs:
1 2 3 0 0
0 1 2 3 0
0 0 1 2 3
0 0 0 1 2
0 0 0 0 1

我的解决方案:

right_pad = T - K + 1
output = F.pad(input, (0, right_pad), 'constant', value=0)
output = output.view(-1)[:-T].view(T, T)

我的解决方案会导致错误——gradient computation has been modified by an in-place operation。有没有一种高效可行的方法来实现我的目的?

【问题讨论】:

  • 您的预期输出在您的示例中没有正确的大小。现在是 5x6 矩阵。
  • 抱歉,我已经解决了问题

标签: matrix pytorch autograd


【解决方案1】:

您的功能很好,不是您出错的原因(使用PyTorch 1.6.0,如果您使用的是其他版本,请更新您的依赖项)。

下面的代码可以正常工作:

import torch
import torch.nn as nn
import torch.nn.functional as F

T = 5
K = 3

inputs = torch.tensor(
    [[1, 2, 3,], [1, 2, 3,], [1, 2, 3,], [1, 2, 3,], [1, 2, 3,],],
    requires_grad=True,
    dtype=torch.float,
)

right_pad = T - K + 1
output = F.pad(inputs, (0, right_pad), "constant", value=0)
output = output.flatten()[:-T].reshape(T, T)

output.sum().backward()

print(inputs.grad)

请注意,我已将dtype 明确指定为torch.float,因为您不能将backprop 指定为整数。

viewslice 永远不会破坏反向传播,因为 gradient 连接到单个值,无论它被视为 1D 还是未压缩的 2D 或其他.这些没有就地修改。就地修改破坏梯度可能是:

output[0, 3] = 15.

此外,您的解决方案返回以下内容:

tensor([[1., 2., 3., 0., 0.],
        [0., 1., 2., 3., 0.],
        [0., 0., 1., 2., 3.],
        [0., 0., 0., 1., 2.],
        [3., 0., 0., 0., 1.]], grad_fn=<ViewBackward>)

所以你在左下角有一个3。如果这不是您所期望的,您应该在output = output.flatten()[:-T].reshape(T,T) 之后添加这一行(与1 相乘的上三角矩阵):

output *= torch.triu(torch.ones_like(output))

给出:

tensor([[1., 2., 3., 0., 0.],
        [0., 1., 2., 3., 0.],
        [0., 0., 1., 2., 3.],
        [0., 0., 0., 1., 2.],
        [0., 0., 0., 0., 1.]], grad_fn=<AsStridedBackward>)

还有inputs.grad:

tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 0.],
        [1., 0., 0.]])

【讨论】:

    【解决方案2】:

    您可以使用 PyTorch 逐列执行此操作。

    # input is a T * K tensor
    input = torch.ones((T, K))
    
    index = torch.tensor(np.linspace(0, T - 1, num=T, dtype=np.int64))
    output = torch.zeros((T, T))
    output[index, index] = input[:, 0]
    for k in range(1, K):
        output[index[:-k], index[:-k] + k] = input[:-k, k]
    print(output)
    

    【讨论】:

    • 我不确定inputoutput之间的复制操作是否会保留梯度反向传播。
    • @Beanocean,将值分配给输出张量时,反向传播应该没有问题。使用这段代码时你的训练失败了吗?
    • 非常感谢您的回复。我仔细检查了我的代码,发现错误是由另一个错误引起的。
    猜你喜欢
    • 2014-07-31
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 2019-11-15
    • 2017-07-23
    • 1970-01-01
    • 2023-03-10
    • 2016-10-01
    相关资源
    最近更新 更多