我的 CNN 产生 volatile validation_loss 并且在 python(Keras) 中不收敛

数据挖掘 Python 喀拉斯 美国有线电视新闻网
2021-09-15 07:02:38

我的模型正在经历验证损失的剧烈波动并且没有收敛。

我正在用我的三只狗做一个图像识别项目,即对图像中的狗进行分类。两只狗非常相似,而第三只非常不同。我分别为每只狗拍摄了 10 分钟的视频。每秒提取帧作为图像。

此代码块负责扩充和创建数据以提供模型。

randomize = np.arange(len(imArr)) # imArr is the numpy array of all the images
np.random.shuffle(randomize) # Shuffle the images and labels
imArr = imArr[randomize]
imLab= imLab[randomize] # imLab is the array of labels of the images
lab = to_categorical(imLab, 3)

gen = ImageDataGenerator(zoom_range = 0.2,horizontal_flip = True , vertical_flip = True,validation_split = 0.25)
train_gen = gen.flow(imArr,lab,batch_size = 64, subset = 'training')
test_gen = gen.flow(imArr,lab,batch_size =64,subset = 'validation')

这张图片是下面模型的结果。在此处输入图像描述

model = Sequential()

model.add(Conv2D(16, (11, 11),strides = 1, input_shape=(imgSize,imgSize,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3,3),strides = 2))
model.add(BatchNormalization(axis=-1))


model.add(Conv2D(32, (5, 5),strides = 1))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3,3),strides = 2))
model.add(BatchNormalization(axis=-1))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(3,3),strides = 2))
model.add(BatchNormalization(axis=-1))


model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(BatchNormalization(axis=-1))
model.add(Dropout(0.3))




#Fully connected layer
model.add(Dense(256))
model.add(Activation('relu'))
model.add(BatchNormalization())
model.add(Dropout(0.3))

model.add(Dense(3))

model.add(Activation('softmax'))

sgd = SGD(lr=0.004)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])

batch_size = 64
epochs = 100
model.fit_generator(train_gen, steps_per_epoch=(len(train_gen)), epochs=epochs, validation_data=test_gen, validation_steps=len(test_gen),shuffle = True)

我尝试过的事情。

  • 高/低学习率(0.01 -> 0.0001)
  • 在两个 Dense 层中将 Dropout 增加到 0.5
  • 增加/减少两个密集层的大小(128 min -> 4048 max)
  • 增加 CNN 层数
  • 引入动量
  • 增加/减少批次大小

我没有尝试过的事情

  • 我没有使用任何其他损失或指标
  • 我没有使用任何其他优化器。
  • 没有调整 CNN 层的任何参数

我的模型中似乎存在某种形式的随机性或过多的参数。我知道它目前过度拟合,但这不应该是波动的原因(?)。我不太担心模型的性能。我想达到大约 70% 的准确率。我现在要做的就是稳定验证准确性并收敛。

笔记:

  • 在某些时期,训练损失非常低(<0.1),但验证损失非常高(>3)。
  • 这些视频是在不同的背景上拍摄的,但是每只狗的每个背景上的数量相同。
  • 有些图像有点模糊。
1个回答

我的模型中似乎存在某种形式的随机性或过多的参数。我知道它目前过度拟合,但这不应该是波动的原因(?)

这种行为很可能是由模型的过度容量和您输入的数据共同引起的。

正如您所指出的,过度拟合在这里很明显 - 模型不能很好地泛化并且在看不见的数据上失败。如果您减少模型容量(更好的是,从最低限度开始并从那里逐步建立),那么网络将被迫学习而不是执行记忆。由于您提到您已经尝试过调整速率/层/大小,因此模型本身不能成为原因,尽管也许在卷积层方面具有更多专业知识的人可以提供有用的见解。

缺乏收敛可能表明根本没有足够的数据可供学习——当数据不足时,神经网络不能保证收敛。所需数量很大程度上取决于任务的具体情况。

我的数据集包含大约 1800 张图像...每只狗 600 张

这是一个相当小的数据集,考虑到:

两只狗非常相似,而第三只非常不同。

因此,大约三分之二的图像会引起混淆。它们看起来越相似,捕获细节所需的样本就越多。

这些视频是在不同的背景上拍摄的,但是每只狗的每个背景上的数量相同。

然后,该模型可能会错误地尝试仅根据背景来区分两只长相相似的狗(想想最坏的情况)。

在您的情况下,我会更仔细地查看数据,调查哪些图像始终是模型最容易/最难分类的图像,并充分利用ImageDataGenerator的图像增强来提高泛化能力。如果您将外观相似的狗放在相同的标签下,或者让其中一只只出现在训练中,另一只出现在验证中,看看模型如何响应。也许那里有一些答案。