繁体   English   中英

Keras CNN 总是预测相同的 class

[英]Keras CNN always predicts same class

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

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

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

对于上下文,我在两组之间进行分类。 我使用的图像数量是总共 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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM