在考虑深度学习方法时,我的 ROC 曲线有什么问题?

What is wrong with my ROC curves when considering deep leaning approaches?

我有一个 class使用 CNN 处理图像的应用程序。我正在考虑输入大小为 64 x 64 图像块的 Mobilenet、Resnet 和 Densenet。为了 class 化图像,我将其 class 定义为 class 在 class 化其块时出现最多的图像。这个问题非常不平衡,我的正样本多于负样本。我正在考虑三个数据集。

为了解决这个问题,我首先计算了f-measure、normalized accuracy等指标。以下是考虑到三个 CNN 的一些数据集的归一化精度结果:

为了构建 ROC 曲线,我决定将图像的分数定义为其块的平均分数,所以这就是我的问题开始的地方。考虑到以下三个 CNN,请查看这些数据集的一些 ROC 曲线:

我很奇怪地看到获得 50% 归一化精度的方法也有 0.85、0.90 甚至 0.97 AUC。这最后一个 AUC 似乎来自一个近乎完美的 classifier,但如果它的归一化准确度是 50%,这怎么可能呢?

那么,这是什么原因呢?是因为:

1- 我的问题是不平衡的。阳性样本也是如此,它们主要出现在我的数据集中,并且我的 ROC 中感兴趣的 class 会影响结果吗?

2-我使用块的平均分数作为图像的分数。有什么办法可以解决这个问题吗?

这是我用来生成标签和分数的代码 (PYTHON)

 base_model=MobileNet(input_shape (64,64,3),weights=None,include_top=False)
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    x = Dense(64, activation='relu')(x)
    predictions = Dense(2, activation='softmax')(x)
    model = Model(inputs=base_model.input, outputs=predictions)
    model.load_weights(model_path)

    intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer("dense_2").output)
    print("Loaded model from disk")
    intermediate_layer_model.compile(loss='categorical_crossentropy', optimizer=algorithm, metrics=['accuracy'])

    #read images, divide them into blocks, predict images and define the mean scores as the score for an image
    with open(test_images_path) as f:
            images_list = f.readlines()
            images_name = [a.strip() for a in images_list]
            predicted_image_vector = []
            groundtruth_image_vector = []

            for line in images_name:
                x_test=[]
                y_test=[]
                print(line)
                image = cv2.imread(line,1)
                #divide into blocks
                windows = view_as_windows(image, (64,64,3), step=64)

                #prepare blocks to be tested later 
                for i in range(windows.shape[0]):
                    for j in range(windows.shape[1]):
                            block=np.squeeze(windows[i,j])
                            x_test.append(block)
                            label = du.define_class(line)
                            y_test.append(label)

            #predict scores for all blocks in the current test image
            intermediate_output = intermediate_layer_model.predict(np.asarray(x_test), batch_size=32, verbose=0)
            #the score for an image is the mean score of its blocks
            prediction_current_image=np.mean(intermediate_output, axis=0)
            predicted_image_vector.append(prediction_current_image)
 groundtruth_image_vector.append(np.argmax(np.bincount(np.asarray(y_test))))

    predicted_image_vector=np.array(predicted_image_vector)
    groundtruth_image_vector=np.array(groundtruth_image_vector)
    print("saving scores and labels to plot ROC curves")

    np.savetxt(dataset_name+ '-scores.txt', predicted_image_vector, delimiter=',') 
    np.savetxt(dataset_name+ '-labels.txt', groundtruth_image_vector, delimiter=',') 

这是我用来生成ROC曲线的代码(MATLAB)

function plot_roc(labels_file, scores_file, name_file, dataset_name)

    format longG
    label=dlmread(labels_file);
    scores=dlmread(scores_file);
    [X,Y,T,AUC] = perfcurve(label,scores(:,2),1);   

    f=figure()
    plot(X,Y);
    title(['ROC Curves for Mobilenet in ' dataset_name])
    xlabel('False positive rate'); 
    ylabel('True positive rate');
    txt = {'Area Under the Curve:', AUC};
    text(0.5,0.5,txt)
    saveas(f, name_file);
    disp("ok")



end

根据我对您的方法的了解 - 输入图像被分成单独的块,这些块由 CNN 模型独立处理。每个补丁都有自己的 classification(或分数,取决于它是在 softmax 之后还是之前)。图像的 class 是根据补丁的 classes 投票确定的。

但是当您构建 ROC 曲线时,您是在使用各个补丁的平均分数来确定图像的class化。

这两种不同的方法是 AUC 与归一化准确度不相关的原因。

例如:

假设图像中有 3 个补丁,概率如下(2 classes):

[cls a, cls b]

[0.51, 0.49]

[0.51, 0.49]

[0.01, 0.99]

通过投票 class a 是预测(2 个补丁对 1 个),平均得分 class b 是预测(0.657 对 0.343)。

我个人认为投票不是class基于补丁验证图像的正确方法,因为它没有考虑模型关于不同补丁的确定性,如中所示例子。但是你更熟悉你的数据集,所以也许我错了。

关于如何解决您的问题,我认为有关数据集和任务的性质的更多信息会有所帮助(不平衡程度如何,最终目标是什么,等等)