【问题标题】:Confusion matrix subset of classes not working properly类的混淆矩阵子集无法正常工作
【发布时间】:2019-10-29 11:58:15
【问题描述】:

我已经在互联网上搜索了这个问题的答案,包括写标题时的建议,但仍然无济于事,希望有人能提供帮助!

我正在尝试使用 sci-kit learn 构建混淆矩阵。这是在 keras 模型之后出现的。

这很奇怪,因为我遇到了以下问题:对于原始数据的训练和测试集...我可以如下构造混淆矩阵(请注意,这是一个多标签问题,因此数据必须是不同标签的子集。

以下工作正常:

cm = confusion_matrix(y_train[:,0:6].argmax(axis=1), trainpred[:,0:6].argmax(axis=1))

和 6:18 等...直到所有类都成为子集。结果形成的混淆矩阵反映了keras模型的真实结果..

当我在完全看不见的数据上部署模型时,问题就出现了。

我通过调用model.predict() 部署模型并获得如上所示的结果。但是,现在我不能以同样的方式对混淆矩阵进行子集化。

代码 cm=confusion_matrix 等...导致 CM 的输出尺寸错误,即使在指定 0:6 等时也是如此。

因此,我使用了上面使用的代码,但修改了标签参数:

age[0,1,2,3,4]
organ[5,6,7,8]

cm = confusion_matrix(y_train[:,0:6].argmax(axis=1), trainpred[:,0:6].argmax(axis=1), labels=age)

第一个标签 (1:5) 完美运行...但是,下一个标签却不行!我在混淆矩阵中没有得到正确的值,并且匹配对于其中的那些也是不正确的。

将其放在上下文中:看不见的测试数据中有 400 多个样本。

model.predict 对大多数标签显示出非常高的分类和正确分数..

调用 CM=ytest[:,4:8]etc 确实会产生一个 4x4 矩阵,但是其中有 5 个值而不是 400,并且其中的那些值没有正确匹配。

另外..标签年龄为 012345,将 ytest 子集为 0:6 会导致形成正确的混淆矩阵(我不确定为什么 6 必须包含在子集中...不过我已经尝试过同一个问题的不同组合!

我已经搜索了这个答案的高低,所以非常感谢一些帮助,因为它非常令人沮丧。我很乐意提供更多代码/信息!

非常感谢!

【问题讨论】:

  • sub set confusion matrix 是什么意思?通常,您通过使用预测和实际标签为 N 类的所有数据 [NXN] 生成混淆矩阵。您能否附上预期输出的图像和一些示例数据?
  • 谢谢!是的,请参阅附加到原始问题的附加屏幕截图......您的问题:我的数据是多标签分类。所以我犯了一个错误,说子集混淆矩阵..而不是它是 one-hot 标签和 model.predict 表的子集,以便单独查看每个标签的 CM。 0:6 是年龄,6:18 是器官等.. 屏幕截图显示了年龄的第一个子集,但器官 CM 中几乎没有任何标签.. 似乎完全错误(并且不反映预测分数要么)....
  • 抱歉补充一句:在 5x5 位置上包含 192 个样本的屏幕截图是一个很好的预测,因为所有样本的年龄都相同......当我尝试对数据进行子集以显示第二个时,您可以看到原始帖子中显示的标签(器官)子集显示下一个标签产生第二个屏幕截图..一个奇怪的CM,矩阵中实际上没有任何样本!正如您从第一个 CM 中看到的那样,有 200 多个样本......

标签: machine-learning scikit-learn confusion-matrix


【解决方案1】:

发生这种情况是因为您试图对生成的混淆矩阵进行子集化,但实际上您必须使用指定的类标签手动生成一个新的混淆矩阵。如果你对A, B, C 上课,你将得到一个 3X3 矩阵。如果你想创建只关注A类的矩阵,其他类将变成false类,但false positivefalse negative会改变,因此你不能只对初始矩阵进行采样。

这就是你实际展示的方式

import matplotlib.pytplot as plt
import seaborn as sns

def generate_matrix(y_true, predict, class_name):
    TP, FP, FN, TN = 0, 0, 0, 0
    for i in range(len(y_true)):
        if y_true[i] == class_name:
            if y_true[i] == predict[i]:
                TP += 1
            else:
                FN += 1
        else:
            if y_true[i] == predict[i]:
                TN += 1
            else:
                FP += 1
    return np.array([[TP, FP],
                     [FN, TN]])

# Plot new matrix
matrix = generate_matrix(actual_labels, 
                         predicted_labels, 
                         class_name = 'A')

这将为class A 生成混淆矩阵。

【讨论】:

  • 非常感谢!!大多数功能都非常有意义! for i in range(len(y_true)): 允许标签为任意长度吗?例如,年龄是 6 个班级,器官是 12:运行以下函数时出现错误:matrix = generate_matrix(NormcountsOneHot1,SingleCelltestpred,class_name = OrganSC) OrganSC is organSC=[6,7,8,9. . up to 17].. 我收到以下错误:ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()
  • 这个函数不会处理编码,你必须添加它。目前它将接受实际标签 (y_true) 和预测标签 (predict) 的列表,并为 class_name 生成混淆矩阵。确保您只输入一维标签列表。
  • 是的!完美运行!再次感谢你!还将尝试在该功能中添加 one-hot 。感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多