Keras图像分类:训练集准确率高但测试图像准确率低

我正在尝试对Caltech101数据集进行图像分类。我使用了Keras中的几个预训练模型,并对训练集进行了数据增强:

train_datagen = keras.preprocessing.image.ImageDataGenerator(                    rescale=1./255, rotation_range=15,                                   width_shift_range=0.1,                                   height_shift_range=0.1,                                   shear_range=0.01,                                   zoom_range=[0.9, 1.25],                                   horizontal_flip=False,                                   vertical_flip=False,                                   fill_mode='reflect',                                   data_format='channels_last',                                   brightness_range=[0.5, 1.5])    validation_datagen = keras.preprocessing.image.ImageDataGenerator(rescale=1./255)    train_generator = train_datagen.flow_from_directory(                    train1_dir,  # 训练图像的源目录                    target_size=(image_size, image_size),                    batch_size=batch_size)    validation_generator = validation_datagen.flow_from_directory(                    validation_dir, # 验证图像的源目录                    target_size=(image_size, image_size),                    batch_size=batch_size)

我还使用了提前停止(在100个周期后停止):

es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=100)    mc = ModelCheckpoint('best_model_%s_%s.h5' % (dataset_name, model_name), monitor='val_acc', mode='max', verbose=1, save_best_only=True)    callbacks = [es, mc]

首先,我训练了最后一个层:

base_model.trainable = False    model = tf.keras.Sequential([      base_model,      keras.layers.GlobalAveragePooling2D(),      keras.layers.Dense(num_classes, activation='softmax')    ])    model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=0.0001),                  loss='categorical_crossentropy',                  metrics=['accuracy'])    epochs = 10000    steps_per_epoch = train_generator.n // batch_size    validation_steps = validation_generator.n // batch_size    history = model.fit_generator(train_generator,                                  steps_per_epoch = steps_per_epoch,                                  epochs=epochs,                                  workers=4,                                  validation_data=validation_generator,                                  validation_steps=validation_steps,                                   callbacks=callbacks)

然后,我按照Keras教程训练了前面的层:

# 在顶层分类器训练后,我们微调网络的层base_model.trainable = True# 让我们看看基础模型中有多少层print("基础模型中的层数: ", len(base_model.layers))# 从这一层开始微调fine_tune_at = 1# 冻结`fine_tune_at`层之前的所有层for layer in base_model.layers[:fine_tune_at]:    layer.trainable =  Falsemodel.compile(optimizer = tf.keras.optimizers.RMSprop(lr=2e-5),              loss='categorical_crossentropy',              metrics=['accuracy'])epochs = 10000history_fine = model.fit_generator(train_generator,                                   steps_per_epoch = steps_per_epoch,                                   epochs=epochs,                                   workers=4,                                   validation_data=validation_generator,                                   validation_steps=validation_steps,                                    callbacks=callbacks                                   )

最后,在模型训练完成后,我在单独的测试集上手动测试它

label_list = train_generator.class_indices    numeric_to_class = {}    for key, val in label_list.items():        numeric_to_class[val] = key    total_num_images = 0    acc_num_images = 0    with open("%s_prediction_%s.txt" % (dataset_name, model_name), "wt") as fid:        fid.write("标签列表:\n")        for label in label_list:            fid.write("%s," % label)        fid.write("\n")        fid.write("真实类别,预测类别\n")        fid.write("--------------------------\n")        for label in label_list:            testing_dir = os.path.join(test_dir, label)            for img_file in os.listdir(testing_dir):                img = cv2.imread(os.path.join(testing_dir, img_file))                img_resized = cv2.resize(img, (image_size, image_size), interpolation = cv2.INTER_AREA)                                img1 = np.reshape(img_resized, (1, img_resized.shape[0], img_resized.shape[1], img_resized.shape[2]))                pred_class_num = model.predict_classes(img1)                pred_class_num = pred_class_num[0]                true_class_num = label_list[label]                                predicted_label = numeric_to_class[pred_class_num]                               fid.write("%s,%s\n" % (label, predicted_label))                if predicted_label == label:                    acc_num_images += 1                total_num_images += 1    acc = acc_num_images / (total_num_images * 1.0)

我不得不这样做,因为库不会输出F1分数。然而,我发现验证集的准确率(val_acc)上升得很高(约0.8),但在训练后的测试阶段,准确率却非常低(我想大约是0.1)。我不明白这是为什么。请帮助我,非常感谢。

更新15/10/2019:我尝试仅在网络顶部训练一个线性SVM,而不进行任何微调,使用VGG16(RMSProp优化器)在Caltech101上获得了70%的准确率。然而,我不确定这是不是最佳选择。

更新2:我使用了Daniel Moller建议的预处理部分,在我的自定义数据集上(约450张图片,283张“打开”类别,203张“关闭”类别),使用提前停止,耐心设置为100,仅训练最后一个层,得到以下准确率和损失:

model = tf.keras.Sequential([  base_model,  keras.layers.GlobalAveragePooling2D(),  keras.layers.Dense(num_classes, activation='softmax')])

准确率

损失

更新3:我还尝试使用VGG16的最后一个全连接层,并在每个全连接层后添加dropout层,dropout率(设置为0的比率)为60%,提前停止的耐心设置为10:

base_model = tf.keras.applications.VGG16(input_shape=IMG_SHAPE, \                                               include_top=True, \                                               weights='imagenet')base_model.layers[-3].Trainable = Truebase_model.layers[-2].Trainable = Truefc1 = base_model.layers[-3]fc2 = base_model.layers[-2]predictions = keras.layers.Dense(num_classes, activation='softmax')dropout1 = Dropout(0.6)dropout2 = Dropout(0.6)x = dropout1(fc1.output)x = fc2(x)x = dropout2(x)predictors = predictions(x)model = Model(inputs=base_model.input, outputs=predictors)

我得到了最高的验证准确率0.93750,测试准确率:0.966216。图表:输入图像描述准确率


回答:

Related Posts

在使用k近邻算法时,有没有办法获取被使用的“邻居”?

我想找到一种方法来确定在我的knn算法中实际使用了哪些…

Theano在Google Colab上无法启用GPU支持

我在尝试使用Theano库训练一个模型。由于我的电脑内…

准确性评分似乎有误

这里是代码: from sklearn.metrics…

Keras Functional API: “错误检查输入时:期望input_1具有4个维度,但得到形状为(X, Y)的数组”

我在尝试使用Keras的fit_generator来训…

如何使用sklearn.datasets.make_classification在指定范围内生成合成数据?

我想为分类问题创建合成数据。我使用了sklearn.d…

如何处理预测时不在训练集中的标签

已关闭。 此问题与编程或软件开发无关。目前不接受回答。…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注