创建 array/tensor 个循环移位数组
Create array/tensor of cycle shifted arrays
我想创建 2d 张量(或 numpy 数组,并不重要),其中每一行都将循环移位到第一行。我使用 for
循环:
import torch
import numpy as np
a = np.random.rand(33, 11)
miss_size = 64
lp_order = a.shape[1] - 1
inv_a = -np.flip(a, axis=1)
mtx_size = miss_size+lp_order # some constant
mtx_row = torch.cat((torch.from_numpy(inv_a), torch.zeros((a.shape[0], miss_size - 1 + a.shape[1]))), dim=1)
mtx_full = mtx_row.unsqueeze(1)
for i in range(mtx_size):
mtx_row = torch.roll(mtx_row, 1, 1)
mtx_full = torch.cat((mtx_full, mtx_row.unsqueeze(1)), dim=1)
需要解压缩,因为我将 2d 张量堆叠到 3d 张量中
有没有更有效的方法?也许是线性代数技巧或更多 pythonic 方法。
您可以使用 scipy.linalg.circulant()
:
scipy.linalg.circulant([1, 2, 3])
# array([[1, 3, 2],
# [2, 1, 3],
# [3, 2, 1]])
我相信您可以使用 torch.gather
通过构造适当的索引张量来实现此目的。这种方法也适用于批处理。
如果我们采用这种方法,objective 就是构建一个索引张量,其中每个值都引用 mtx_row
中的一个索引(这里是最后一个维度 dim=1
)。在这种情况下,它的形状为 (3, 3)
:
tensor([[0, 1, 2],
[2, 0, 1],
[1, 2, 0]])
您可以通过使用自己的转置广播 torch.arange
并对结果矩阵应用模来实现此目的:
>>> idx = (n-torch.arange(n)[None].T + torch.arange(n)[None]) % n
tensor([[0, 1, 2],
[2, 0, 1],
[1, 2, 0]])
让mtx_row
整形(2, 3)
:
>>> mtx_row
tensor([[0.3523, 0.0170, 0.1875],
[0.2156, 0.7773, 0.4563]])
从那里你需要 idx
和 mtx_row
所以它们有相同的形状:
>>> idx_ = idx[None].expand(len(mtx_row), -1, -1)
>>> val_ = mtx_row[:, None].expand(-1, n, -1)
然后我们可以在最后一个维度上应用torch.gather
dim=2
:
>>> val_.gather(-1, idx_)
tensor([[[0.3523, 0.0170, 0.1875],
[0.1875, 0.3523, 0.0170],
[0.0170, 0.1875, 0.3523]],
[[0.2156, 0.7773, 0.4563],
[0.4563, 0.2156, 0.7773],
[0.7773, 0.4563, 0.2156]]])
我想创建 2d 张量(或 numpy 数组,并不重要),其中每一行都将循环移位到第一行。我使用 for
循环:
import torch
import numpy as np
a = np.random.rand(33, 11)
miss_size = 64
lp_order = a.shape[1] - 1
inv_a = -np.flip(a, axis=1)
mtx_size = miss_size+lp_order # some constant
mtx_row = torch.cat((torch.from_numpy(inv_a), torch.zeros((a.shape[0], miss_size - 1 + a.shape[1]))), dim=1)
mtx_full = mtx_row.unsqueeze(1)
for i in range(mtx_size):
mtx_row = torch.roll(mtx_row, 1, 1)
mtx_full = torch.cat((mtx_full, mtx_row.unsqueeze(1)), dim=1)
需要解压缩,因为我将 2d 张量堆叠到 3d 张量中
有没有更有效的方法?也许是线性代数技巧或更多 pythonic 方法。
您可以使用 scipy.linalg.circulant()
:
scipy.linalg.circulant([1, 2, 3])
# array([[1, 3, 2],
# [2, 1, 3],
# [3, 2, 1]])
我相信您可以使用 torch.gather
通过构造适当的索引张量来实现此目的。这种方法也适用于批处理。
如果我们采用这种方法,objective 就是构建一个索引张量,其中每个值都引用 mtx_row
中的一个索引(这里是最后一个维度 dim=1
)。在这种情况下,它的形状为 (3, 3)
:
tensor([[0, 1, 2],
[2, 0, 1],
[1, 2, 0]])
您可以通过使用自己的转置广播 torch.arange
并对结果矩阵应用模来实现此目的:
>>> idx = (n-torch.arange(n)[None].T + torch.arange(n)[None]) % n
tensor([[0, 1, 2],
[2, 0, 1],
[1, 2, 0]])
让mtx_row
整形(2, 3)
:
>>> mtx_row
tensor([[0.3523, 0.0170, 0.1875],
[0.2156, 0.7773, 0.4563]])
从那里你需要 idx
和 mtx_row
所以它们有相同的形状:
>>> idx_ = idx[None].expand(len(mtx_row), -1, -1)
>>> val_ = mtx_row[:, None].expand(-1, n, -1)
然后我们可以在最后一个维度上应用torch.gather
dim=2
:
>>> val_.gather(-1, idx_)
tensor([[[0.3523, 0.0170, 0.1875],
[0.1875, 0.3523, 0.0170],
[0.0170, 0.1875, 0.3523]],
[[0.2156, 0.7773, 0.4563],
[0.4563, 0.2156, 0.7773],
[0.7773, 0.4563, 0.2156]]])