由于将numpy数组列表转换为单个数组,因此自定义图像数据生成器(keras)非常慢

时间:2020-03-09 14:26:40

标签: arrays performance numpy keras image-segmentation

我的神经模型训练遇到瓶颈。我编写了一个自定义生成器,该生成器可以动态加载图像和蒙版,以传递给我的模型进行训练。我发现即使当我使用GPU时,它也非常慢,并将其范围缩小到我将一批面具从数组列表转换为具有尺寸(批处理,高度,宽度,类)的数组时。这似乎要花很长时间,但是我不知道为什么?每个掩码是224x224x4(4个类是一个热编码的类),我只使用一批16个。对他们的操作非常快。任何想法将不胜感激?

import cv2
import os
import numpy as np
from tensorflow import keras
from skimage import img_as_bool
from skimage.transform import resize


class DataGenerator(keras.utils.Sequence):
    def __init__(self, imgIds, maskIds, imagePath, maskPath, weights=[1,1,1,1],
                        batchSize=16, shuffle=False):
        self.imgIds = imgIds
        self.maskIds = maskIds
        self.imagePath = imagePath
        self.maskPath = maskPath
        self.weights = np.array(weights)
        self.batchSize = batchSize
        self.shuffle = shuffle


    '''
    for each image id load the patch and corresponding mask
    '''
    def __load__(self, imgName, maskName):

        img = cv2.imread(os.path.join(self.imagePath,imgName))
        img = img/255.0

        mask = np.load(os.path.join(self.maskPath,maskName))
        mask = np.multiply(mask, self.weights)
        mask = tf.cast(mask, tf.float32)

        return (img, mask)


    '''
    get the files for each batch (override __getitem__ method)
    '''
    def __getitem__(self, index):

        if(index+1)*self.batchSize > len(self.imgIds):
            self.batchSize = len(self.imgIds) - index*self.batchSize

        batchImgs = self.imgIds[self.batchSize*index:self.batchSize*(index+1)]
        batchMasks = self.maskIds[self.batchSize*index:self.batchSize*(index+1)]
        batchfiles = [self.__load__(imgFile, maskFile) for imgFile, maskFile in zip(batchImgs, batchMasks)]
        images, masks = zip(*batchfiles)

        return np.array(list(images)), np.array(list(masks))


    '''
    Return number of steps per batch that are needed (override __len__ method)
    '''
    def __len__(self):
        return int(np.ceil(len(self.imgIds)/self.batchSize))

1 个答案:

答案 0 :(得分:1)

尝试在tensorflow(我正在使用tensorflow 2.1.0)中做尽可能多的事情:

def __load__(self, imgName, maskName):
  path = os.path.join(self.imagePath,imgName)
  img = tf.image.decode_jpeg(tf.io.read_file(path)))
  img = img/255.0
  mask = np.load(os.path.join(self.maskPath,maskName))
  mask = tf.cast(mask, tf.float32)
  mask = tf.multiply(mask, self.weights)

np.multiply绝对不是一个好主意,可以肯定的是用户tf.multiply。我担心np.load,它也可能很慢,因为您的数据根本没有被压缩(意味着更多的I / O)。

您可以使用np.load保存数据,并使用tf.data.TFRecord作为数据生成器来解决tf.data.Dataset问题。这是在tensorflow中加载数据的性能的最佳选择。