ValueError:尝试计算 ROC 曲线时输入形状错误 (2, 256, 3)

Posted

技术标签:

【中文标题】ValueError:尝试计算 ROC 曲线时输入形状错误 (2, 256, 3)【英文标题】:ValueError: bad input shape (2, 256, 3) when trying to compute ROC curve 【发布时间】:2019-07-03 12:26:38 【问题描述】:

首先,我是 python 新手。尝试构建 ROC 曲线时,我在此代码行上遇到错误:

fpr_keras, tpr_keras, thresholds_keras = roc_curve(Y_test.argmax(axis=1), decoded_imgs.argmax(axis=1))

错误:

ValueError: bad input shape (2, 256, 3)

当我在 reshape 后尝试塑形时,出现第二个错误:

TypeError: 'tuple' 对象不可调用

我关注了这个link,但我不明白我应该怎么做,我正在处理这个问题。有人可以编辑我的代码吗?这就是我想要做的:link2

import keras
import numpy as np
from keras.datasets import mnist
from get_dataset import get_dataset
from stack import keras_model

X_train, X_test, Y_train, Y_test = get_dataset()

from keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, Dense
from keras.models import Model

input_img = Input(shape=(256, 256, 3))

x = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)

x = Conv2D(64, (3, 3), activation='relu', padding='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
x = UpSampling2D((2, 2))(x)
decoded = Conv2D(3, (3, 3), activation='sigmoid', padding='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='rmsprop', loss='mae',metrics=['mse', 'accuracy'])

from keras.callbacks import ModelCheckpoint, TensorBoard
checkpoints = []

from keras.preprocessing.image import ImageDataGenerator

generated_data = ImageDataGenerator(featurewise_center=False, samplewise_center=False, featurewise_std_normalization=False, samplewise_std_normalization=False, zca_whitening=False, rotation_range=0,  width_shift_range=0.1, height_shift_range=0.1, horizontal_flip = True, vertical_flip = False)
generated_data.fit(X_train)
epochs = 1
batch_size = 5

autoencoder.fit_generator(generated_data.flow(X_train, X_train, batch_size=batch_size), steps_per_epoch=X_train.shape[0]/batch_size, epochs=epochs, validation_data=(X_test, X_test), callbacks=[TensorBoard(log_dir='/tmp/autoencoder')])

autoencoder.fit(X_train, X_train, batch_size=batch_size, epochs=epochs, validation_data=(X_test, X_test), shuffle=True, callbacks=[TensorBoard(log_dir='/tmp/auti')])

decoded_imgs = autoencoder.predict(X_test)

from sklearn.metrics import roc_curve
#2 256  3
print(decoded_imgs.argmax(axis=1))
print(decoded_imgs.argmax(axis=1).reshape(1,3))

fpr_keras, tpr_keras, thresholds_keras = roc_curve(Y_test.argmax(axis=1), decoded_imgs.argmax(axis=1))

ValueError: bad input shape (2, 256, 3)    

将行编辑为:

fpr_keras, tpr_keras, thresholds_keras = roc_curve(Y_test.argmax(axis=1), decoded_imgs.reshape(6,256,1)) 

我得到这个错误:

ValueError: 发现样本数量不一致的输入变量:[2, 4]

【问题讨论】:

欢迎来到 SO; 1) 请删除所有注释掉的代码,以及所有您不提供输出的打印/绘图命令(看看为什么a wall of code isn't helpful) 2) 也删除所有附带的代码在产生错误的行之后,因为它从不执行,因此与问题无关 3)修复您的第一行代码,这可以说是问题的核心 4)发布您的 @987654327 示例@ & decoded_imgs(同样,这些是您问题的核心) @desertnaut 我编辑了我的代码,你现在可以修复它吗? fpr_keras, tpr_keras, thresholds_keras = roc_curve(Y_test.argmax(axis=1), decoded_imgs.argmax(axis=1).reshape(6,256,1)) 之后还有代码(这个随机森林在那里做什么??),顺便说一句,这与您在帖子开头显示的命令不同...请把 exact 命令就地产生错误,并删除它之后的所有内容 “当我在重塑后尝试塑形时出现第二个错误”这可能是因为您在塑形后检查形状时使用了a.shape(),您只需去掉括号:@ 987654331@. 【参考方案1】:

对于 ROC 曲线和自动编码器的基础知识,您听起来有点困惑...

引用roc_curve的scikit-learn documentation:

roc_curve (y_true, y_score, pos_label=None, sample_weight=None, drop_intermediate=True)

参数:

y_true : 数组,形状 = [n_samples]

真正的二进制标签。如果标签不是 -1, 1 或 0, 1,则应明确给出 pos_label。

y_score : 数组,形状 = [n_samples]

目标分数,可以是正类的概率估计、置信度值或决策的非阈值度量(如 由某些分类器上的“decision_function”返回)。

换句话说,roc_curve 的两个输入都应该是简单的一维标量数组,第一个包含真实类别,第二个包含预测分数。

现在,尽管您没有展示您自己的数据样本,而且我不怀疑您的 Y_test.argmax(axis=1) 可能符合本规范,但最肯定的是您的 decoded_imgs.argmax(axis=1)(无论您如何重塑它) ) 没有。为什么?因为自动编码器的本质。

与您也尝试在代码的(现已删除的)部分中使用的模型(例如随机森林分类器)形成鲜明对比的是,自动编码器不是分类器:它们的功能是重建(去噪,压缩等)版本的输入,not 生成类预测(请参阅 Keras 博客中的漂亮小 tutorial 以了解快速定位)。在您的情况下,这意味着您的decoded_imgs 实际上是转换后的图像(或类似图像的数据,无论如何),而不是roc_curve 要求的课程分数,因此错误(从技术上讲,实际上是由于decoded_imgs 不是一维数组,但希望你能明白)。

即使您在这里使用分类器而不是自动编码器,您也会遇到另一个问题:ROC 曲线用于二元分类任务,而不是用于多类任务,例如 MNIST (实际上也有一些方法将它们应用于多类数据,但它们并未广泛使用 AFAIK)。确实,从表面上看,scikit-learn 的 roc_curve 即使在多类设置中也可以工作:

import numpy as np
from sklearn import metrics

y = np.array([0, 1, 1, 2, 2]) # 3-class problem
scores = np.array([0.05, 0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)  # works OK, no error

但实际上这种情况发生只是因为我们明确定义了pos_label=2,因此,在幕后,scikit-learn 将除2 之外的所有标签视为负标签,然后将其余的计算视为我们的问题是二进制问题(即2 类与所有其他类)。

就您的情况(MNIST)而言,您应该问自己一个问题:10 类 MNIST 数据集中的“阳性”究竟是什么?这个问题是否有意义? 希望你能够说服自己答案并不简单,就像二进制 (0/1) 的情况一样。


总结一下:这里没有编码错误需要纠正;问题的根本原因只是您尝试了一些无意义且无效的事情,因为自动编码器不会产生类预测,因此它们的输出不能用于计算 ROC 曲线。我建议您先深入了解相关概念和概念,然后再进行应用...

【讨论】:

感谢@desertnaut 的回答,我的目标是人脸识别,我的代码中的自动编码器用于去噪和数据压缩。我在另一个代码中计算欧几里得距离和余弦相似度。只是,要绘制 ROC 曲线,我不知道我必须将什么作为输入(分数?)传输到 ROC 曲线代码以测试我的识别系统的性能。 @GuizmoCharo 现在应该很明显了,ROC 曲线不能用于衡量任何数据“去噪”或“压缩”的性能,它只是 (二进制)分类。既然答案可以说解决了您的问题,请接受它(答案占用了受访者的宝贵时间)-谢谢。

以上是关于ValueError:尝试计算 ROC 曲线时输入形状错误 (2, 256, 3)的主要内容,如果未能解决你的问题,请参考以下文章

ROC曲线如何确定诊断临界值

如何从具有 2 个输出神经元的 softmax 二元分类器绘制 ROC 曲线?

如何在 Python 中绘制 ROC 曲线

ROC曲线 大于阈值后如何计算HR

ROC 曲线,以及AUC计算方式

R语言ROC分析ROC曲线可视化及最佳阈值计算(thresholdcutoff)