带Tensorflow的Keras:根据需要使用内存[ResourceExhaustedError]

时间:2018-06-26 03:11:52

标签: python tensorflow keras deep-learning

因此,我尝试使用多用途数据集来保留CNN,并且它会暗示当我添加足够的数据时(例如,当我添加多个集合时,或者当我尝试添加具有一百万个样本的集合时)引发ResourceExhaustedError

关于说明here,我尝试添加

from keras.backend.tensorflow_backend import set_session
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3
set_session(tf.Session(config=config))

对我的代码来说,但这并没有什么不同。 在打印出config.gpu_options.per_process_gpu_memory_fraction之后,我看到了0.3,以便接缝正常。

我什至可以放一个config.gpu_options.allow_growth = True,但是除了想一次使用所有内存只是发现不够用之外,它并不想做任何事情。

我正在尝试用来训练此CNN的计算机具有4个GTX1080 Ti,每个都有12gb的专用内存。

编辑:很抱歉没有指定我如何加载数据,老实说我没有意识到有不止一种方法。当我学习时,他们总是有一些示例,其中加载了已经内置的数据集,花了我一段时间才意识到如何加载一个自我提供的数据集。

我这样做的方法是创建两个numpy数组。一个具有路径或每个图像,另一个具有相应的标签。这是最基本的示例:

data_dir = "folder_name"

# There is a folder for every form and in that folder is every line of that form
for filename in glob.glob(os.path.join(data_dir, '*', '*')):

    # the format for file names are: "{author id}-{form id}-{line number}.png"
    # filename is a path to the file so .split('\\')[-1] get's the raw file name without the path and .split('-')[0] get's the author id
    authors.append(filename.split('\\')[-1].split('-')[0])
    files.append(filename)

#keras requires numpy arrays 
img_files  = np.asarray(files)
img_targets = np.asarray(authors)

3 个答案:

答案 0 :(得分:3)

确定要使用巨型batch_size吗?

“添加数据”:老实说,我不知道这意味着什么,如果您能用代码准确地描述您在这里所做的事情,那将会有所帮助。

样本数量完全不会对GPU内存造成任何问题。导致问题的原因是batch_size

加载巨大的数据集可能会导致CPU RAM问题,与keras / tensorflow无关。 numpy数组太大的问题。 (您可以通过“不创建任何模型”简单地加载数据来进行测试)

如果这是您的问题,则应使用generator逐步加载批次。同样,由于您的问题中绝对没有代码,因此我们无济于事。

但这是简单地为图像创建生成器的两种形式:

  • 使用现有的ImageDataGenerator及其flow_from_directory()方法explained here
  • 创建自己的编码生成器,可以是:

循环生成器的快速示例:

def imageBatchGenerator(imageFiles, imageLabels, batch_size):
    while True:
        batches = len(imageFiles) // batch_size
        if len(imageFiles) % batch_size > 0:
            batches += 1

        for b in range(batches):
            start = b * batch_size
            end = (b+1) * batch_size

            images = loadTheseImagesIntoNumpy(imageFiles[start:end])
            labels = imageLabels[start:end]

            yield images,labels
  

警告:即使使用发电机,也必须确保批次大小不要太大!

使用它:

model.fit_generator(imageBatchGenerator(files,labels,batchSize), steps_per_epoch = theNumberOfBatches, epochs= ....)

在GPU之间划分模型

您应该能够决定哪个GPU处理哪些层,这“可能”可以优化您的RAM使用率。

示例,在创建模型时:

with tf.device('/gpu:0'):
    createLayersThatGoIntoGPU0

with tf.device('/gpu:1'):
    createLayersThatGoIntoGPU1

#you will probably need to go back to a previous GPU, as you must define your layers in a proper sequence
with tf.device('/cpu:0'):
    createMoreLayersForGPU0

#and so on

我不确定这是否会更好,但也值得尝试。

在此处查看更多详细信息:https://keras.io/getting-started/faq/#how-can-i-run-a-keras-model-on-multiple-gpus

答案 1 :(得分:0)

引发ResourceExhaustedError是因为您试图分配的内存超过GPU或主内存中的可用内存。内存分配大约等于您的网络占用空间(为此进行估算,请保存检查点并查看文件大小)加上批处理大小乘以数据集中单个元素的大小。

在没有有关您的设置的更多信息的情况下直接回答您的问题很困难,但是这个问题的一个要素引起了我的注意:您说过,当您“添加足够的数据”或“使用大量数据时,会出现错误足够的数据集。”真奇怪请注意,数据集的大小不包括在内存分配占用空间的计算中。因此,数据集的大小无关紧要。既然如此,这似乎意味着您正在以某种方式尝试将整个数据集加载到GPU内存或主内存中。如果这样做,那就是问题的根源。要修复它,请使用TensorFlow Dataset API。使用Dataset可以通过将数据隐藏在Iterator后面而仅在被调用时产生批处理的方式来避免这种有限的内存资源。另外,您可以使用较旧的feed_dictQueueRunner数据馈送结构,但我不建议这样做。您可以找到此here的一些示例。

如果您已经在使用Dataset API,则需要发布更多代码作为对问题的编辑,以便我们为您提供帮助。

答案 2 :(得分:-1)

没有任何设置可以神奇地使您的内存超过GPU的设置。在我看来,您的输入将足够大以适合GPU RAM(以及所有所需的状态和渐变)。 您应该使用SELECT table1.id, table1.value AS tab1_value, table2.value AS tab2_value, table3.value AS tab3_value FROM table1 LEFT OUTER JOIN table2 ON table1.id = table2.link AND table2.value IS NOT NULL -- not strictly necessary AND table2.active = 1 LEFT OUTER JOIN table3 ON table1.id = table3.link AND table3.value IS NOT NULL -- not strictly necessary AND table3.active = 1 WHERE table1.active = 1; 而不是为了获得更多的内存,只是为了了解每个输入长度需要多少内存。从较小的长度开始,以config.gpu_options.allow_growth = True开始计算,GPU占用了多少RAM,然后增加了长度。一次又一次地执行此操作,直到您了解GPU可以容纳的最大输入长度(批量大小)为止。