【问题标题】:Coverting big list of 2D elements to 3D NumPy array - memory problem将 2D 元素的大列表转换为 3D NumPy 数组 - 内存问题
【发布时间】:2019-10-22 05:35:16
【问题描述】:

在将 2D 元素的大列表转换为 3D numpy 数组时,我遇到了内存问题。 我正在使用 CoLab 环境。我正在做与医学图像(.nii)、CNN 网络相关的深度学习项目。这些图像是浮动类型的(因为标准化)。 我将图像(一个通道)作为列表加载到内存中,然后将其分成小块(11x11 分辨率)。结果,我有 11650348 - 11x11 图像的列表。

获取序列。 内存信息:

Gen RAM 免费:12.8 GB |进程大小:733.4 MB

可用 GPU RAM:15079MB |已使用:0MB |使用率 0% |总计 15079MB

获取序列...

时间:109.60107789899996

Gen RAM 免费:11.4 GB |进程大小:2.8 GB

可用 GPU RAM:15079MB |已使用:0MB |使用率 0% |总计 15079MB

[INFO] 11507902 个图像列表中的数据矩阵

现在我正在使用 np.array 方法将列表转换为数组。

内存信息:

Gen RAM 免费:11.8 GB |进程大小:2.1 GB

可用 GPU RAM:15079MB |已使用:0MB |使用率 0% |总计 15079MB

掩饰....

免费一代 RAM:6.7 GB |进程大小:7.3 GB

可用 GPU RAM:15079MB |已使用:0MB |使用率 0% |总计 15079MB

我们的训练数据的形状:(11650348, 11, 11, 1) SPLIT!请参阅下面的代码。

如你所见,我失去了很多记忆。为什么会这样?

我尝试使用 np.asarraynp.array 和参数 copy。没用。

负责分割原始图像的代码。

def get_parts(image, segmented):
    T2 = image[0]
    seg = segmented[0]
    labels = []
    val = [];
    window_width = 5
    zlen, ylen, xlen = T2.shape
    nda = np.zeros((240, 240))
    for x in range(0, xlen):
        for y in range(0, ylen):
            for z in range(0, zlen):
                if T2[z, y, x] != 0:
                    xbegin = x - window_width
                    xend = x + window_width + 1
                    ybegin = y - window_width
                    yend = y + window_width + 1
                    val.append(T2[z, ybegin:yend, xbegin:xend])
                    labels.append(seg[z, y, x])
    #np_array_01 = np.asarray(val)
    #np_array_02 = np.asarray(labels)
    return val, labels

获取值

for x in range(0, length):
   data, labels = get_parts(T2_images[x], segmented[x])
   uber_dane.extend(data)
   uber_label.extend(labels)

我正在以这种方式对其进行改造。

X_train, X_test, y_train, y_test = train_test_split(uber_dane, uber_label,test_size=0.2, random_state=0)
#LABELS
y_train = np.array(y_train)
y_test= np.array(y_test)
y_train = np.expand_dims(y_train, axis=3)
y_test = np.expand_dims(y_test, axis=3)
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

#DATA - HERE IS A PROBLEM
X_train = np.array(X_train)
X_test= np.array(X_test)
print(sys.getsizeof(X_train))
print(sys.getsizeof(X_test))
X_train = np.expand_dims(X_train, axis=4)
X_test = np.expand_dims(X_test, axis=4)

你怎么看?也许我做错了什么。 Array 应该比 list 占用更少的内存:/ 我通过 stackoverflow 和 Internet 进行了一些搜索,但没有帮助。我忍不住了。

我希望,你会有一些好主意:D

2019 年 8 月 6 日更新

我在 pyCharm 中运行了我的代码,出现了不同的错误:

X_train = np.array(uber_dane) ValueError: array is too big; arr.size * arr.dtype.itemsize 大于最大可能大小。

我有: Python 3.6.3(v3.6.3:2c5fed8,2017 年 10 月 3 日,17:26:49)[MSC v.1900 32 位(英特尔)] 在 win32 上 所以python试图分配超过3GB。

lmfit minimize fails with ValueError: array is too big

你怎么看?

【问题讨论】:

标签: python numpy tensorflow keras deep-learning


【解决方案1】:

您打算使用fitevaluate 还是predict?如果是这样,您可以尝试使用自定义 generator 仅加载一些数据并使用 fit_generator (evaluate_generator, ...)

【讨论】:

  • 是的,我打算使用它们。我不确定发电机是否会帮助我。我必须做一个算法来分割脑瘤,每个脑瘤都是不同的,形状、长度和位置。
  • 生成器不会“生成”更多数据,而只是逐渐加载数据(即不是加载 11650348 张图像,您可以每次在内存中轻松加载 10000 张图像,然后生成器将加载接下来的 10000 张当fit请求时)
  • 你是对的!我真的很抱歉,我的坏。我想到了 ImageDataGenerator。我会试试的!
  • 但是 CNN 中的梯度是什么?什么时候放10000张图片,所以我知道放100000张就不同了。
  • @Damian 不是每个batch step都计算梯度吗?如果批量大小保持不变,则不会有任何差异。
【解决方案2】:

当您创建小块列表时,实际上您不会创建 numpy 数组列表,而是创建 numpy 视图列表(请参阅this section 中的第一个注释)。因此,此对象不存储所有数据,而仅引用大型数组(在您的情况下为 T2_images[i])。

你可以在这个例子中观察到它(当你修改 slice 的元素时实际上你指的是源数组):

x = np.arange(5)
y = x[:2]
y[0] = 3
print(x)

当您将此列表转换为三维 numpy 数组时,必须从大数组中复制所有必需的数据。

【讨论】:

  • 那么有没有解决办法?这是将列表更改为数组的唯一方法吗?
  • 你真的需要 (11650348, 11, 11) numpy 数组吗?假设您使用的是 float32,您至少需要 11650348*11*11*4 字节,大约等于 5.2 GB(这与您的观察结果一致)。您只能将类型更改为 float16 以减少所需的内存。
  • 但是你想用它作为批处理来训练 CNN 吗?神经网络需要大量内存来存储中间结果,因此可以肯定它不适合内存。此外,我认为使用所有 11M 块来训练 NN 并不是一个好主意。如果我是你,我会在大图像中绘制一些位置并将其用作小批量(你可以选择这样的批量大小以便能够在训练期间将神经网络拟合到内存中)。然后你可以移动到另一个图像或绘制另一批图像片段。
  • 我不明白你的意思。可以私信聊聊吗?
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2019-10-31
  • 2017-03-10
  • 2017-07-26
  • 2015-12-26
  • 2019-06-11
相关资源
最近更新 更多