【问题标题】:How to find the ROC curve and AUC score of this CNN model (keras)如何找到这个CNN模型(keras)的ROC曲线和AUC分数
【发布时间】:2020-08-15 03:56:42
【问题描述】:

我在keras中的CNN代码如下:

from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
from keras.layers import Dropout

classifier = Sequential()
#1st Conv layer
classifier.add(Convolution2D(64, (9, 9), input_shape=(64, 64, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(4,4)))
#2nd Conv layer
classifier.add(Convolution2D(32, (3, 3), activation='relu'))
classifier.add(MaxPooling2D(pool_size=(2,2)))

#Flattening
classifier.add(Flatten())

# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dropout(0.1))
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dropout(0.2))
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 2, activation = 'softmax'))

classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])

#Fitting dataset

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)

test_datagen = ImageDataGenerator(rescale = 1./255)

training_set = train_datagen.flow_from_directory('dataset/training_set',
                                                 target_size = (64, 64),
                                                 batch_size = 32,
                                                 class_mode = 'categorical')

test_set = test_datagen.flow_from_directory('dataset/test_set',
                                            target_size = (64, 64),
                                            batch_size = 32,
                                            class_mode = 'categorical')

classifier.fit_generator(
        training_set,
        steps_per_epoch=(1341+3875)/32,
        epochs=15,
        validation_data=test_set,
        validation_steps=(234+390)/32)

无论我在哪里看到 sklearn.metrics 中使用 roc_curve,它都需要 x_train、y_train、x_test、y_test 等参数,我知道这些参数可以是 pandas DataFrame,但在我的情况下并非如此。如何绘制 ROC 曲线并获得用于 CNN 模型训练的 AUC 分数?

【问题讨论】:

    标签: python tensorflow keras deep-learning neural-network


    【解决方案1】:

    实际上,如果查看 sklearn.metrics.roc_curve 的文档(以及几乎每个 sklearn 指标),它们不会将模型(图像)的输入作为参数,它只需要真实标签和预测标签。因此,在您对测试集进行推断之后,在 keras 中(我只是猜测)类似于

    preds = classifier.predict(batch)

    你把 roc_curve 称为

    fpr, tpr = roc_curve(true_labels,preds)

    可能你必须改变类型,因为它们是张量。

    编辑:我检查了 flow_from_directory 上的 keras 文档,并在 (x,y) = (images,labels) 上生成了一个迭代器,所以如果你想做某种训练后分析,你应该使用像这样:

    labels = []
    for _,y in test_set:
        labels.extend(list(y))
    

    如果你只有两个类,请将 class_mode 更改为 binary

    【讨论】:

    • 假设我有两个类名,“NORMAL”和“PNEUMONIA”用于胸部 X 光数据集。在classifier.predict(batch)中,我将batch作为测试集。那么,在调用 roc_curve 时,true_labels 的类型应该是什么?它是一个字符串列表,其中每个元素都是“正常”或“肺炎”吗?或者是 0 和 1,默认情况下将 0 分配给“正常”,反之亦然。我怎么知道模型遵循什么顺序来预测每个图像?图像在文件资源管理器中的排列顺序是否正常?
    • 关于你的第一个问题,是的,你应该为正常和肺炎分配一个数字标签。你有你的测试集的标签吗?有时人们将测试称为没有标签的集合,在这种情况下,您应该将训练集分为训练集和验证集。我不确定您的第二个问题,您的意思是模型可能会更改图像的顺序吗?如果答案是否定的,则预测将按照相同的顺序对应图像。
    • 对于测试集,我只有一个名为“test_set”的文件夹,其中还有两个名为“PNEUMONIA”和“NORMAL”的文件夹。您是否可以编辑您的答案并添加相应的代码以对它们进行标签编码,以便我可以准确地获得 true_labels?我不确定如何使用 LabelEncoder 自动为所有图像分配 0 和 1 的过程。请注意,“test_set”的第一个文件夹为“NORMAL”,第二个文件夹为“PNEUMONIA”。你答对了我的第二个问题。
    • 我尝试了您的解决方案,但它卡在 Jupyter Notebook 中的处理上。因此,我尝试调查 test_set,结果发现每个元素都是图像列表、标签元组(图像和标签分别是 2D 和 1D 列表)。我设法获得了一个 0 和 1 的标签列表,并将它们展平为一个只有 0 和 1 的列表,并将其命名为“true_labels”。我使用这个 'true_labels' 和 preds=classifier.predict(test_set) 作为 fpr, tpr = roc_curve(true_labels, preds) 但它给了我这个错误ValueError: too many values to unpack (expected 2)
    【解决方案2】:

    我让它工作了。我所要做的就是将从preds = classifier.predict(test_set) 获得的preds 的数据类型与我从labels = test_set 获得的true_labels 匹配。 Preds 基本上是一个 numpy.ndarray 包含具有 np.float32 值的单个元素列表。将标签转换为相同的格式和形状使 roc_curve 正常工作。

    另外,我必须在fpr, tpr, threshold = roc_curve(true_labels, preds) 中添加第三个变量阈值,因此不会弹出 ValueError: too many values to unpack 错误。

    【讨论】:

      【解决方案3】:

      要计算 ROC AUC,您需要分数,而不是最终分类/决策的结果。

      由于您的模型有一个带有两个神经元 (classifier.add(Dense(units = 2, activation = 'softmax'))) 作为其最后一层的 softmax,因此这是一种多类分类,其中类数为 2。但是,函数 roc_curve 仅限使用在二元分类问题中。所以,你不能将它与 softmax 一起使用。

      您可以用一个神经元和 sigmoid 替换您的 2 个神经元和 softmax。然后,在二分类问题中使用roc_curve 是安全的。

      还有另一个名为roc_auc_score 的函数,它有一个参数multi_class,可以将多类分类问题转换为多个二元问题。例如,auc_roc = roc_auc_score(labels, classifier.predict(...), multi_class='ovr')。但是,这只会返回 AUC 分数,并不能帮助您绘制 ROC 曲线。

      【讨论】:

        猜你喜欢
        • 2021-03-12
        • 1970-01-01
        • 2020-05-05
        • 2021-06-12
        • 2021-11-01
        • 2015-11-24
        • 2016-01-17
        • 2012-04-15
        • 2019-09-29
        相关资源
        最近更新 更多