Python Pyrotch argsort排序,张量中有重复元素
我有一个向量Python Pyrotch argsort排序,张量中有重复元素,python,sorting,machine-learning,pytorch,tensor,Python,Sorting,Machine Learning,Pytorch,Tensor,我有一个向量a=[0,1,2,3,0,0,1,1,2,2,3,3]。我需要以一种递增的方式对它进行排序,以便它以有序的方式列出,并从中提取argsort。为了更好地解释这一点,我需要对A进行排序,使其返回B=[0,4,5,1,6,7,2,8,9,3,10,11]。但是,当我使用pyotch的torch.argsort(A)时,它返回B=[4,5,0,1,6,7,2,8,9,3,10,11] 我假设这样做的算法在我这边是无法控制的。有没有办法在不引入for循环的情况下实现这一点?这种操作是我的NN
a=[0,1,2,3,0,0,1,1,2,2,3,3]
。我需要以一种递增的方式对它进行排序,以便它以有序的方式列出,并从中提取argsort。为了更好地解释这一点,我需要对A进行排序,使其返回B=[0,4,5,1,6,7,2,8,9,3,10,11]
。但是,当我使用pyotch的torch.argsort(A)
时,它返回B=[4,5,0,1,6,7,2,8,9,3,10,11]
我假设这样做的算法在我这边是无法控制的。有没有办法在不引入for循环的情况下实现这一点?这种操作是我的NN模型的一部分,如果不有效地执行,将导致性能问题。谢谢 这里有一种方法:
- 使用numpy.argsort()对numpy数组进行排序
- 使用torch.from_numpy()将结果转换为张量
导入火炬 将numpy作为np导入 A=[0,1,2,3,0,0,1,1,2,2,3,3] x=np.数组(A) y=torch.from_numpy(np.argsort(x,kind='mergesort')) 打印(y)
argsort
it,然后再转移回PyTorch(如其他方法所建议的),这是不可能的
一旦我们有了这个布尔张量,我们就可以通过在转换布尔张量后检查1
的位置来找到所需的索引
这将为我们提供排序的输入
和索引
。因为我们只需要索引,所以我们可以通过索引最后一列(1
或-1
)来获取索引
以下是OP在评论中提供的另一个示例的结果:
In [55]: A_large = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9])
In [56]: boolean_large = A_large[:, None] == torch.unique(A_large)
In [57]: torch.nonzero(boolean_large.t())[:, -1]
Out[57]:
tensor([ 0, 10, 11, 1, 12, 13, 2, 14, 15, 3, 16, 17, 4, 18, 19, 5, 20, 21,
6, 22, 23, 7, 24, 25, 8, 26, 27, 9, 28, 29])
注意:与其他答案中提出的基于NumPy的解决方案不同,这里我们不必担心我们必须使用的排序算法的
种类,因为我们根本不使用任何排序。您可以尝试使用NumPy.argsort()
来查看它是否有效。我尝试使用NumPy.sort([0,1,2,3,0,0,1,1,2,3,3]))
结果是[0,4,5,1,6,7,2,8,9,3,10,11]
如您所愿。完美-谢谢!嗯,在我的例子中,当向量更大时,这似乎就失效了。以案例A=[0112344567809001234344556677889]
为例,需要组织这样的B=[01011112132141531634171819520262237242582627929]
。但是,np.argsort()返回:[10,0,11,1,13,12,15,14,2,3,17,16,19,18,4,21,5,20,6,22,23,25,7,24,27,8,26,9,28,29]
。已解决:要使用的排序算法需要是kind='mergesort',而不是默认的'quicksort'@AnubhavSingh。虽然这种方法似乎可行,但我们可能会遇到性能问题,因为numpy无法使用GPU,而且在CPU和GPU之间来回复制张量也会带来开销。此外,您可能会失去自动添加的功能,这是真正的切肉刀。非常感谢。当我想使用GPU时,我没有考虑这个问题。
In [53]: torch.nonzero(boolean.t())[:, -1]
Out[53]: tensor([ 0, 4, 5, 1, 6, 7, 2, 8, 9, 3, 10, 11])
In [55]: A_large = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9])
In [56]: boolean_large = A_large[:, None] == torch.unique(A_large)
In [57]: torch.nonzero(boolean_large.t())[:, -1]
Out[57]:
tensor([ 0, 10, 11, 1, 12, 13, 2, 14, 15, 3, 16, 17, 4, 18, 19, 5, 20, 21,
6, 22, 23, 7, 24, 25, 8, 26, 27, 9, 28, 29])