2016-06-14 39 views
2

我有两个不同的numpy数组,我想以异步方式将它们洗牌。切片没有意见(或:洗牌多个阵列)

目前的解决方案是从https://www.tensorflow.org/versions/r0.8/tutorials/mnist/pros/index.html取出并进行如下:

perm = np.arange(self.no_images_train) 
np.random.shuffle(perm) 
self.images_train = self.images_train[perm] 
self.labels_train = self.labels_train[perm] 

的问题是,它的每个I做时间加倍存储器。不知怎的,旧的数组没有被删除,可能是因为切片操作符创建视图,我猜。我尝试了下面的改变,出于纯粹的绝望:

perm = np.arange(self.no_images_train) 
np.random.shuffle(perm) 

n_images_train = self.images_train[perm] 
n_labels_train = self.labels_train[perm]    

del self.images_train 
del self.labels_train 
gc.collect() 

self.images_train = n_images_train 
self.labels_train = n_labels_train 

仍然是一样的,内存泄漏,我经历了几个操作后内存不足。

顺便说一句,这两个数组的排名是100000,224,244,1和100000,1。

我知道这已经在这里处理过了(Better way to shuffle two numpy arrays in unison),但答案并没有帮助我,因为提供的解决方案需要再次切片。

感谢您的任何帮助。

+1

那些不是意见。您可能在其他地方有其他对原始数组的引用。 – user2357112

+0

*“...因为切片运算符创建视图我猜。”*切片*确实*创建视图,但您显示的代码不切片。当你写'a [perm]'时,就会复制一份。 “切片”是指使用冒号的操作:“开始:结束:步骤”,例如, '0:4','4:'等 –

+0

*“...以异步方式。”*我想你错过了一个空间。基于下面的内容,我认为你的意思是“以同步的方式”。 –

回答

1

一种以同步方式就地排列两个大型数组的方法是保存随机数发生器的状态,然后洗牌第一个数组。然后恢复状态并洗牌第二个数组。

例如,这里有我的两个数组:

In [48]: a 
Out[48]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) 

In [49]: b 
Out[49]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) 

保存随机数生成器的当前内部状态:

In [50]: state = np.random.get_state() 

洗牌a就地:

In [51]: np.random.shuffle(a) 

恢复随机数发生器的内部状态:

In [52]: np.random.set_state(state) 

洗牌b就地:

In [53]: np.random.shuffle(b) 

检查排列是相同的:

In [54]: a 
Out[54]: array([13, 12, 11, 15, 10, 5, 1, 6, 14, 3, 9, 7, 0, 8, 4, 2]) 

In [55]: b 
Out[55]: array([13, 12, 11, 15, 10, 5, 1, 6, 14, 3, 9, 7, 0, 8, 4, 2]) 

为您的代码,这将是这样的:

state = np.random.get_state() 
np.random.shuffle(self.images_train) 
np.random.set_state(state) 
np.random.shuffle(self.labels_train) 
+0

它确实有帮助,谢谢。但是,我确实发现了一个更好的东西:以规避这个问题。我决定不要周期性地洗牌数据,而只是重新创建一个置换矢量并对其进行采样。我仍然想知道原始解决方案失败的原因。 – Flonks

+0

然而,这个解决方案需要两次调用随机数发生器,这可能会成为一个性能瓶颈。您可以使用不同的随机数生成器来减少这种影响。 – Guillaum

+0

@Guillaum是的,对随机数生成器的两次调用(以生成相同的序列!)可能是个问题,因此建议进行一些性能测试。如何使用不同的发电机帮助? –

0

其实我不认为numpy或python有问题。 Numpy使用系统malloc/free分配阵列,这导致内存碎片(请参阅Memory Fragmentation on SO)。

所以我猜你的内存配置文件可能会增加,并在系统能够减少碎片时突然下降,如果可能的话。

+0

内存以6GB的步长增加,在230GB的时间内,我用64GB的物理内存终止了我的机器上的进程。我不确定这可以完全归因于碎片。特别是因为没有真正的理由,为什么应该有超过6GB的内存在较长的时间内使用(除了临时分配复制等)。 – Flonks