keras 使用图像数据生成器训练多输入CNN

cfh9epnr  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(167)

我得到了一个图像数据集,其组织方式如下:
-dir_path文件夹:
---train-testa子文件夹:
------train(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
-------瓦尔(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
---train-testb子文件夹:
------train(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
-------瓦尔(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
---train-testc子文件夹:
------train(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
-------瓦尔(包含6个子文件夹(类别1到6),每个子文件夹包含图像样本)
我想训练一个CNN,一次用3张图像作为输入。比如说
\dir_path\train-testa\train\class3\sample05.png,
\dir_path\train-testb\train\class3\sample05.png,
\dir_path\train-testc\train\class3\sample05.png
将是CNN的级联输入进行训练。验证输入将是相同的,但是样本仅从val子文件夹中提取。
我使用ImageDataGenerators如下:

image_generator = ImageDataGenerator(rescale = 1/255)

def generate_generator_multiple(generator,dir1, dir2, dir3, batch_size, img_height,img_width):
    genX1 = generator.flow_from_directory(dir1,
                                          target_size = (img_height,img_width),
                                          class_mode = 'categorical',
                                          batch_size = batch_size,
                                          shuffle=False, 
                                          seed=7)

    genX2 = generator.flow_from_directory(dir2,
                                          target_size = (img_height,img_width),
                                          class_mode = 'categorical',
                                          batch_size = batch_size,
                                          shuffle=False, 
                                          seed=7)
    genX3 = generator.flow_from_directory(dir2,
                                          target_size = (img_height,img_width),
                                          class_mode = 'categorical',
                                          batch_size = batch_size,
                                          shuffle=False, 
                                          seed=7)
    while True:
            X1i = genX1.next()
            X2i = genX2.next()
            X3i = genX3.next()
            yield [X1i[0], X2i[0], X3i[0]], X2i[1]  #Yield images and their mutual label

train_generator=generate_generator_multiple(generator=image_generator,
                                           dir1=dir_path + "\\train-testa" + "\\train",
                                           dir2=dir_path + "\\train-testb" + "\\train",
                                           dir3=dir_path + "\\train-testc" + "\\train",
                                           batch_size=30,
                                           img_height=217,
                                           img_width=217)
test_generator=generate_generator_multiple(generator=image_generator,
                                           dir1=dir_path + "\\train-testa" + "\\val",
                                           dir2=dir_path + "\\train-testb" + "\\val",
                                           dir3=dir_path + "\\train-testc" + "\\val",
                                           batch_size=30,
                                           img_height=217,
                                           img_width=217)

在上面的函数中,我合并了train-testa、b和c的生成器。我使用了下面的CNN模型:

def CNNModel(input_shape): 
    
    X_input1 = Input(input_shape)
    X_input2 = Input(input_shape)
    X_input3 = Input(input_shape)

    X = layers.concatenate([X_input1, X_input2, X_input3])
    
    X = Conv2D(16, (3, 3), strides = (1, 1), name = 'conv1')(X)
    X = Activation('LeakyReLU')(X)
    X = Dropout(.25)(X)
    X = MaxPooling2D((2, 2), name='max_pool1')(X) 
    
    X = Conv2D(32, (3, 3), strides = (1, 1), name = 'conv2')(X)
    X = Activation('LeakyReLU')(X)
    X = Dropout(.3)(X)
    X = MaxPooling2D((2, 2), name='max_pool2')(X) 
    
    X = Conv2D(64, (3, 3), strides = (1, 1), name = 'conv3')(X)
    X = Activation('LeakyReLU')(X)
    X = Dropout(.3)(X)
    
    X = Flatten()(X)
    
    X = Dense(64, activation='LeakyReLU', name='fc1')(X)
    X = Dropout(.4)(X)
    
    X = Dense(6, activation='softmax', name='fc2')(X)
    
    return model

最后,我用以下代码训练了模型:

CNN_Model = CNNModel((217, 217, 3));

CNN_Model.compile(optimizer = "adam",loss = "categorical_crossentropy",metrics = ["accuracy"])

callback = tf.keras.callbacks.EarlyStopping(monitor='val_accuracy', patience=50, verbose=1, restore_best_weights=True)

his = CNN_Model.fit(train_generator, epochs=200, validation_data=test_generator, callbacks=[callback], use_multiprocessing=False)

现在我有一些问题:
1-我的代码的逻辑(概念)是否正确?
2-训练过程太慢。我的总图像训练是630个文件,它已经接近3个小时,我还没有能够看到最终的结果。epoch的数量可能太大了,但我已经为单个输入图像运行了相同的代码,只花了几分钟。这是我在跑步时得到的:
“device:GPU:0,1654 MB内存:- 〉device:0,name:NVIDIA GeForce RTX 3050笔记本电脑GPU,pci总线ID:0000:01:00.0,计算能力:8.6历元1/200 21527/未知-10706 s 497 ms/步长-丢失:0.3556 -准确度:0.9668英寸
它的训练准确率虽然很慢,但仍在提高。很有可能是装得太多了。正如您所看到的,我既看不到还剩多少步骤,也看不到验证的准确性。
既然我需要训练更大的数据集,有没有办法提高速度?
如果你能和我分享你的建议,我将不胜感激。问候

9gm1akwq

9gm1akwq1#

不要使用ImageDataGenerator,它非常慢,而且已经过时了。使用image_dataset_from_directory代替。以下是更多信息:https://www.tensorflow.org/api_docs/python/tf/keras/utils/image_dataset_from_directory
在这种情况下,您可以使用3次image_dataset_from_directory来创建3个数据集,然后可以使用类似tf.data.Dataset.zip((a, b, c))的方法将它们连接成一个数据集。您可能需要Map,您可以使用dataset.map(...)来完成。
您还可以应用预取,并将其缓存以加快速度。这里是信息:https://www.tensorflow.org/guide/data_performance

相关问题