Keras:训练损失减少(准确度增加),同时验证损失增加(准确度降低)

Jes*_*per 6 python classification deep-learning keras

我正在研究一个非常稀疏的数据集,其中包含预测6个类的要点.我尝试过使用很多模型和架构,但问题仍然存在.

当我开始训练时,训练的acc将慢慢开始增加,并且损失将减少,因为验证将完全相反.

真的试图处理过度拟合,我根本不能相信这就是这个问题.

我试过了什么

在VGG16上转学:

  • 排除顶层并添加256个单位和6个单位softmax输出层的密集层
  • 微调顶级CNN区块
  • 微调前3-4个CNN区块

为了处理过度拟合,我在Keras中使用了大量增强,在p = 0.5的256密集层之后使用了丢失.

使用VGG16-ish架构创建自己的CNN:

  • 尽可能包括批量标准化
  • 每个CNN +密集层上的L2正则化
  • 在每个CNN +密集+汇集层之后从0.5-0.8之间的任何地方辍学
  • Keras"飞行中"的大量数据增加

意识到我可能有太多的免费参数:

  • 减少网络只包含2个CNN块+密集+输出.
  • 以与上述相同的方式处理过度拟合.

毫无例外,所有培训课程都是这样的: 培训和验证损失+准确性

最后提到的架构如下所示:

    reg = 0.0001

    model = Sequential()

    model.add(Conv2D(8, (3, 3), input_shape=input_shape, padding='same',
            kernel_regularizer=regularizers.l2(reg)))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dropout(0.7))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))

    model.add(Conv2D(16, (3, 3), input_shape=input_shape, padding='same',
            kernel_regularizer=regularizers.l2(reg)))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dropout(0.7))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.5))

    model.add(Flatten())
    model.add(Dense(16, kernel_regularizer=regularizers.l2(reg)))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dropout(0.5))

    model.add(Dense(6))
    model.add(Activation('softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='SGD',metrics=['accuracy'])
Run Code Online (Sandbox Code Playgroud)

并且数据由Keras中的生成器增强,并加载了flow_from_directory:

    train_datagen = ImageDataGenerator(rotation_range=10,
                                width_shift_range=0.05,
                                height_shift_range=0.05,
                                shear_range=0.05,
                                zoom_range=0.05,
                                rescale=1/255.,
                                fill_mode='nearest',
                                channel_shift_range=0.2*255)
    train_generator = train_datagen.flow_from_directory(
                train_data_dir,
                target_size=(img_width, img_height),
                batch_size=batch_size,
                shuffle = True,
                class_mode='categorical')

    validation_datagen = ImageDataGenerator(rescale=1/255.)
    validation_generator = validation_datagen.flow_from_directory(
                                            validation_data_dir,
                                            target_size=(img_width, img_height),
                                            batch_size=1,
                                            shuffle = True,
                                            class_mode='categorical')
Run Code Online (Sandbox Code Playgroud)

Dar*_*nus 5

通过分析您的指标输出(来自您提供的链接) ,我能想到什么:

在此输入图像描述

在我看来,大约在第 30 纪元左右,您的模型开始过度拟合。因此,您可以尝试在该迭代中停止训练,或者只训练大约 30 个时期(或确切的数字)。Keras回调在这里可能很有用,特别是ModelCheckpoint可以让您在需要时 (Ctrl +C) 或满足某些条件时停止训练。这是基本使用的示例ModelCheckpoint

#save best True saves only if the metric improves
chk = ModelCheckpoint("myModel.h5", monitor='val_loss', save_best_only=False) 
callbacks_list = [chk]
#pass callback on fit
history = model.fit(X, Y, ... , callbacks=callbacks_list)
Run Code Online (Sandbox Code Playgroud)

(编辑:)正如评论中所建议的,您可以使用的另一个选项是使用EarlyStopping回调,您可以在其中指定可容忍的最小更改以及在停止训练之前没有此类改进的“耐心”或时期。如果使用它,您必须将其传递给callbacks前面解释的参数。

在当前设置下,您的模型(以及您尝试过的修改)在您的训练中的那个点似乎是您的案例的最佳训练时间;进一步训练它不会给你的模型带来任何好处(事实上,会让它的泛化能力更差)。

鉴于您已经尝试了多次修改,您可以做的一件事就是尝试增加网络深度,以赋予其更多容量。尝试添加更多层,一次一层,并检查是否有改进。此外,在尝试多层解决方案之前,您通常希望首先从更简单的模型开始。

如果简单的模型不起作用,请添加一层并再次测试,重复直到满意或可能为止。我所说的简单是指非常简单,您尝试过非卷积方法吗?尽管 CNN 非常适合图像,但也许您在这里有点过分了。

如果似乎没有任何效果,也许是时候获取更多数据,或者通过采样或其他技术从现有数据中生成更多数据。对于最后一个建议,请尝试查看我发现非常有用的这个keras 博客。深度学习算法通常需要大量的训练数据,特别是对于图像等复杂模型,因此请注意,这可能不是一件容易的任务。希望这可以帮助。