Python 凯拉斯:过拟合模型?

Python 凯拉斯:过拟合模型?,python,machine-learning,keras,deep-learning,classification,Python,Machine Learning,Keras,Deep Learning,Classification,我正在尝试使用NIH(国家医学图书馆)的疟疾数据集创建一个二值图像分类模型,该数据集包含每个类别(感染/未感染)的大约27000张图像 这似乎有点过度拟合,我尝试过使用不同的批处理大小、每个历元的步骤/验证步骤、使用不同的隐藏层和添加回调等。图中始终显示一条直线,该直线要么急剧增加,要么急剧减少,而不是在学习过程中稳步增加,但有所减少(根据我的理解,应该是这样的)。下面是一个例子,大多数结果与此类似 我是一个新的深度学习者,我读过很多关于过度装修和试图找到解决方案的书。但我认为一定是我做错了什

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


这似乎有点过度拟合,我尝试过使用不同的批处理大小、每个历元的步骤/验证步骤、使用不同的隐藏层和添加回调等。图中始终显示一条直线,该直线要么急剧增加,要么急剧减少,而不是在学习过程中稳步增加,但有所减少(根据我的理解,应该是这样的)。下面是一个例子,大多数结果与此类似

我是一个新的深度学习者,我读过很多关于过度装修和试图找到解决方案的书。但我认为一定是我做错了什么和/或误解了什么。如果有人能发现一些看起来不对劲的东西,并能为我指出正确的方向,我将不胜感激

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()

这似乎不是过度装修的情况。如果不仔细观察,将执行以下操作:

  • 在第一层将滤波器设置为32,然后在接下来的每个卷积层上逐渐加倍

  • 因为图像中的变化并没有那么显著,所以降低了辍学率


  • 奇怪的是,这是我第一次尝试Tensorflow 2.0时创建的,你可以检查。

    你如何知道它的过度拟合?你的验证精度>从图中训练精度“图中总是显示一条直线,要么急剧增加,要么急剧减少”图表显示了每条线的四个点,因为Keras只记录每个历元结束时的精度。从您的验证损失来看,模型已经在一个历元中训练,没有过度拟合的迹象(验证损失不会减少)有点奇怪,val损耗比train损耗高,但您的数据增加有效地使测试数据集更容易分类,所以我不太担心。您的精度线图看起来非常好,正如@GPhilo所说,拥有比train更好的val acc甚至有点奇怪,但无论如何,这不符合定义过度拟合。啊,似乎我误读了图表。我当时的印象是,这是一个过度拟合的案例,因为在第二个纪元之后,准确率会从大约80%跳到90%。另一件事是,测试结果相当差!这意味着它没有很好地推广,我认为过度拟合是罪魁祸首。我已经尝试了你的建议,降低辍学率似乎使培训验证更高一些。但是测试结果(看不见的数据)仍然很差。过度拟合是指您的模型了解实际数据集,并使用该数据执行得非常好,但在新数据上执行得很差。我建议您将层建立在经证明有效的基础上(即vgg)。再看一眼,将退出层放在密集层之前。编译模型时,在密集层和adam优化器中使用relu激活(adam通常是一个很好的起点,因为它不太容易在局部点收敛).还要考虑学习率。仔细看看我给你的示例模型,看看是否有什么可以提高的地方。