1

我正在尝试训练一个非常简单的图像识别模型,没什么了不起的。当我使用图像重新缩放时,我的第一次尝试效果很好:

# this is the augmentation configuration to enhance the training dataset
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)

# validation generator, only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='categorical')

validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='categorical')

然后我简单地训练了模型:

model.fit_generator(
        train_generator,
        steps_per_epoch=nb_train_samples // batch_size,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=nb_validation_samples // batch_size)

这工作得非常好,并导致合理的准确性。然后我认为尝试平均减法可能是一个好主意,就像 VGG16 模型使用的那样。我没有手动进行,而是选择使用 ImageDataGenerator.fit()。但是,为此,您需要将训练图像作为 numpy 数组提供给它,所以我首先读取图像,转换它们,然后将它们输入其中:

train_datagen = ImageDataGenerator(
featurewise_center=True,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)

test_datagen = ImageDataGenerator(featurewise_center=True)

def process_images_from_directory(data_dir):
    x = []
    y = []
    for root, dirs, files in os.walk(data_dir, topdown=False):
        class_names = sorted(dirs)

        global class_indices
        if len(class_indices) == 0:
            class_indices = dict(zip(class_names, range(len(class_names))))

        for dir in class_names:
            filenames = os.listdir(os.path.join(root,dir))
            for file in filenames:
                img_array = img_to_array(load_img(os.path.join(root,dir,file), target_size=(224, 224)))[np.newaxis]
                if len(x) == 0:
                    x = img_array
                else:
                    x = np.concatenate((x,img_array))
                y.append(class_indices[dir])
    #this step converts an array of classes [0,1,2,3...] into sparse vectors [1,0,0,0], [0,1,0,0], etc.
    y = np.eye(len(class_names))[y]
    return x, y

x_train, y_train = process_images_from_directory(train_data_dir)
x_valid, y_valid = process_images_from_directory(validation_data_dir)

nb_train_samples = x_train.shape[0]
nb_validation_samples = x_valid.shape[0]
train_datagen.fit(x_train)
test_datagen.mean = train_datagen.mean

train_generator = train_datagen.flow(
        x_train,
        y_train,
        batch_size=batch_size,
        shuffle=False)

validation_generator = test_datagen.flow(
        x_valid,
        y_valid,
        batch_size=batch_size,
        shuffle=False)

然后,我以同样的方式训练模型,只是给它两个迭代器。训练完成后,即使经过 50 个 epoch,准确率也基本停留在 ~25%:

80/80 [==============================] - 77s 966ms/步 - 损失:12.0886 - acc: 0.2500 - val_loss :12.0886 - val_acc:0.2500

当我对上述模型进行预测时,它只正确分类了 4 个类别中的 1 个,其他 3 个类别的所有图像都被归类为第一类——显然 25% 的百分比与这个事实有关,我只是无法弄清楚我做错了什么。

我意识到我可以手动计算平均值,然后简单地为两个生成器设置它,或者我可以使用 ImageDataGenerator.fit() 然后仍然使用 flow_from_directory,但这会浪费已经处理的图像,我会这样做相同处理两次。

关于如何让它一直与 flow() 一起工作的任何意见?

4

1 回答 1

-1

您是否尝试在生成器中设置 shuffle=True ?

您没有在第一种情况下指定改组(默认情况下应该是 True)并在第二种情况下将其设置为 False。

您的输入数据可能按类排序。如果不进行改组,您的模型首先只会看到第 1 类,然后总是学会预测第 1 类。然后它会看到 #2 类并学会始终预测 #2 类,依此类推。在一个 epoch 结束时,您的模型学会始终预测第 4 类,因此验证的准确率为 25%。

于 2018-08-21T14:14:29.937 回答