这是np.argpartition/np.argsort 的一个技巧。
这个想法是-
现在,我们可以使用np.argpartition 进一步提高性能,以使用k=50 沿每一行进行分区。
因此,我们将有一个矢量化解决方案,就像这样 -
np.sort(np.random.rand(10000,365).argpartition(50,axis=1)[:,:50])
让我们验证输出数据的一致性
In [209]: out = np.sort(np.random.rand(10000,365).argpartition(50,axis=1)[:,:50])
In [210]: count = np.bincount(out.ravel(), minlength=365)
In [211]: print count.min(), count.max()
1277 1466
看起来很统一!让我们进入主要业务,即获取性能数据。
运行时测试
方法-
# Original approach
def org_app():
return np.array([np.sort(np.random.choice(365, 50, replace=False)) for _ in range(10000)])
# @Nils Werner's soln
def sort_random_choice():
return np.sort([np.random.choice(365, 50, replace=False) for _ in range(10000)], axis=1)
# @Miriam Farber's soln
def random_permute():
l = np.array([True]*50 + [False]*315)
total = np.arange(1,366)
return np.array([total[np.random.permutation(l)] for _ in range(10000)])
# Proposed in this post
def argpartition_sort(nrows=10000, maxc=365, ncols=50):
return np.sort(np.random.rand(nrows,maxc).argpartition(ncols,axis=1)[:,:ncols])
# @ayhan's soln
def while_loop():
arr = np.random.choice(365, 10000)
for i in range(49):
arr2 = np.random.choice(365, 10000)
comp = (arr2 == arr)
while comp.any():
duplicate = comp if i==0 else comp.any(axis=0)
arr2[duplicate] = np.random.choice(365, duplicate.sum())
comp = (arr2 == arr)
arr = np.vstack([arr, arr2])
arr = arr.T
arr.sort(axis=1)
return arr
时间安排 -
In [44]: %timeit org_app()
...: %timeit sort_random_choice()
...: %timeit random_permute()
...: %timeit argpartition_sort()
...: %timeit while_loop()
...:
1 loops, best of 3: 258 ms per loop
1 loops, best of 3: 232 ms per loop
10 loops, best of 3: 166 ms per loop
10 loops, best of 3: 79.9 ms per loop
10 loops, best of 3: 58.6 ms per loop