Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 由于将numpy数组列表转换为单个数组,自定义图像数据生成器(keras)速度非常慢_Arrays_Performance_Numpy_Keras_Image Segmentation - Fatal编程技术网

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

Arrays 由于将numpy数组列表转换为单个数组,自定义图像数据生成器(keras)速度非常慢,arrays,performance,numpy,keras,image-segmentation,Arrays,Performance,Numpy,Keras,Image Segmentation,我的神经模型训练遇到了瓶颈。我已经编写了一个自定义生成器,可以动态加载图像和遮罩,以传递给我的模型进行训练。我发现,即使在我使用gpu时,速度也非常慢,并缩小到我将一批掩码从数组列表转换为一个具有维度(批次、高度、宽度、类别)的数组时。这似乎需要很长时间,但我不知道为什么?每个掩码是224x224x4(4个类作为一个热编码),我只使用了16个类。如果我生成一组(224x224x4)随机数组的列表,并对其应用np.array(array)操作,速度会非常快。有什么好主意吗 import cv2 i

我的神经模型训练遇到了瓶颈。我已经编写了一个自定义生成器,可以动态加载图像和遮罩,以传递给我的模型进行训练。我发现,即使在我使用gpu时,速度也非常慢,并缩小到我将一批掩码从数组列表转换为一个具有维度(批次、高度、宽度、类别)的数组时。这似乎需要很长时间,但我不知道为什么?每个掩码是224x224x4(4个类作为一个热编码),我只使用了16个类。如果我生成一组(224x224x4)随机数组的列表,并对其应用np.array(array)操作,速度会非常快。有什么好主意吗

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))

尝试在
tensorflow
中尽可能多地执行操作(我正在使用
tensorflow 2.1.0
):

np.multiply
绝对是个坏主意,当然用户
tf.multiply
。我担心
np.load
,而且它可能会很慢,因为您的数据根本没有被压缩(意味着更多的I/O)


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

我肯定会做出这些改变,然而,我的瓶颈似乎是在np.array(list(masks))上,但我不知道为什么。我本以为在64(224224,4)个数组上调用数组操作在计算上不会那么昂贵
zip
是一个生成器,所以当您调用
list(mask)s
时,您的列表才会具体化。尝试用
列表
调用来包围每个
邮政编码
,然后再次计时,这会让您更好地了解实际的瓶颈所在。在tf.data.TFRecord上,您有什么好的资源吗?我已经找到了一些很好的解释,但我想知道如何与keras generatorhmm集成——这更像是一种“或”的情况(如使用
tf.data.Dataset
或keras生成器)。它本身就是一个数据生成器(它惰性地加载数据)。我不认为有任何理由将其封装到keras数据生成器中,但我认为这非常简单。我将发布一些伪代码作为答案,这样它的格式会更好。如果您要使用
tf.data.Dataset
就没有理由再使用
keras生成器了。把它包在里面并不是很有用,但是可能
\uuuuu init\uuuuuuuuu
创建
tf.data.Dataset
\uuuuuu load\uuuuuuuuu
为空,
\uuuuuu len\uuuuuuuuuuuuuuuu
只需在整个数据集上循环对其进行计数(
count=sum([1代表self.tf\uu数据集中的i)
),而
\uuu获取项目
只返回

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)