【问题标题】:How to evaluate object detection in Python?如何评估 Python 中的对象检测?
【发布时间】:2021-05-20 10:19:22
【问题描述】:

对于给定图片,我有一个基本事实列表和一个相应预测的列表,用于对象检测,格式如下:

ground_truth = [[0,6,234,45,362],
                [1,1,156,103,336],
                [1,36,111,198,416],
                [1,91,42,338,500]]

prediction = [[0,6,234,39,128],
              [0,3,244,39,128]
              [1,1,156,102,180],
              [1,36,111,162,305]]

其中各个对象被描述为每个识别对象的边界框的class, min_x, min_y, max_x, max_y 值的(子)列表。

现在,我想根据实际情况评估预测的正确性。我知道联合上的交集和从中计算出的 F1,但仅适用于一个类和一个对象。我想知道如何将其推广到多个可能类的多个可能对象上?

我应该遍历每个真实对象并遍历所有预测对象,看看哪个预测最接近?但是,如果预测部分重叠了两个地面实况对象怎么办?很混乱……

【问题讨论】:

  • 我投票结束这个问题,因为这与编程或调试无关。这是一个关于设计统计模型评估的问题,这是题外话。 (见How to Ask。)
  • @AryaMcCarthy 实际上,difflib 模块处理这些事情 :)

标签: python object-detection evaluation


【解决方案1】:

您可以使用内置difflib 模块中的SequenceMatcher 类来比较两个数组。您的嵌套列表需要被展平才能工作,这可以通过嵌套的简单列表推导来完成:

from difflib import SequenceMatcher

ground_truth = [[0,6,234,45,362],
                [1,1,156,103,336],
                [1,36,111,198,416],
                [1,91,42,338,500]]

prediction = [[0,6,234,39,128],
              [0,3,244,39,128],
              [1,1,156,102,180],
              [1,36,111,162,305]]

lst1 = [a for b in ground_truth for a in b]
lst2 = [a for b in prediction for a in b]

print(SequenceMatcher(None, lst1, lst2).ratio())

输出:

0.45

如您所见,两个列表的相似度为 45%。

【讨论】:

    【解决方案2】:

    看看

    sklearn.metrics.f1_score(y_true, y_pred, *, labels=None, pos_label=1, average='binary', sample_weight=None, zero_division='warn')

    F-1 分数是准确率和召回率的调和平均值。

    参数average 将帮助您有效地处理多类/多标签情况:宏/微/样本/加权/二进制在多类/多标签目标的上下文中使用。如果没有,则返回每个班级的分数。否则,这将确定对数据执行的平均类型:

    binary: 只报告 pos_label 指定的类的结果。这仅适用于目标 (y_{true,pred}) 是二进制的。

    micro:通过统计真阳性、假阴性和假阳性的总数来全局计算指标。

    macro:计算每个标签的指标,并找到它们的未加权平均值。这没有考虑标签不平衡。

    weighted:计算每个标签的指标,并找到它们的平均加权支持度(每个标签的真实实例数)。这会改变“宏观”以解决标签不平衡问题;它可能导致 F 分数不在精确率和召回率之间。

    samples:计算每个实例的指标,并找到它们的平均值(仅对不同于 accuracy_score 的多标签分类有意义)

    例子:

    from sklearn.metrics import f1_score
    y_true = [0, 1, 2, 0, 1, 2]
    y_pred = [0, 2, 1, 0, 0, 1]
    f1_score(y_true, y_pred, average='macro')
    0.26...
    f1_score(y_true, y_pred, average='micro')
    0.33...
    f1_score(y_true, y_pred, average='weighted')
    0.26...
    f1_score(y_true, y_pred, average=None)
    array([0.8, 0. , 0. ])
    y_true = [0, 0, 0, 0, 0, 0]
    y_pred = [0, 0, 0, 0, 0, 0]
    f1_score(y_true, y_pred, zero_division=1)
    1.0...
    

    详细学术论文:A Survey on Performance Metrics for Object-Detection Algorithms

    【讨论】:

    • 正如我所写,F1 很清楚。但在我的情况下,它不仅仅是在两个列表上调用 sklearn.metrics.f1_score,因为列表元素本身就是列表,并且子列表的顺序不一定在两个列表中对齐。
    猜你喜欢
    • 2018-08-07
    • 2020-04-05
    • 2020-06-03
    • 2018-07-22
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    相关资源
    最近更新 更多