CNN 数据不平衡,测试准确率高达 70%

问题描述

我正在使用眼底图像数据处理糖尿病视网膜病变的图像分类任务。有5个班。数据分布为1805张图像(类别1)、370张图像(类别2)、999张图像(类别3)、193张图像(类别4)、295张图像(类别5)。 以下是我尝试运行的步骤:

  1. 预处理(调整大小为 224 * 224)
  2. 训练和测试数据的划分为 85% : 15%
x_train,xtest,y_train,ytest = train_test_split(
    x_train,test_size = 0.15,random_state=SEED,stratify = y_train
)
  1. 数据分析
ImageDataGenerator(
        zoom_range=0.15,fill_mode='constant',cval=0.,horizontal_flip=True,vertical_flip=True,)
  1. 使用 resnet-50 模型和交叉验证进行训练
def getresnet():
    modelres = resnet50(weights=None,include_top=False,input_shape= (IMAGE_HEIGHT,IMAGE_HEIGHT,3))
    x = modelres.output
    x = GlobalAveragePooling2D()(x)
    x = Dense(5,activation= 'softmax')(x)
    model = Model(inputs = modelres.input,outputs = x)
    return model

num_folds = 5
skf = StratifiedKFold(n_splits = 5,shuffle=True,random_state=2021) 
cvscores = []
fold = 1
for train,val in skf.split(x_train,y_train.argmax(1)):
    print('Fold: ',fold)
    Xtrain = x_train[train]
    Xval = x_train[val]
    Ytrain = y_train[train]
    Yval = y_train[val]
    data_generator = create_datagen().flow(Xtrain,Ytrain,batch_size=32,seed=2021)

    model = getresnet()
    model.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.0001),metrics=['accuracy'])
    with tf.compat.v1.device('/device:GPU:0'):       
          model_train = model.fit(data_generator,validation_data=(Xval,Yval),epochs=30,batch_size = 32,verbose=1)
    model_name = 'cnn_keras_aug_Fold_'+str(fold)+'.h5'
    model.save(model_name)
    scores = model.evaluate(xtest,ytest,verbose=0)
    print("%s: %.2f%%" % (model.metrics_names[1],scores[1]*100))
    cvscores.append(scores[1] * 100)
    fold = fold +1

我从这种方法中得到的最大结果是训练准确度为 81.2%,验证准确度为 72.2%,测试准确度为 70.73%。 任何人都可以给我一个改进模型的想法,以便我可以使测试准确率尽可能高于 90%? 稍后,我将使用此模型作为预训练模型来训练糖尿病视网膜病变数据,但来自其他来源。

顺便说一句,我试过用这种方法替换我的预处理:

def preprocessing(path):
    image = cv2.imread(path)
    image = crop_image_from_gray(image)
    green = image[:,:,1]
    clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
    cl = clahe.apply(green)
    image[:,0] = image[:,0]
    image[:,2] = image[:,2]
    image[:,1] = cl
    image = cv2.resize(image,(224,224))
    return image

我还尝试用 VGG16、EfficientNetB0 替换我的模型。然而,这些都没有对我的结果产生太大影响。我仍然坚持大约 70% 的准确率。 请帮助我提出改进我的建模结果的想法。我希望。

解决方法

您的训练准确率为 81.2%。测试准确度通常不可能高于训练准确度,即在当前设置下,您不会达到 90%。

但是,您的验证(以及测试)准确度约为 70-72%。我可以建议,在您的小数据集上,您的模型过度拟合。因此,如果您添加模型正则化(例如 dropout),您的训练和验证(和测试)之间的差距可能会减小。这样您就可以提高验证分数。

要进一步提高分数,您需要手动检查数据并尝试了解哪些类对错误的贡献最大,并找出如何减少这些错误(例如更新预处理管道)。