【问题标题】:Keras CNN always predicts same classKeras CNN 总是预测同一类
【发布时间】:2020-10-28 10:03:54
【问题描述】:

编辑:似乎我什至没有运行足够的 epoch 的模型,所以我会尝试一下并返回我的结果

我正在尝试创建一个对 3D 大脑图像进行分类的 CNN。但是,当我运行 CNN 程序时,它总是预测同一个类,并且不确定我可以采取哪些其他方法来防止这种情况。我已经用许多似是而非的解决方案搜索了这个问题,但它们都不起作用

到目前为止,我已经尝试过:

对于上下文,我在两组之间进行分类。我使用的图像数量是总共 200 张 3D 大脑图像(每个类别大约 100 张)。为了增加训练规模,我使用了从 github 找到的自定义数据增强

查看学习曲线,准确率和丢失率是完全随机的。有些运行会减少,有些会增加,有些会在一定范围内波动

任何帮助将不胜感激!

import os
import csv
import tensorflow as tf  # 2.0
import nibabel as nib
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
from keras.models import Model
from keras.layers import Conv3D, MaxPooling3D, Dense, Dropout, Activation, Flatten 
from keras.layers import Input, concatenate
from keras import optimizers
from keras.utils import to_categorical
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
from augmentedvolumetricimagegenerator.generator import customImageDataGenerator
from keras.callbacks import EarlyStopping


# Administrative items
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# Where the file is located
path = r'C:\Users\jesse\OneDrive\Desktop\Research\PD\decline'
folder = os.listdir(path)

target_size = (96, 96, 96)


# creating x - converting images to array
def read_image(path, folder):
    mri = []
    for i in range(len(folder)):
        files = os.listdir(path + '\\' + folder[i])
        for j in range(len(files)):
            image = np.array(nib.load(path + '\\' + folder[i] + '\\' + files[j]).get_fdata())
            image = np.resize(image, target_size)
            image = np.expand_dims(image, axis=3)
            image /= 255.
            mri.append(image)
    return mri

# creating y - one hot encoder
def create_y():
    excel_file = r'C:\Users\jesse\OneDrive\Desktop\Research\PD\decline_label.xlsx'
    excel_read = pd.read_excel(excel_file)
    excel_array = np.array(excel_read['Label'])
    label = LabelEncoder().fit_transform(excel_array)
    label = label.reshape(len(label), 1)
    onehot = OneHotEncoder(sparse=False).fit_transform(label)
    return onehot

# Splitting image train/test
x = np.asarray(read_image(path, folder))
y = np.asarray(create_y())
x_split, x_test, y_split, y_test = train_test_split(x, y, test_size=.2, stratify=y)
x_train, x_val, y_train, y_val = train_test_split(x_split, y_split, test_size=.25, stratify=y_split)
print(x_train.shape, x_val.shape, x_test.shape, y_train.shape, y_val.shape, y_test.shape)


batch_size = 10
num_classes = len(folder)

inputs = Input((96, 96, 96, 1))
conv1 = Conv3D(32, [3, 3, 3], padding='same', activation='relu')(inputs)
conv1 = Conv3D(32, [3, 3, 3], padding='same', activation='relu')(conv1)
pool1 = MaxPooling3D(pool_size=(2, 2, 2), padding='same')(conv1)
drop1 = Dropout(0.5)(pool1)

conv2 = Conv3D(64, [3, 3, 3], padding='same', activation='relu')(drop1)
conv2 = Conv3D(64, [3, 3, 3], padding='same', activation='relu')(conv2)
pool2 = MaxPooling3D(pool_size=(2, 2, 2), padding='same')(conv2)
drop2 = Dropout(0.5)(pool2)

conv3 = Conv3D(128, [3, 3, 3], padding='same', activation='relu')(drop2)
conv3 = Conv3D(128, [3, 3, 3], padding='same', activation='relu')(conv3)
pool3 = MaxPooling3D(pool_size=(2, 2, 2), padding='same')(conv3)
drop3 = Dropout(0.5)(pool3)

