【问题标题】:How to speed up my Keras CNN with pre-trained InceptionV3如何使用预训练的 InceptionV3 加速我的 Keras CNN
【发布时间】:2019-03-20 11:55:28
【问题描述】:

我想训练一个卷积神经网络来识别两种类型的类。
我还想使用已经训练好的模型(如 InceptionV3)的第一个卷积层。
然而,训练过程真的很慢。你有什么建议我可以改进吗?我不会提到我的 CPU、RAM,我在这里只关心瓶颈在哪里以及我可以改进什么来加快速度(我的图像已经是 229x299x3)。

from keras.applications import InceptionV3
from keras import layers
from keras.models import Model
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
import os


def generator(images_dir):
    datagen = ImageDataGenerator(rescale=1. / 255)
    gen = datagen.flow_from_directory(
        images_dir,
        target_size=(segment_size, segment_size),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=True)
    return gen


def num_files_in_folder(folder):
    count = 0
    for subdir, dirs, files in os.walk(folder):
        for file in files:
            if not file.startswith("."):
                count += 1
    return count


segment_size = 229
batch_size = 32
base_model = InceptionV3(weights='imagenet',
                         include_top=False,
                         input_shape=(segment_size, segment_size, 3))
x = base_model.output
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(1024, activation='relu')(x)
predictions = layers.Dense(2, activation='softmax')(x)

model = Model(inputs=base_model.input, outputs=predictions)

for layer in base_model.layers:
    layer.trainable = False

model.compile(optimizer=optimizers.SGD(lr=0.01, nesterov=True),
              loss='categorical_crossentropy',
              metrics=['acc'])

train_dir = "/home/user/train"
validation_dir = "/home/user/val"
train_gen = generator(train_dir)
val_gen = generator(validation_dir)
steps_per_epoch = int(np.ceil(num_files_in_folder(train_dir) / batch_size))
validation_steps = int(np.ceil(num_files_in_folder(validation_dir) / batch_size))

history = model.fit_generator(
    generator=train_gen,
    steps_per_epoch=steps_per_epoch,
    epochs=10,
    validation_data=val_gen,
    validation_steps=validation_steps,
    use_multiprocessing=False,
    verbose=1)

【问题讨论】:

  • 定义“真的很慢”。你用的是CPU还是GPU?如果是后者,利用率是多少?
  • 嗨鲨鱼。我将它与我拥有的另一个实现进行了比较。在那里,我通过incepv3.predict(generator) 从预训练模型中提取特征,然后将它们保存到 pickle 文件中。在这一切完成之后,我运行另一个 Python 脚本,该脚本通过另一个生成器读取泡菜文件并将内容传递给我的最终模型。这个 impl 需要大约 25 分钟的特征提取和 2 分钟的训练。我在此处粘贴的代码使用相同的 CPU 处理相同的图像、相同的 epoch 数等超过 2 小时。
  • 正如答案所暗示的,您应该使用数据集 api。我不会直接从 tfrecords 格式开始,因为它并不总是有优势,而且它本身需要时间来转换。您可以选择使用没有 pickle 的普通 numpy 数组吗?为什么要使用它?
  • 我的数据不适合内存。我找不到从文件系统中读取所有 SxSx3 图像的方法,将它们提供给 inceptV3.predict 并将结果传递给我的 model.fit_generator,需要将所有内容加载到内存中。
  • 您的初始数据是什么样的?它是一个大的 numpy 数组吗?还是图片目录?

标签: python tensorflow keras conv-neural-network


【解决方案1】:

首先,我建议您将数据转换为 TFRecords 并避免使用flow_from_directoryImageDataGenerator 可能是快速原型设计的一个不错的选择,但 TFRecords 和相应的 TF 基础设施(队列/运行器/阅读器)确实针对快速阅读进行了优化。通过使用tf.data API,尤其是Dataset.prefetch(),您可以获得显着的加速。

在大多数情况下,数据读取是瓶颈,我可以在这里停下来。但在那之后我也会尝试:

【讨论】:

    【解决方案2】:

    我会用tf.data.Dataset.from_tensor_slices 试试这个 假设您有通往训练集train_path 的路径。首先,您从中创建数据集对象。您也可以不传递路径,而是传递路径 from_tensor_slices((image_path, labels_path)) 或文件名/标签列表。以后可以用parse函数处理。

    dataset = tf.data.Dataset.from_tensor_slices(image_path)
    

    然后,您可以将任何解析函数混洗、批处理和映射到此数据集。您可以控制使用随机缓冲区预加载的示例数量。重复控制 epoch 计数,最好保留 None,因此它将无限重复。您可以使用普通批处理功能或与

    结合使用
    dataset = dataset.shuffle().repeat()
    dataset.apply(tf.data.experimental.map_and_batch(map_func=parse_func, batch_size,num_parallel_batches))
    

    你需要定义解析函数来从文件名加载实际数据

    def parse_func(filename):
        f = tf.read_file(filename)
        img = tf.image.decode_image(f)
        label = #get label from filename
        return img, l
    

    将此应用于数据集对象后,它将包含成对的图像/标签。

    请记住,批处理在此管道中进行,因此您不需要在 model.fit 中使用批处理,但您需要传递每个 epoch 的数量和步骤。后者可能有点棘手,因为你不能像 len(dataset) 那样做事,所以应该提前计算。

    model.fit(dataset, epochs, steps_per_epoch)
    

    您可以对测试数据集执行相同的操作。您也可以使用

    检查它的内容
    iterator = dataset.make_one_shot_iterator()
    with tf.Session() as sess:
        print(sess.run(iterator.get_next()))
    

    这将输出 num_batches。

    【讨论】:

    • 感谢 Sharky 的回答。我使用 TF 数据 API 实现了我的算法,但它非常慢(5 多个小时)。我将它与我的另一个实现进行了比较:我没有将预训练的 inceptionv3 模型添加到我的模型中,而是首先使用我的所有图像调用 inceptionv3.predict()(大约需要 26 分钟)。然后将来自预测的特征向量传递给我的新 model.fit(这个模型只有 3 层),这大约需要一分钟)。总共 27 分钟
    猜你喜欢
    • 1970-01-01
    • 2017-07-07
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多