Keras fit_generator即使批量小也使用大量内存

时间:2018-03-08 09:40:04

标签: tensorflow machine-learning keras

之前我在for循环中使用model.fit()手动训练我的模型,以便根据内存限制在小批量数据上训练它。这样做的问题在于,我无法通过历史记录访​​问所有以前的历史记录。因为它类似于每次训练新模型时,以前的历史都没有存储在任何地方。 / p>

当我在500批量大小上使用model.fit()时,我的ram大约7 GB就会满了。我使用keras和tensorflow-cpu后端。 但是当我使用发生器时,即使批量大小为50韩元也不适合内存,并且可以换成磁盘。

我正在使用224 * 224图像进行分类,我正在尝试微调vgg face。我正在使用根据此链接实现的vgg face: VGG-Face

我正在使用ResNet和SeNet架构,如链接中所述。

我以前洗过我的数据。我已将%20的数据放在一边进行测试。 我的数据,图像地址和标签存储在列表中。我的训练数据的%20将用于验证。例如,如果批量大小等于50,则train_data_generator将从训练数据的第一个%80部分创建大小为40的批次,并且vl_data_generator将从训练数据的最后%20部分创建大小为10的批次。我已经编写了一个类,并通过创建实例和调用train方法  通过它,我进行训练。以下是我的代码的生成器和培训部分,不包括模型定义:

def prepare_input_data(self, batch_addresses):
    image = []
    for j in range(len(batch_addresses)):
        img = cv2.imread(batch_addresses[j])
        img = cv2.resize(img, (224, 224))
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        img = img - np.array([103.939, 116.779, 123.68])

        image.append(img)

    data = np.array(image)
    data = data.astype('float32')
    data /= 255

    return data


def train_data_generator(self, addresses, labels, batch_size):
    """Train data generator"""
    #Use first %80 of data for training.
    addresses = addresses[: int(0.8 * len(addresses))]
    labels = labels[: int(0.8 * len(labels))]
    total_data = len(addresses)
    while 1:
        for i in range(total_data / batch_size):
            batch_addresses = addresses[i * batch_size: (i + 1) * batch_size]
            batch_labels = labels[i * batch_size: (i + 1) * batch_size]

            data = self.prepare_input_data(batch_addresses)

            batch_labels = np_utils.to_categorical(batch_labels, self.nb_class)

            yield data, batch_labels

def val_data_generator(self, addresses, labels, batch_size):
    """Validation data generator"""
    #Use the last %20 of data for validation
    addresses = addresses[int(0.8 * len(addresses)):]
    labels = labels[int(0.8 * len(labels)):]
    total_data = len(addresses)
    image = []
    while 1:
        for i in range(total_data / batch_size):
            batch_addresses = addresses[i * batch_size: (i + 1) * batch_size]
            batch_labels = labels[i * batch_size: (i + 1) * batch_size]

            data = self.prepare_input_data(batch_addresses)

            batch_labels = np_utils.to_categorical(batch_labels, self.nb_class)

            yield data, batch_labels

def train(self, label_interested_in):
    """Trains the model"""
    #Read training data from json file, and get addresses and labels
    addresses, labels = self.create_address_and_label(label_interested_in)
    batch_size = 50
    train_batch_size = 40
    val_batch_size = 10
    steps = int(len(addresses) / batch_size) + 1
    print(len(addresses), steps)
    #Perform training
    history = self.custom_vgg_model.fit_generator(
        self.train_data_generator(addresses, labels, train_batch_size),
        steps_per_epoch=steps, epochs=self.number_of_epochs,
        verbose=1, validation_data=self.val_data_generator(addresses, labels, val_batch_size),
        validation_steps=steps, initial_epoch=0)

为什么我看到如此高的内存使用率?是因为发电机在keras工作的方式吗?我读到发电机事先准备好批次,通过与培训并行运行来加速培训过程。或者我做错了什么?

作为一个附带问题,由于fit_generator()中没有't batch_size参数,我是否正确假设数据基于生成器加载到模型中,并且在每次训练和验证批处理加载后执行渐变更新?

1 个答案:

答案 0 :(得分:0)

尝试workers=0

这将不会调用任何旨在使用k个工作器来预先填充队列直到max_queue_size参数的多重处理。 这是什么?在GPU上进行训练的同时,在CPU上准备生成的数据队列,这样就不会浪费时间并避免了瓶颈。

为您的需要,工人= 0将起作用

有关更深入的查询,请参阅 keras fit_generator