你还可以使用
np.random.permutation
生成行索引的随机排列,然后使用带有
axis = 0
的
np.take
来索引
X
的行。此外,
np.take
可通过使用
out=
选项在原始数组
X
上进行重写,这将节省内存。因此,实现应如下所示-
np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X)
运行示例 -
In [23]: X
Out[23]:
array([[ 0.60511059, 0.75001599],
[ 0.30968339, 0.09162172],
[ 0.14673218, 0.09089028],
[ 0.31663128, 0.10000309],
[ 0.0957233 , 0.96210485],
[ 0.56843186, 0.36654023]])
In [24]: np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X);
In [25]: X
Out[25]:
array([[ 0.14673218, 0.09089028],
[ 0.31663128, 0.10000309],
[ 0.30968339, 0.09162172],
[ 0.56843186, 0.36654023],
[ 0.0957233 , 0.96210485],
[ 0.60511059, 0.75001599]])
额外的性能提升
这里有一个技巧可以通过使用np.argsort()
来加速np.random.permutation(X.shape[0])
-
np.random.rand(X.shape[0]).argsort()
加速结果 -
In [32]: X = np.random.random((6000, 2000))
In [33]: %timeit np.random.permutation(X.shape[0])
1000 loops, best of 3: 510 µs per loop
In [34]: %timeit np.random.rand(X.shape[0]).argsort()
1000 loops, best of 3: 297 µs per loop
因此,洗牌方案可以修改为 -
np.take(X,np.random.rand(X.shape[0]).argsort(),axis=0,out=X)
运行时测试 -
这些测试包括本帖中列出的两种方法以及@Kasramvd的解决方案
中基于np.shuffle
的方法。
In [40]: X = np.random.random((6000, 2000))
In [41]: %timeit np.random.shuffle(X)
10 loops, best of 3: 25.2 ms per loop
In [42]: %timeit np.take(X,np.random.permutation(X.shape[0]),axis=0,out=X)
10 loops, best of 3: 53.3 ms per loop
In [43]: %timeit np.take(X,np.random.rand(X.shape[0]).argsort(),axis=0,out=X)
10 loops, best of 3: 53.2 ms per loop
所以,似乎只有在内存受限的情况下才应该使用基于np.take
的解决方案,否则基于np.random.shuffle
的解决方案看起来更合适。
np.random.shuffle(x)
,文档中指出,“此函数仅沿多维数组的第一个索引洗牌数组”,这对您来说已经足够了,对吧?显然,启动时需要一些时间,但从那时起,它与原始矩阵一样快。 - Dima Tisneknp.random.shuffle(x)
相比,对nd-array的索引进行洗牌并从洗牌后的索引获取数据是解决此问题的更有效方法。有关详细的比较,请参见我在下面的回答中(https://dev59.com/Z1sV5IYBdhLWcg3w6iV8#43716153)。 - John