从压缩表示转换张量的最佳方法
Best way to convert a tensor from a condensed representation
我有一个压缩格式的张量,表示稀疏 3-D 矩阵。我需要将它转换为普通矩阵(它实际代表的矩阵)。
因此,在我的例子中,矩阵的任何二维切片的每一行只能包含一个非零元素。作为数据,我有这些行中的每一行、值和它出现的索引。例如张量
inp = torch.tensor([[ 1, 2],
[ 3, 4],
[-1, 0],
[45, 1]])
表示一个4x5的矩阵(第一维来自张量的第一维,第二维来自元数据)A,其中A[0][2] = 1, A[1][4] = 3, A[2][0] = -1, A[3][1] = 45
.
这只是我的 Matrix 的一个二维切片,我有可变数量的切片。
我能够使用 sparse_coo_tensor:
通过以下方式对二维切片执行此操作
>>> torch.sparse_coo_tensor(torch.stack([torch.arange(0, 4), inp.t()[1]]), inp.t()[0], [4,5]).to_dense()
tensor([[ 0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 3],
[-1, 0, 0, 0, 0],
[ 0, 45, 0, 0, 0]])
这是完成此任务的最佳方法吗?有没有更简单、更易读的替代方案?
如何在不循环的情况下将其扩展到 3-D 矩阵?
对于 3-D 矩阵,您可以想象输入类似于
inp_list = torch.stack([inp, inp, inp, inp])
并且所需的输出将是上述输出堆叠 4 次。
我觉得如果我正确地创建一个索引数组我应该能够做一些事情,但是我想不出不使用某种循环的方法来做到这一点。
我相信你所说的是你有一个稀疏张量并且想要转换它。从 tf.sparse.to_dense and follow that with tensorflow.Tensor.eval()
开始
好的,在对不同类型的索引进行了大量实验之后,我开始使用它了。事实证明,答案就在 Advanced Indexing 中。不幸的是,PyTorch 文档没有详细介绍高级索引。 Here is a link for it in the Numpy documentation.
对于上述问题,此命令可以解决问题:
>>> k_lst = torch.zeros([4,4,5])
>>> k_lst[torch.arange(4).unsqueeze(1), torch.arange(4), inp_list[:,:,1]] = inp_list[:,:,0].float()
>>> k_lst
tensor([[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]]])
这正是我想要的。
我在搜索这个问题时学到了很多东西,我想把这个分享给任何偶然发现这个问题的人。那么,为什么会这样呢?答案在于 Broadcasting 的工作方式。如果您查看所涉及的不同索引张量的形状,您会发现它们(必然)是可广播的。
>>> torch.arange(4).unsqueeze(1).shape, torch.arange(4).shape, inp_list[:,:,1].shape
(torch.Size([4, 1]), torch.Size([4]), torch.Size([4, 4]))
显然,要访问此处的 k_lst 等 3-D 张量的元素,我们需要 3 个索引 - 每个维度一个。如果你给[]
算子3个相同形状的张量,它可以从3个张量中匹配对应的元素得到一堆合法的索引。
如果 3 个张量具有不同的形状,但可以广播(就像这里的情况),它会复制缺少张量的相关 rows/columns 所需的次数以获得具有相同形状的张量。
最终,在我的例子中,如果我们研究如何分配不同的值,这相当于做
k_lst[0,0,inp_list[0,0,1]] = inp_list[0,0,0].float()
k_lst[0,1,inp_list[0,1,1]] = inp_list[0,1,0].float()
k_lst[0,2,inp_list[0,2,1]] = inp_list[0,2,0].float()
k_lst[0,3,inp_list[0,3,1]] = inp_list[0,3,0].float()
k_lst[1,0,inp_list[1,0,1]] = inp_list[1,0,0].float()
k_lst[1,1,inp_list[1,1,1]] = inp_list[1,1,0].float()
.
.
.
k_lst[3,3,inp_list[3,3,1]] = inp_list[3,3,0].float()
这个格式让我想起了torch.Tensor.scatter()
,但是如果能用它来解决这个问题,我还没想好怎么办。
我有一个压缩格式的张量,表示稀疏 3-D 矩阵。我需要将它转换为普通矩阵(它实际代表的矩阵)。 因此,在我的例子中,矩阵的任何二维切片的每一行只能包含一个非零元素。作为数据,我有这些行中的每一行、值和它出现的索引。例如张量
inp = torch.tensor([[ 1, 2],
[ 3, 4],
[-1, 0],
[45, 1]])
表示一个4x5的矩阵(第一维来自张量的第一维,第二维来自元数据)A,其中A[0][2] = 1, A[1][4] = 3, A[2][0] = -1, A[3][1] = 45
.
这只是我的 Matrix 的一个二维切片,我有可变数量的切片。 我能够使用 sparse_coo_tensor:
通过以下方式对二维切片执行此操作>>> torch.sparse_coo_tensor(torch.stack([torch.arange(0, 4), inp.t()[1]]), inp.t()[0], [4,5]).to_dense()
tensor([[ 0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 3],
[-1, 0, 0, 0, 0],
[ 0, 45, 0, 0, 0]])
这是完成此任务的最佳方法吗?有没有更简单、更易读的替代方案? 如何在不循环的情况下将其扩展到 3-D 矩阵? 对于 3-D 矩阵,您可以想象输入类似于
inp_list = torch.stack([inp, inp, inp, inp])
并且所需的输出将是上述输出堆叠 4 次。
我觉得如果我正确地创建一个索引数组我应该能够做一些事情,但是我想不出不使用某种循环的方法来做到这一点。
我相信你所说的是你有一个稀疏张量并且想要转换它。从 tf.sparse.to_dense and follow that with tensorflow.Tensor.eval()
开始好的,在对不同类型的索引进行了大量实验之后,我开始使用它了。事实证明,答案就在 Advanced Indexing 中。不幸的是,PyTorch 文档没有详细介绍高级索引。 Here is a link for it in the Numpy documentation.
对于上述问题,此命令可以解决问题:
>>> k_lst = torch.zeros([4,4,5])
>>> k_lst[torch.arange(4).unsqueeze(1), torch.arange(4), inp_list[:,:,1]] = inp_list[:,:,0].float()
>>> k_lst
tensor([[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]],
[[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 3.],
[-1., 0., 0., 0., 0.],
[ 0., 45., 0., 0., 0.]]])
这正是我想要的。
我在搜索这个问题时学到了很多东西,我想把这个分享给任何偶然发现这个问题的人。那么,为什么会这样呢?答案在于 Broadcasting 的工作方式。如果您查看所涉及的不同索引张量的形状,您会发现它们(必然)是可广播的。
>>> torch.arange(4).unsqueeze(1).shape, torch.arange(4).shape, inp_list[:,:,1].shape
(torch.Size([4, 1]), torch.Size([4]), torch.Size([4, 4]))
显然,要访问此处的 k_lst 等 3-D 张量的元素,我们需要 3 个索引 - 每个维度一个。如果你给[]
算子3个相同形状的张量,它可以从3个张量中匹配对应的元素得到一堆合法的索引。
如果 3 个张量具有不同的形状,但可以广播(就像这里的情况),它会复制缺少张量的相关 rows/columns 所需的次数以获得具有相同形状的张量。
最终,在我的例子中,如果我们研究如何分配不同的值,这相当于做
k_lst[0,0,inp_list[0,0,1]] = inp_list[0,0,0].float()
k_lst[0,1,inp_list[0,1,1]] = inp_list[0,1,0].float()
k_lst[0,2,inp_list[0,2,1]] = inp_list[0,2,0].float()
k_lst[0,3,inp_list[0,3,1]] = inp_list[0,3,0].float()
k_lst[1,0,inp_list[1,0,1]] = inp_list[1,0,0].float()
k_lst[1,1,inp_list[1,1,1]] = inp_list[1,1,0].float()
.
.
.
k_lst[3,3,inp_list[3,3,1]] = inp_list[3,3,0].float()
这个格式让我想起了torch.Tensor.scatter()
,但是如果能用它来解决这个问题,我还没想好怎么办。