我试图从numpy使用arpgpartition,但似乎出现了问题,我似乎无法弄明白。以下是发生的事情:
这些是排序数组[u'Location: New Delhi / Safdarjung',
u'Current Time: Feb 12, 2017 at 10:29:52 am',
u'Latest Report: Feb 12, 2017 at 8:30 am',
u'Visibility: 1 km',
u'Pressure: 102.12 kPa',
u'Humidity: 95%',
u'Dew Point: 10 \uc9f8C']
norms
但是当我使用np.sort(norms)[:5]
array([ 53.64759445, 54.91434479, 60.11617279, 64.09630585, 64.75318909], dtype=float32)
indices_sorted = np.argpartition(norms, 5)[:5]
当我认为我应该得到与排序数组相同的结果?
当我使用3作为参数norms[indices_sorted]
array([ 60.11617279, 64.09630585, 53.64759445, 54.91434479, 64.75318909], dtype=float32)
indices_sorted = np.argpartition(norms, 3)[:3]
这对我来说没有多大意义,希望有人可以提供一些见解?
编辑:将这个问题改为argpartition是否保留k个分区元素的顺序更有意义。
答案 0 :(得分:14)
我们需要使用按排序顺序保存的索引列表,而不是将第k个参数作为标量。因此,要保持第一个5
元素的排序性质,而不是np.argpartition(a,5)[:5]
,只需执行 -
np.argpartition(a,range(5))[:5]
这是一个让事情变得清晰的示例 -
In [84]: a = np.random.rand(10)
In [85]: a
Out[85]:
array([ 0.85017222, 0.19406266, 0.7879974 , 0.40444978, 0.46057793,
0.51428578, 0.03419694, 0.47708 , 0.73924536, 0.14437159])
In [86]: a[np.argpartition(a,5)[:5]]
Out[86]: array([ 0.19406266, 0.14437159, 0.03419694, 0.40444978, 0.46057793])
In [87]: a[np.argpartition(a,range(5))[:5]]
Out[87]: array([ 0.03419694, 0.14437159, 0.19406266, 0.40444978, 0.46057793])
请注意argpartition
在性能方面有意义,如果我们想要获得一小部分元素的排序索引,让我们说k
元素的数量,这只是总数的一小部分元素数量。
让我们使用更大的数据集并尝试获取所有元素的排序索引,以使上述要点清晰明了 -
In [51]: a = np.random.rand(10000)*100
In [52]: %timeit np.argpartition(a,range(a.size-1))[:5]
10 loops, best of 3: 105 ms per loop
In [53]: %timeit a.argsort()
1000 loops, best of 3: 893 µs per loop
因此,要对所有元素进行排序,np.argpartition
不是最佳选择。
现在,假设我希望只使用该大数据集获得前5个元素的排序索引,并保留其中的顺序 -
In [68]: a = np.random.rand(10000)*100
In [69]: np.argpartition(a,range(5))[:5]
Out[69]: array([1647, 942, 2167, 1371, 2571])
In [70]: a.argsort()[:5]
Out[70]: array([1647, 942, 2167, 1371, 2571])
In [71]: %timeit np.argpartition(a,range(5))[:5]
10000 loops, best of 3: 112 µs per loop
In [72]: %timeit a.argsort()[:5]
1000 loops, best of 3: 888 µs per loop
非常有用!
答案 1 :(得分:5)
鉴于直接排序子集的任务(顶部 k ,排序顺序中首先是最重要的意义),有两个内置解决方案:argsort
和argpartition
cf. @Divakar的回答。
argsort
的输出上应用argpartition
>>> def top_k_sort(a, k):
... return np.argsort(a)[:k]
...
>>> def top_k_argp(a, k):
... return np.argpartition(a, range(k))[:k]
...
>>> def top_k_hybrid(a, k):
... b = np.argpartition(a, k)[:k]
... return b[np.argsort(a[b])]
>>> k = 100
>>> timeit.timeit('f(a,k)', 'a=rng((100000,))', number = 1000, globals={'f': top_k_sort, 'rng': np.random.random, 'k': k})
8.348663672804832
>>> timeit.timeit('f(a,k)', 'a=rng((100000,))', number = 1000, globals={'f': top_k_argp, 'rng': np.random.random, 'k': k})
9.869098862167448
>>> timeit.timeit('f(a,k)', 'a=rng((100000,))', number = 1000, globals={'f': top_k_hybrid, 'rng': np.random.random, 'k': k})
1.2305558240041137
argsort
是O(n log n),范围参数的argpartition
似乎是O(nk)(?),argpartition
+ argsort
是O( n + k log k)
因此,在一个有趣的制度 n >> k >> 1混合方法预计最快
答案 2 :(得分:5)
让我们以一种简化的方式来描述 partition 方法,该方法有助于大量了解 argpartition
下面的示例中,如果我们执行 C = numpy.argpartition(A,3),C将是获取B中每个元素相对于A数组的位置的结果数组。即:
Idx(z) = index of element z in array A
then C would be
C = [ Idx(B[0]), Idx(B[1]), Idx(B[2]), Idx(X), Idx(B[4]), ..... Idx(B[N]) ]
如前所述,该方法非常有用,当您有一个巨大的数组并且只对选定的一组有序元素感兴趣,而不对整个数组感兴趣时,该方法非常方便。