如果洗牌,这个 5-d numpy 数组几乎不占用 RAM

Posted

技术标签:

【中文标题】如果洗牌,这个 5-d numpy 数组几乎不占用 RAM【英文标题】:This 5-d numpy array takes up hardly no RAM if shuffled 【发布时间】:2021-05-04 06:34:52 【问题描述】:

我有一些图像以 80 块的形式存储在一个 numpy 数组中。

trainImages.shape
# (715, 80, 96, 96, 3)

例如trainImages 有 715 个块,每 80 个图像大小为 (96,96,3)。

数组是dtype=float32,所以它占用了相当多的RAM空间,大约6GB。

我用这段代码洗牌

shuffler = np.random.permutation(trainImages.shape[0])
trainImages = trainImages[shuffler]

我注意到 RAM 使用率下降到几乎为 0。形状仍然相同,我可以显示图像。所有和所有的阵列看起来都很好,但在洗牌后它几乎不占用任何 RAM。怎么可能?

我正在使用具有 25GB RAM 的 Google Colab Pro,并通过顶部的指示器监控 RAM 使用情况。

您可以通过将此代码粘贴到 Colab 笔记本中轻松重现此行为

import numpy as np
a = np.random.rand(715, 80, 96, 96, 3).astype(np.float32)
shuffler = np.random.permutation(a.shape[0])
a = a[shuffler]

我也尝试过洗牌相同的数组,但重新调整为(57200,96,96,1),所以我对每张图片都进行了洗牌。在这种情况下,正如预期的那样,我没有注意到 RAM 使用量有任何变化。

【问题讨论】:

Google Colab 是否显示交换使用量? 看起来好像没有任何交换... 你能仔细检查一下“几乎 0”到底是什么吗?我怀疑它实际上是从 18GB 下降了 6GB。 【参考方案1】:

您似乎内存不足。通常在numpy中切片时,结果是一个不占用大量内存的视图。但是,当使用布尔掩码或随机整数数组进行切片时,没有规律性,因此 numpy 不会返回视图而是返回副本。行内:

a = a[shuffler]

Python会先分配一个新的6GB数组,然后根据shuffler中的索引将数据复制到新数组中,最后将新数组重新分配给旧数组,释放旧数组的内存。但是,它必须在某一时刻分配 12GB!我怀疑只有 ~13GB 的 Colab 会杀死试图分配比允许更多内存的 python 内核。结果,您会看到 RAM 降至 0。

我不太确定重组后的阵列为什么会起作用,也许当您对其进行测试时,您有更多可用内存,所以您勉强能适应 13GB。

但是,为了更有效地洗牌样本,您可以做的是使用

np.random.shuffle(a)

此方法将随机播放数据的第一个轴,这应该可以防止内存溢出问题。

如果您需要以一致的顺序对两个不同数组的第一个轴进行 shuffle(例如输入特征 x 和输出标签 y),您可以在每次 suffle 之前设置一个种子,以确保两个 shuffle 是等效:

np.random.seed(42)
np.random.shuffle(x)
np.random.seed(42)
np.random.shuffle(y)

【讨论】:

我正在使用 Colab Pro,我有 25GB 的 RAM。我也尝试过使用较小的阵列,但我仍然可以注意到 RAM 使用率再次上升和下降。我会尝试np.random.shuffle。感谢您的提示。

以上是关于如果洗牌,这个 5-d numpy 数组几乎不占用 RAM的主要内容,如果未能解决你的问题,请参考以下文章

numpy.array 中的零条目是不是占用内存?

『Numpy』内存分析_利用共享内存创建数组

Numpy笔记 · Permutation

Numpy笔记 · Permutation

python [shuffle data]在其命令的打乱数据#python #numpy时对数据集进行洗牌

洗牌算法