与 Keras 的内置生成器相比,自定义 Keras 生成器要慢得多

Posted

技术标签:

【中文标题】与 Keras 的内置生成器相比,自定义 Keras 生成器要慢得多【英文标题】:Custom Keras generator much slower compared to Keras' bult in generator 【发布时间】:2019-03-17 19:30:01 【问题描述】:

我有一个多标签分类问题。我写了这个自定义生成器。它从磁盘读取图像和输出标签,并以 32 大小的批次返回它们。

def get_input(img_name):
    path = os.path.join("images", img_name)
    img = image.load_img(path, target_size=(224, 224))

    return img


def get_output(img_name, file_path):
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)

    img_id = img_name.split(".")[0]
    img_id = img_id.lstrip("0")
    img_id = int(img_id)

    labels = data.loc[img_id - 1].values
    labels = labels[1:]

    labels = list(labels)
    label_arrays = []
    for i in range(20):
        val = np.zeros((1))
        val[0] = labels[i]
        label_arrays.append(val)

    return label_arrays


def preprocess_input(img_name):
    img = get_input(img_name)
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)    
    return x

def train_generator(batch_size):
    file_path = "train.txt"
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)

    while True:
        for i in range(math.floor(8000/batch_size)):
            x_batch = np.zeros(shape=(32, 224, 224, 3))
            y_batch = np.zeros(shape=(32, 20))
            for j in range(batch_size):
                img_name = data.loc[i * batch_size + j].values
                img_name = img_name[0]
                x = preprocess_input(img_name)
                y = get_output(img_name, file_path)
                x_batch[j, :, :, :] = x
                y_batch[j] = y

            ys = []
            for i in range(20):
              ys.append(y_batch[:,i])

            yield(x_batch, ys)

返回模型的标签有一点问题,在这个问题中得到了解决: training a multi-output keras model

我在单个输出问题上测试了这个生成器。这个自定义生成器非常慢。使用此自定义生成器的单个 epoch 的 ETA 约为 27 小时,而内置生成器(使用 flow_from_directory)单个 epoch 需要 25 分钟。我究竟做错了什么?

这两个测试的训练过程是相同的,除了使用的生成器。验证生成器类似于训练生成器。我知道我不会达到 Keras 内置生成器的效率,但是这种速度差异太大了。

编辑

我阅读了一些关于创建自定义生成器的指南。

Writing Custom Keras Generators

custom generator for fit_generator() that yields multiple inputs with different shapes

【问题讨论】:

这是什么“当真:” 我搜索过编写自定义 Keras 生成器,大多数都使用了类似的方法。我认为 python 迭代器应该无限期地运行。在我的问题底部添加了一些链接。 只是为了确保生成器是问题所在,检查一个是否以tensorflow-gpu 运行,而另一个仅以tensorflow 运行(这是CPU 版本)。您可以查看输出的第一行来验证这一点,当使用 GPU 版本时,它会打印选择了哪个显卡。 @H.Tacon 运行这两个测试时,输出显示我的 GPU 和设备上剩余的内存量。 【参考方案1】:

也许内置的生成器在你的 gpu 上处理数据,而你的自定义生成器在 cpu 上运行,导致速度明显变慢。

另一个猜测是因为 Keras 在后台使用了Dataset。您的实现可能使用feed-dict,这是将信息传递给 TensorFlow 的最慢方式。将数据输入模型的最佳方式是使用输入管道,以确保 GPU 永远不必等待新的东西进来。

【讨论】:

以上是关于与 Keras 的内置生成器相比,自定义 Keras 生成器要慢得多的主要内容,如果未能解决你的问题,请参考以下文章

将自定义输出层添加到 R 中的内置(功能)keras 模型

tf2.0 Keras:使用 RNN 的自定义张量流代码时无法保存权重

kera 学习-线性回归

机器学习:我选kera

如何将内置 tensorflow 的 logits 自定义损失函数转换为 keras?

用于不适合内存的大型 hdf5 文件的 Keras 自定义数据生成器