提问者:小点点

Keras CNN预测即使在增强后也是相同的等级


我正在尝试创建一个CNN,对3D大脑图像进行分类。 然而,CNN程序总是在我运行它时预测相同的类,并且不确定我还能做什么其他方法来防止这一点。 我用许多看似合理的解决办法来寻找这个问题,但都不起作用

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

  • 降低学习速率
  • 将数据规范化为[0,1]
  • 更改优化器
  • 更改最后一层的激活(softmax,sigmoid),我只使用categorical_crossentropy
  • 添加/删除脱落层
  • 改为更简单的CNN模型(无济于事)
  • 平衡数据集
  • 使用自定义3D imagedatagenerator()添加增强数据
      链接:https://github.com/dhuy228/augmented-volumetric-image-generator

    请注意,我使用的图像数量是总共20个3D大脑图像(每类5个),我不能增加样本量,因为根本没有足够的图像。 我最近尝试了数据增强,但是这似乎没有帮助。

    如有任何帮助,我们将不胜感激!

    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\decline2'
    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)
                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())
    test_size = .2
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=test_size)
    print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
    
    
    batch_size = 4
    num_classes = 4
    
    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)
    
    conv4 = Conv3D(256, [3, 3, 3], padding='same', activation='relu')(drop3)
    conv4 = Conv3D(256, [3, 3, 3], padding='same', activation='relu')(conv4)
    pool4 = MaxPooling3D(pool_size=(2, 2, 2), padding='same')(conv4)
    drop4 = Dropout(0.5)(pool4)
    
    conv5 = Conv3D(256, [3, 3, 3], padding='same', activation='relu')(drop4)
    conv5 = Conv3D(256, [3, 3, 3], padding='same', activation='relu')(conv5)
    pool5 = MaxPooling3D(pool_size=(2, 2, 2), padding='same')(conv5)
    drop5 = Dropout(0.5)(pool5)
    
    flat1 = Flatten()(drop5)
    dense1 = Dense(128, activation='relu')(flat1)
    dense2 = Dense(64, activation='relu')(dense1)
    dense3 = Dense(32, activation='relu')(dense2)
    drop6 = Dropout(0.5)(dense3)
    dense4 = Dense(num_classes, activation='softmax')(drop6)
    
    model = Model(inputs=[inputs], outputs=[dense4])
    
    opt = optimizers.Adam(lr=1e-8, beta_1=1e-3, beta_2=1e-4, decay=2e-5)
    model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
    
    
    train_datagen = customImageDataGenerator(rescale=1./255,
                                             #width_shift_range=0.2,
                                             #height_shift_range=0.2,
                                             #rotation_range=15,
                                             #shear_range=0.2,
                                             #zoom_range=0.2,
                                             #brightness_range=[0.2, 1.0],
                                             data_format='channels_last',
                                             horizontal_flip=True)
    
    test_datagen = customImageDataGenerator(rescale=1./255)
    
    
    training_set = train_datagen.flow(x_train, y_train, batch_size=batch_size)
    
    testing_set = test_datagen.flow(x_test, y_test, batch_size=batch_size)
    
    
    callbacks = EarlyStopping(monitor='val_loss')
    
    model.fit_generator(training_set,
                        steps_per_epoch = 20,
                        epochs = 30,
                        validation_steps = 5,
                        callbacks = [callbacks],
                        validation_data = testing_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)
    

共1个答案

匿名用户

不知道到底发生了什么。 但我有几点意见和建议。

首先看一下学习曲线,看看它是否真的符合一些东西。

其次,您将0.2%的数据集用于由5个类的20幅图像组成的数据集。 如果所有最后的图像都是同一个标签。 你只会在那个标签上测试。 所以这可能是这里的一个问题,除非图像没有被分类。

第三,对于为数不多的数据,看起来您可能有很多密集的参数。 通常从小处开始,增加参数的数量。 通过观察学习曲线,你可以看到一些关于这一点的提示。

最后,可悲的是,机器学习并不神奇,你不能指望用那么少的数据取得好的结果。

阿莱克斯