我正在为一个项目进行犬种分类,但是遇到一个主要问题,我不知道如何解决。
数据集是Stanford Dogs dataset提供的狗的图像。
我使用keras进行数据增强:
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras import optimizers
from keras.callbacks import History
from keras.applications import vgg16
batch_size = 16
# this is the augmentation configuration I will use for training
train_datagen = ImageDataGenerator(rotation_range=20,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest',
preprocessing_function=vgg16.preprocess_input)
# This is the augmentation configuration I will use for testing/validation... just a rescale
test_datagen = ImageDataGenerator(rescale=1./255)
# This is the generator which will read pictures found in my training subset
train_generator = train_datagen.flow_from_directory('../data/train/',
target_size = (224, 224),
batch_size = batch_size,
shuffle=True,
class_mode = 'categorical',
seed=42)
# This is the generator for validation data
validation_generator = test_datagen.flow_from_directory('../data/validation/',
target_size = (224, 224),
batch_size = batch_size,
class_mode = 'categorical')
然后我将转移学习与VGG16一起使用来训练我的模型:
from keras.applications.vgg16 import VGG16
from keras.layers import Input, Dense, Flatten, GlobalAveragePooling2D
from keras.models import Model, Sequential
pretrained_model = VGG16(weights="imagenet", include_top=False, input_shape=(224, 224, 3))
for layer in pretrained_model.layers:
layer.trainable = False
x = pretrained_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation="relu")(x)
predictions = Dense(120, activation='softmax')(x)
model = Model(inputs = pretrained_model.input, outputs=predictions)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
当我训练模型时,似乎过拟合了: 我在火车上的准确性为0.99,而在验证中为0.23。
当查看火车和验证集中的图像时,没有明显的原因使验证的准确性下降。
我所做的是手动检查模型在验证和测试中对几幅图像(超过50张)预测的品种,并且80%以上是正确的预测。
所以我认为验证准确性存在问题,但不知道如何解决。
感谢您的帮助!
答案 0 :(得分:0)
几乎没有什么可以提高训练和验证数据集分类的准确性:
首先,设置layer.trainable = True,因为Imagenet数据集是在不同的数据集上训练的。仅对顶层进行微调将直接导致过度拟合。加载imagenet权重,但重新训练所有或几层。
使用带有Nosy_student权重的EfficientNet。需要训练的参数数量较少。由于它具有可扩展的体系结构,因此可以提供更好的准确性。将整个数据集转换为numpy数组。我猜np数组将加载得更快。使用sklearn train_test_split函数拆分训练数据。标准化数据集(1/255)。在火车数据上沿轴0计算np.mean,并从火车和val数据集中减去np.mean。
您可以使用测试时间增加。在测试数据生成器中,执行简单的水平翻转,垂直翻转(如果数据看起来逼真)和仿射变换。它将生成数据的多个视图,并帮助模型对更可能的类进行平均。
检出图像库(压纹,锐化,添加噪点等)。另外,还提供了random_eraser,剪切和混合策略,这些方法已被证明是有用的。将此添加到预处理功能中,而不是放置preprocess_input。这也将有助于规范化模型。
尝试平滑标签。它还可以帮助您的分类器将更多概率分配给正确的分类。
尝试学习率预热。像这样的东西:
LR_START = 0.0001
LR_MAX = 0.00005
LR_MIN = 0.0001
LR_RAMPUP_EPOCHS = 4
LR_SUSTAIN_EPOCHS = 6
LR_EXP_DECAY = .8
def lrfn(epoch):
if epoch < LR_RAMPUP_EPOCHS:
lr = (LR_MAX - LR_START) / LR_RAMPUP_EPOCHS * epoch + LR_START
elif epoch < LR_RAMPUP_EPOCHS + LR_SUSTAIN_EPOCHS:
lr = LR_MAX
else:
lr = (LR_MAX - LR_MIN) * LR_EXP_DECAY**(epoch - LR_RAMPUP_EPOCHS - LR_SUSTAIN_EPOCHS) + LR_MIN
return lr
您还可以提取特征并应用整体特征分类(XGBoost,Adaboost,BaggingClassifier)或三元组损失。
尝试将图像分辨率提高到299。分辨率越高,细分类效果越好。