如果洗牌,这个 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的主要内容,如果未能解决你的问题,请参考以下文章