Keras:过拟合模型?

Posted

技术标签:

【中文标题】Keras:过拟合模型?【英文标题】:Keras: Overfitting Model? 【发布时间】:2020-05-12 20:22:00 【问题描述】:

我正在尝试使用来自 NIH(国家医学图书馆)的疟疾数据集创建一个二进制图像分类模型,该数据集包含每个类别(感染/未感染)的大约 27,000 张图像。

似乎存在过度拟合,我尝试使用不同的批量大小、每个时期/验证步骤的步数、使用不同的隐藏层和添加回调等。图表总是显示一条直线,该直线要么急剧增加,要么急剧减少,而不是随着它的学习而稳步增加(根据我的理解,它应该是这样的)。下面是一个示例,大多数结果与此类似。

我是深度学习的新手,我已经阅读了很多关于过度拟合并试图找到解决方案的内容。但我认为一定有什么我做错了和/或误解了。如果有人能够发现看起来不正确的东西并能够为我指出正确的方向,我们将不胜感激!

from keras.layers import MaxPooling2D, Conv2D, Flatten, Dense, Dropout
from keras_preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
from keras.models import Sequential
import matplotlib.pyplot as plt
import constants as c
import numpy as np
import keras

# Clear session and instantiate model
keras.backend.clear_session()
model = Sequential()

# Load images & labels
cells = np.load(c.cells_path)
labels = np.load(c.labels_path)

# Shuffle the entire dataset
n = np.arange(cells.shape[0])
np.random.shuffle(n)

# Update numpy files with shuffled data
cells = cells[n]
labels = labels[n]

# Split the dataset into train/validation/test
train_x, test_x, train_y, test_y = train_test_split(cells, labels, test_size=1 - c.train_ratio, shuffle=False)
val_x, test_x, val_y, test_y = train_test_split(test_x, test_y, test_size=c.test_ratio / (c.test_ratio + c.val_ratio),
                                                shuffle=False)

# The amount of images in each set
print('Training data shape: ', train_x.shape)
print('Validation data shape: ', val_x.shape)
print('Testing data shape: ', test_x.shape)

# Neural network
model.add(Conv2D(32, (3, 3), input_shape=c.input_shape, activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(units=64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(units=1, activation='sigmoid'))

# Compile the model
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])

# Data augmentation
train_datagen = ImageDataGenerator(rescale=1. / 255,
                                   rotation_range=20,
                                   width_shift_range=0.05,
                                   height_shift_range=0.05,
                                   shear_range=0.05,
                                   zoom_range=0.05,
                                   horizontal_flip=True,
                                   fill_mode='nearest')

validation_datagen = ImageDataGenerator(rescale=1. / 255)
testing_datagen = ImageDataGenerator(rescale=1. / 255)

training_dataset = train_datagen.flow(train_x, train_y, batch_size=32)
validation_dataset = validation_datagen.flow(val_x, val_y, batch_size=32)
testing_dataset = validation_datagen.flow(val_x, val_y, batch_size=32)

# Add callbacks to prevent overfitting
es = EarlyStopping(monitor='accuracy',
                   min_delta=0,
                   patience=2,
                   verbose=0,
                   mode='max')

rlrop = ReduceLROnPlateau(monitor='val_loss',
                          factor=0.2,
                          patience=0.5,
                          min_lr=0.001)

checkpoint = ModelCheckpoint("Model.h5")

# Perform backpropagation and update weights in model
history = model.fit_generator(training_dataset,
                              epochs=50,
                              validation_data=validation_dataset,
                              callbacks=[es, checkpoint, rlrop])

# Save model & weights
model.save_weights("Model_weights.h5")
model.save("Model.h5")

# Plot accuracy graph
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper left')
plt.show()

【问题讨论】:

你怎么知道它的过拟合?,你的验证准确率 > 从图中训练准确率 "图表总是显示一条直线,要么急剧增加要么急剧减少" 图表显示每条线的四个点,因为 Keras 只记录 end 的准确度每个时代。从您的验证损失来看,模型已经在一个时期训练,没有过度拟合的迹象(验证损失没有减少)。 val loss 高于 train loss 有点奇怪,但是你有数据增强,可以有效地使测试数据集更容易分类,所以我不会太担心 是的。正如@GPhilo 所说,您的准确度线图看起来非常好,拥有比 train 更好的 val acc 甚至有点奇怪,但无论如何这不符合过度拟合的定义。 【参考方案1】:

似乎不是过度拟合的情况。不用多看,会做以下事情:

    将过滤器保留在第一层的 32 处,并在随后的每个卷积层上逐渐加倍。

    由于图像中的变化并没有那么显着降低 Dropout 率。

奇怪的是,这是我第一次尝试 Tensorflow 2.0 时构建的,您可以查看 here。

【讨论】:

啊,看来我看错了图表。我的印象是这是过度拟合的情况,因为在第二个 epoch 之后准确率会从大约 80% 跃升至 90%。另一件事是测试结果相当差!这意味着它没有很好地泛化,我认为应该归咎于过度拟合。我已经尝试了您的建议,降低 dropout 似乎使训练验证更高一些。但是测试结果(看不见的数据)仍然很差。 过度拟合是指您的模型学习了实际的日期集并使用该数据表现得非常好,但在新数据上表现不佳。我建议您将图层建立在已证明有效的东西(即 vgg)上。再看一眼,将 dropout 层放在密集层之前。编译模型时,在密集层和 adam 优化器中使用 relu 激活(Adam 通常是一个很好的起点,因为它不太容易在局部点收敛)。也玩学习率。仔细看看我给你的示例模型,看看是否有什么东西可以从那里举起。

以上是关于Keras:过拟合模型?的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch vs. Keras:Pytorch 模型严重过拟合

防止神经网络模型过拟合的6种方法及keras代码实现

Keras 密集网络过拟合

如何提高keras模型的准确率,防止过拟合

如何在 Keras 模型中训练和验证样本较小时测量过拟合

Keras深度学习实战——深度学习过拟合问题及解决方法