【问题标题】:Using multiple images per data point in a binary classification CNN在二进制分类 CNN 中为每个数据点使用多个图像
【发布时间】:2020-08-16 17:56:16
【问题描述】:

我正在制作一个 CNN 模型,将 MRI 脑部扫描分类为阿尔茨海默氏症和健康组。

目前看来它似乎过拟合了,我们在书中尝试了很多技巧来解决这个问题。

我现在想尝试的一种方法(但没有经验)是对每个数据点使用多个脑部扫描图像。

例如:

我以 .nii 格式下载脑部扫描图像并将它们转换为一系列 png 文件。每个 png 文件在不同的时间点进行相同的扫描。在我目前的模型中,我只是在每次脑部扫描时删除了所有这些图像,只删除了一张,使我的模型更易于使用。

我现在想尝试的是为我的数据集中的每个样本使用多张图片(比如从 5 张开始)。

我将如何通过改变我当前的模型来实现这一目标?

我不想使用 ImageDataGenerator 的数据增强功能,我想使用我存储在计算机上的现有文件。

由于当前模型的训练准确度约为 80%,验证准确度为 55%,因此我将不胜感激。

# Use ImageDataGenerator to create 3 lots of batches
train_batches = ImageDataGenerator(
    rescale=1/255).flow_from_directory(directory=train_path,
        target_size=(80,80), classes=['cn', 'ad'], batch_size=100,
            color_mode="rgb")
valid_batches = ImageDataGenerator(
    rescale=1/255).flow_from_directory(directory=valid_path,
        target_size=(80,80), classes=['cn', 'ad'], batch_size=100,
            color_mode="rgb")
# test_batches = ImageDataGenerator(
#     rescale=1/255).flow_from_directory(directory=test_path,
#         target_size=(224,224), classes=['cn', 'ad'], batch_size=10,
#             color_mode="rgb")

imgs, labels = next(train_batches)

# Test to see normalisation has occurred properly
print(imgs[1][8])

# Define method to plot MRIs
def plotImages(images_arr):
    fig, axes = plt.subplots(1, 10, figsize=(20,20))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
        ax.axis('off')
    plt.tight_layout()
    plt.show()

# Plot a sample of MRIs
plotImages(imgs)

# # Define the model
# # VGG16
# model = Sequential()
# model.add(Conv2D(input_shape=(160,160,3),filters=64,kernel_size=(3,3),padding="same", activation="relu"))
# model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"))
# model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
# model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
# model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))
# model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))
# model.add(Flatten())
# model.add(Dense(units=1024,activation="relu"))
# model.add(Dense(units=128,activation="relu"))
# model.add(Dense(units=2, activation="softmax"))

# # Model from the paper
# model = Sequential([
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(160,160,3)),
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same'),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Flatten(),
#     Dense(units=2, activation='softmax')
# ])

## Model from Dr Paul
# static_conv_layer=Conv2D(filters=16, kernel_size=(5, 5), activation='relu', padding = 'same')
#
# model = Sequential([
#     Conv2D(filters=16, kernel_size=(5, 5), activation='relu', padding = 'same', input_shape=(32,32,3)),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Dropout(0.1),
#     static_conv_layer,
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Dropout(0.1),
#     Flatten(),
#     Dense(units=2, activation='softmax')
# ])

# This model hits around 75% train acc, 54% val acc
model = Sequential([
    Conv2D(filters=16, kernel_size=(5, 5), activation='relu', padding = 'same', input_shape=(80,80,3)),
    MaxPool2D(pool_size=(2, 2), strides=2),
    # Dropout(0.1),
    # Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same'),
    # MaxPool2D(pool_size=(2, 2), strides=2),
    # Conv2D(filters=16, kernel_size=(3, 3), activation='relu', padding='same'),
    # MaxPool2D(pool_size=(2, 2), strides=2),
    Flatten(),
    Dense(units=2, activation='softmax')
])

# model = Sequential([
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(160,160,3)),
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same'),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same'),
#     Flatten(),
#     Dense(units=2, activation='softmax')
# ])

## Basic model with dropouts
# model = Sequential([
#     Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(224,224,3)),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Dropout(0.1),
#     Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same'),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Dropout(0.2),
#     Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'),
#     MaxPool2D(pool_size=(2, 2), strides=2),
#     Dropout(0.3),
#     Flatten(),
#     Dense(units=1, activation='sigmoid')
# ])

# Summarise each layer of the model
print(model.summary())

# Compile and train the model
model.compile(optimizer=Adam(), loss='binary_crossentropy', metrics=['accuracy'])
model.fit(x=train_batches,
    steps_per_epoch=len(train_batches),
    validation_data=valid_batches,
    validation_steps=len(valid_batches),
    epochs=20,
    verbose=1
)

【问题讨论】:

  • 这是我的favorite article(我经常提到)关于如何防止过拟合和欠拟合。 :) 一些技巧包括简化模型(移除神经元/层)和添加Dropout layers。在您的模型中,我还注意到在您的 Flatten 层之后,您没有更多的 Dense 层。在 Flatten 之后,尝试添加一个具有 64-128 个神经元的密集层。
  • @Landon 我尝试将我的模型简化到只包含一个 conv2d 和最大池化层的程度。我也试过添加辍学层无济于事。我会尝试额外的密集层,但我真的认为问题的症结在于每个数据点没有足够的图像,你有关于如何在每个数据点使用多个图像的任何信息吗?不管怎样,谢谢!
  • 您的目标是防止过度拟合还是以 5 个一组而不是单独提供图像?

标签: python tensorflow keras deep-learning conv-neural-network


【解决方案1】:

现在为了在您的模型中合并多张图像,您可以为每个数据点获取多张图像,最简单的方法是将它们平均化,您可以尝试一下。但是,更好的方法是对多张图像应用降维。

首先,它将整合每个人的所有特征,而且,如果每个人的图像数量不同,那么这将简化您的训练。

最好在外部计算特征,然后将它们插入到您的模型中。

考虑到这一点,首先要考虑 PCA。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 2016-04-19
    • 2012-09-23
    • 2020-04-01
    • 2020-12-15
    相关资源
    最近更新 更多