在考虑深度学习方法时,我的 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基于补丁验证图像的正确方法,因为它没有考虑模型关于不同补丁的确定性,如中所示例子。但是你更熟悉你的数据集,所以也许我错了。
关于如何解决您的问题,我认为有关数据集和任务的性质的更多信息会有所帮助(不平衡程度如何,最终目标是什么,等等)
我有一个 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基于补丁验证图像的正确方法,因为它没有考虑模型关于不同补丁的确定性,如中所示例子。但是你更熟悉你的数据集,所以也许我错了。
关于如何解决您的问题,我认为有关数据集和任务的性质的更多信息会有所帮助(不平衡程度如何,最终目标是什么,等等)