flat1 = Flatten()(drop3)
dense1 = Dense(128, activation='relu')(flat1)
drop5 = Dropout(0.5)(dense1)
dense2 = Dense(num_classes, activation='sigmoid')(drop5)

model = Model(inputs=[inputs], outputs=[dense2])

opt = optimizers.Adagrad(lr=1e-5)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])


train_datagen = customImageDataGenerator(
                                         horizontal_flip=True
                                        )

val_datagen = customImageDataGenerator()

training_set = train_datagen.flow(x_train, y_train, batch_size=batch_size)

validation_set = val_datagen.flow(x_val, y_val, batch_size=batch_size)


callbacks = EarlyStopping(monitor='val_loss', patience=3)

history = model.fit_generator(training_set,
                    steps_per_epoch = 10,
                    epochs = 20,
                    validation_steps = 5,
                    callbacks = [callbacks],
                    validation_data = validation_set)

score = model.evaluate(x_test, y_test, batch_size=batch_size)
print(score)


y_pred = model.predict(x_test, batch_size=batch_size)
y_test = np.argmax(y_test, axis=1)
y_pred = np.argmax(y_pred, axis=1)
confusion = confusion_matrix(y_test, y_pred)
map = sns.heatmap(confusion, annot=True)
print(map)


acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

plt.figure(1)
plt.plot(acc)
plt.plot(val_acc)
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='best')
plt.title('Accuracy')

plt.figure(2)
plt.plot(loss)
plt.plot(val_loss)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='best')
plt.title('Loss')

您可以在此处找到输出:https://i.stack.imgur.com/FF13P.jpg

【问题讨论】:

  • 能否分享输出日志、model.summary 以及可视化效果?
  • dense2应该只有1个神经元,而不是num_classes。你也使用了太多的辍学。而且背靠背卷积只是浪费计算。
  • @AbhiramSatputé 我已经用您可以在此处找到的输出编辑了问题:i.stack.imgur.com/FF13P.jpg

标签: python tensorflow keras conv-neural-network


【解决方案1】:

没有数据集本身就很难提供帮助。虽然我会测试一两件事:

  • 我发现 ReLU 激活不适用于 Dense 层,这可能导致单类预测。尝试用其他东西(sigmoid、tanh)替换 Dense(128) 层中的 relu
  • Dropout 通常不适用于图像,您可能需要查看DropBlock
  • 初始学习率很低,我会从 1e-3 或 1e-4 之间的东西开始
  • 我经常发生的愚蠢事情:您是否将图像/标签组合可视化以确保每个图像都有正确的标签?

同样,不确定它是否能解决所有问题,但我希望它可能会有所帮助!

【讨论】:

  • 感谢您的意见,在尝试了您的建议后,我发现 1. 不幸的是,dense(128) 层的激活似乎不会以任何方式影响准确性。 2. 我已经删除了希望改进模型的 dropout,但似乎还不够。 3.你是对的,我已经适当调整了学习率,希望不会过拟合。 4. 我按照read_images(path, folder) 将读取的文件顺序使用excel文件标记每个图像,希望在我train_test_split时它会合并。不知道我还能如何检查。谢谢!
  • 让我回复你,看看情况如何
【解决方案2】:

这可能是任意数量的事情,但不当行为可能是由数据本身引起的。

仅从代码来看,您似乎在调用model.predictmodel.evaluate 之前还没有对测试数据进行标准化,就像您对训练和验证数据所做的那样。

我曾经遇到过类似的问题,结果证明这就是原因。作为一项快速测试,您只需重新调整测试数据的比例,看看是否有帮助。

【讨论】:

  • 你是对的,我直到现在才意识到这个错误,谢谢。我已经对所有图像进行了正确的归一化编辑问题,但是虽然我相信它在未来会有所帮助,但它目前并不能解决问题,并且模型仍然预测单个类,不幸的是
猜你喜欢
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2019-09-04
  • 2018-01-04
  • 2019-09-09
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
相关资源
最近更新 更多