Numpy:使用不同的种子多次统一洗牌数组
Numpy: shuffle arrays in unison multiple times with different seeds
我有多个 numpy 数组,它们的行数 (axis_0) 相同,我想一致地洗牌。一次洗牌后,我想用不同的随机种子再次洗牌。
到目前为止,我使用的解决方案来自
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 () 的解决方案:
def shuffle_in_unison(a, b):
n_elem = a.shape[0]
indeces = np.random.permutation(n_elem)
return a[indeces], b[indeces]
唯一的缺点就是这不是原地操作,对于我这样的大数组(500G)有点可惜
我不知道你设置状态的方式有什么问题。但是,我找到了另一种解决方案:不是洗牌 n
数组,而是使用 numpy.random.choice
只洗牌一次,然后重新排序所有数组。
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]
我不知道你到底在做什么,但你没有选择那个页面上得票最多或得票第二多的解决方案。尝试 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]
我通常不必一次多次打乱我的数据。但是这个函数可以容纳任意数量的输入数组,以及任意数量的随机洗牌 - 并且它就地洗牌。
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
拆分或使用切片引用 - 取决于应用程序。
我有多个 numpy 数组,它们的行数 (axis_0) 相同,我想一致地洗牌。一次洗牌后,我想用不同的随机种子再次洗牌。
到目前为止,我使用的解决方案来自 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 (
def shuffle_in_unison(a, b):
n_elem = a.shape[0]
indeces = np.random.permutation(n_elem)
return a[indeces], b[indeces]
唯一的缺点就是这不是原地操作,对于我这样的大数组(500G)有点可惜
我不知道你设置状态的方式有什么问题。但是,我找到了另一种解决方案:不是洗牌 n
数组,而是使用 numpy.random.choice
只洗牌一次,然后重新排序所有数组。
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]
我不知道你到底在做什么,但你没有选择那个页面上得票最多或得票第二多的解决方案。尝试 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]
我通常不必一次多次打乱我的数据。但是这个函数可以容纳任意数量的输入数组,以及任意数量的随机洗牌 - 并且它就地洗牌。
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
拆分或使用切片引用 - 取决于应用程序。