Keras Resnet-50 图像分类过拟合

Posted

技术标签:

【中文标题】Keras Resnet-50 图像分类过拟合【英文标题】:Keras Resnet-50 image classification overfitting 【发布时间】:2022-01-10 09:16:56 【问题描述】:

您好,我的 resnet-50 预训练权重过拟合了。我正在尝试训练文件的 RGB 图像,而我使用的数据集带有训练和验证集。我有 26 个类和大约 14k 图像,9k 训练和 5k 测试。

数据集名称为maleviz

我的验证准确率非常低,我的训练准确率达到 1.000。我的验证没有超过 0.50-0.55,所以我认为似乎过拟合了.. 像每个类样本这样的数据有问题还是我的模型有问题?

我希望 resnet 在这方面表现良好...

这是我的代码:

import tensorflow as tf
import keras
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
import keras
from keras.models import Sequential, Model, load_model
from tensorflow.keras.optimizers import Adam
from keras.callbacks import EarlyStopping,ModelCheckpoint
from keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization,Flatten, Conv2D, AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D,MaxPool2D
from keras.preprocessing import image
from keras.initializers import glorot_uniform
from keras.applications.resnet import ResNet50
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

samples = ImageDataGenerator().flow_from_directory(directory='malevis_train_val_300x300/train', target_size=(300,300))
imgs, labels = next(samples)
print(imgs.shape, labels.shape)
samples2 = ImageDataGenerator().flow_from_directory(directory='malevis_train_val_300x300/val', target_size=(300,300))
imgs2, labels2 = next(samples2)

classes = samples.class_indices.keys()
y = (sum(labels)/labels.shape[0])*100
plt.xticks(rotation='vertical')
plt.bar(classes,y)
plt.show()

X_train, y_train = imgs,labels
X_val, y_val = imgs2,labels2
def define_model():
    model = ResNet50(weights = 'imagenet', pooling = 'avg', include_top = False, input_shape =(300,300,3))
    for layer in model.layers:
        layer.trainable = False
    flat1 = Flatten()(model.layers[-1].output)
    class1 = Dense(256,activation='relu',)(flat1)
    output = Dense(26,activation='softmax')(class1)
    model = Model(inputs = model.inputs, outputs=output)
    opt = Adam(lr =0.001)
    model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
    return model

model = define_model()
model.summary()

history1 = model.fit(X_train,y_train, validation_data=(X_val,y_val), epochs = 200,batch_size = 20, steps_per_epoch = 4,shuffle=True)
scores = model.evaluate(X_val,y_val)
print('Final accuracy:', scores[1])

acc = history1.history['accuracy']
val_acc = history1.history['val_accuracy']
loss = history1.history['loss']
val_loss = history1.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'r', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.legend(loc=0)
plt.figure()


plt.show()

我尝试了不同的优化器、损失函数、目标大小和每步添加的 epochs。没有什么真正能带来太大的不同,它仍然过拟合。我正在使用 softmax 激活并冻结图层并移除顶部。我刚刚为 26 个类添加了密集层和输出层。我尝试过改组真假

【问题讨论】:

能否提供损失曲线?它可能有助于解决问题。帮助过拟合的一般规则是在网络的某处添加一个 Dropout 层。 @Michael 感谢 dropout 层的建议。我会尽快提供损失曲线。 我建议不要冻结预训练 ResNet 的所有层。这将最小化 NN 的学习能力,因为大多数可训练变量都是冻结的,即恒定的。您可以解冻一些初始卷积层,因为这将帮助它们捕获可能特定于您的数据集的局部特征。 【参考方案1】:

我想向您推荐几件事,其中一件可能会有所帮助:

    您没有在flow_from_directory() 中提供任何classes 参数,请确保您具有文档要求的正确文件夹结构:flow_from_directory 如果您的输出标签不是 one-hot 编码,请尝试将损失从categorical_crossentropy 更改为sparse_categorical_crossentropy。参考:Probabilistic losses | SparseCategoricalCrossentropy

【讨论】:

以上是关于Keras Resnet-50 图像分类过拟合的主要内容,如果未能解决你的问题,请参考以下文章

图像分类用最简短的代码复现SeNet,小白一定要收藏(keras,Tensorflow2.x)

使用 keras ResNet50 模型进行二进制分类的输出层

Keras:过拟合模型?

Keras深度学习实战——基于ResNet模型实现性别分类

深度学习之图像分类ResNet50学习

图像分类案例 ResNet50 鸟类图像4分类,附Pytorch完整代码