Numpy:用不同的种子多次混合阵列

时间:2017-11-07 10:36:40

标签: python arrays numpy shuffle

我有多个具有相同行数(axis_0)的numpy数组,我想要一致地进行洗牌。在一次洗牌之后,我想用另一种随机种子再次洗牌。

到目前为止,我已经使用了解决方案 Better way to shuffle two numpy arrays in unison

def shuffle_in_unison(a, b):
    rng_state = numpy.random.get_state()
    numpy.random.shuffle(a)
    numpy.random.set_state(rng_state)
    numpy.random.shuffle(b)

然而,由于rng_state总是相同的,因此对多个同步混洗不起作用。

<小时/> 我尝试使用RandomState为每次通话获取不同的种子,但这对于单一的同步改组甚至不起作用:

a = np.array([1,2,3,4,5])
b = np.array([10,20,30,40,50])

def shuffle_in_unison(a, b):
    r = np.random.RandomState() # different state from /dev/urandom for each call
    state = r.get_state()
    np.random.shuffle(a) # array([4, 2, 1, 5, 3])
    np.random.set_state(state)
    np.random.shuffle(b) # array([40, 20, 50, 10, 30])
    # -> doesn't work
    return a,b

for i in xrange(10):
    a,b = shuffle_in_unison(a,b)
    print a,b

我做错了什么?

修改:

对于没有像我这样的大型阵列的每个人,只需使用Francesco(https://stackoverflow.com/a/47156309/3955022)的解决方案:

def shuffle_in_unison(a, b):
    n_elem = a.shape[0]
    indeces = np.random.permutation(n_elem)
    return a[indeces], b[indeces]

唯一的缺点是这不是就地操作,这对像我这样的大型阵列(500G)来说很可惜。

3 个答案:

答案 0 :(得分:4)

我不知道你设置状态的方式有什么问题。但是我找到了另一种解决方案:不是改组n数组,而是用numpy.random.choice对它们的indeces进行一次洗牌,然后重新排序所有数组。

a = np.array([1,2,3,4,5])
b = np.array([10,20,30,40,5])

def shuffle_in_unison(a, b):
     n_elem = a.shape[0]
     indeces = np.random.choice(n_elem, size=n_elem, replace=False)
     return a[indeces], b[indeces]

 for i in xrange(5):
     a, b = shuffle_in_unison(a ,b)
     print(a, b)

我明白了:

[5 2 4 3 1] [50 20 40 30 10]
[1 3 4 2 5] [10 30 40 20 50]
[1 2 5 4 3] [10 20 50 40 30]
[3 2 1 4 5] [30 20 10 40 50]
[1 2 5 3 4] [10 20 50 30 40]

修改

感谢@Divakar的建议。 以下是使用numpy.random.premutation

获取相同结果的更具可读性的方法
def shuffle_in_unison(a, b):
     n_elem = a.shape[0]
     indeces = np.random.permutation(n_elem)
     return a[indeces], b[indeces]

答案 1 :(得分:1)

我并不确切知道你做得怎么样,但是你没有选择在该页面上投票最多或投票次数最多的解决方案。试试this一个:

from sklearn.utils import shuffle
for i in range(10):
    X, Y = shuffle(X, Y, random_state=i)
    print ("X - ", X, "Y - ", Y)

输出:

X -  [3 5 1 4 2] Y -  [30 50 10 40 20]
X -  [1 5 2 3 4] Y -  [10 50 20 30 40]
X -  [2 4 5 3 1] Y -  [20 40 50 30 10]
X -  [3 1 4 2 5] Y -  [30 10 40 20 50]
X -  [3 2 1 5 4] Y -  [30 20 10 50 40]
X -  [4 3 2 1 5] Y -  [40 30 20 10 50]
X -  [1 5 4 3 2] Y -  [10 50 40 30 20]
X -  [1 3 4 5 2] Y -  [10 30 40 50 20]
X -  [2 4 3 1 5] Y -  [20 40 30 10 50]
X -  [1 2 4 3 5] Y -  [10 20 40 30 50]

答案 2 :(得分:1)

通常,我通常不需要一次多次洗牌。但是此函数可容纳任意数量的输入数组,以及任意数量的随机混洗-并且可以就地混洗。

import numpy as np


def shuffle_arrays(arrays, shuffle_quant=1):
    assert all(len(arr) == len(arrays[0]) for arr in arrays)
    max_int = 2**(32 - 1) - 1

    for i in range(shuffle_quant):
        seed = np.random.randint(0, max_int)
        for arr in arrays:
            rstate = np.random.RandomState(seed)
            rstate.shuffle(arr)

并且可以像这样使用

a = np.array([1, 2, 3, 4, 5])
b = np.array([10,20,30,40,50])
c = np.array([[1,10,11], [2,20,22], [3,30,33], [4,40,44], [5,50,55]])

shuffle_arrays([a, b, c], shuffle_quant=5)

一些注意事项:

  • 方法使用NumPy,不使用其他软件包。
  • 断言确保所有输入数组的长度相同 他们的第一个维度。
  • max_int将随机种子保持在int32范围内。
  • 数组按其第一个维度在原位随机排列-没有返回任何内容。

随机播放后,可以根据应用使用np.split拆分数据或使用切片来引用数据。