我正在从我的图像检测器算法中收集结果。基本上我所做的是,从一组图像(尺寸为320 x 480)开始,我会通过它运行一个64x128的滑动窗口,并且还可以在一些预定义的比例下运行。
我理解:
但是真正否定呢?这些真正的否定因为我的分类器给了我负面结果的所有窗口吗?这听起来很奇怪,因为我一次将一个小窗口(64x128)滑动4个像素,并且我在检测中使用了大约8个不同的比例。如果我这样做,那么每张图片都会有很多真正的底片。
或者我是否准备了一组纯负片图像(根本没有物体/人物),我只是滑过,如果每个图像中有一个或多个正面检测,我会将其视为假阴性,反之亦然?
这是一个示例图像(绿色作为基本事实)
答案 0 :(得分:1)
我总是看到以下四个术语:
在您的情况下,如果我理解正确,您正在尝试检测图像中是否有对象。因此,假阴性意味着存在一个对象(结果应为正)但算法未检测到它(因此返回为负)。真正的否定就是算法正确地说明它检查的区域不持有一个对象。
您可以选择忽略负值,但这些可用于进一步训练您的算法(例如;使用查找两者的算法,而不是将未识别的所有内容设置为false)。
答案 1 :(得分:0)
AFAIK,真否定是一种场景,其中图像中存在一个对象,但没有在地面真相注释或模型预测中对其进行标记。
通常,二维物体检测系统仅使用两个数据,即地面真相注释和模型预测。但是,要找到True Negative案例,我们需要寻找地面实况注释的超集,其中包含有关图像中存在的所有类实例的信息(而不仅仅是我们模型中特定的实例)。
例如,拍摄给定的图像;如果我们对出于自动驾驶目的进行对象检测感兴趣,则可以考虑以下两个地面实况注释:
Super Set GT批注
自动驾驶GT注释
有了上述两个地面真相注释,就有可能计算出汉堡和窗户的真否定词。但是,我怀疑是否可以在没有超集注释的情况下计算出真实否定词。
答案 2 :(得分:0)
所有不是fn,fp或tp的矩形都是tn。
因此,真实负片(tn)的数量巨大,但详尽无遗。
上下文:通常,在对象检测中,所有包含tn的度量都将被忽略,因为tn会很多,这使得该度量难以使用。
答案 3 :(得分:0)
真否定词:这是一种背景预测,地面真相没有用于这些位置的框,并且也没有出现在预测中。
假否定词:地面真相有其框,但预测在该位置不包含任何框。
答案 4 :(得分:0)
通常,在对象检测任务中,我们不会寻找真阴性(TN)情况,因为算法告诉我们我们喜欢检测对象(不是非对象候选对象);相反,在分类任务中,我们旨在确定将每个实例视为负面还是正面。因此,自然地,我们将在分类任务中使用True Negative(TN)案例。 此外,还有更好,更兼容的对象检测任务措施。您可以参考平均平均精度(mAP)来评估对象检测算法。 请注意,mAP与简单的平均精度不同。您可以在以下位置找到有关此主题的更多信息: https://medium.com/@jonathan_hui/map-mean-average-precision-for-object-detection-45c121a31173
答案 5 :(得分:-1)
有一个很好的解释here。在维基中解释F1得分,here有助于衡量成功。
我试图编写一个计算F1得分的函数:
/// <param name="realClasses">Class names that exists on the image. A class name may exists more than once.</param>
/// <param name="foundClasses">Predicted class names. A class name may exists more than once.</param>
private static void findPosNeg(List<string> realClasses, List<string> foundClasses, out int truePositive, out int falsePositive, out int falseNegative)
{
Dictionary<string, int> dicReal = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
Dictionary<string, int> dicFound = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
#region fill dictionaries
foreach (string className in realClasses)
{
if (!dicReal.ContainsKey(className))
dicReal[className] = 1;
else
dicReal[className]++;
}
foreach (string className in foundClasses)
{
if (!dicFound.ContainsKey(className))
dicFound[className] = 1;
else
dicFound[className]++;
}
#endregion
truePositive = 0;
falsePositive = 0;
falseNegative = 0;
foreach (string className in dicFound.Keys)
{
if (!dicReal.ContainsKey(className))
falsePositive += dicFound[className];
else
{
int found = dicFound[className];
int real = dicReal[className];
truePositive += Math.Min(found, real);
if (real > found)
falseNegative += real - found;
else if (found > real)
falsePositive += found - real;
}
}
foreach (string className in dicReal.Keys)
if (!dicFound.ContainsKey(className))
falseNegative += dicReal[className];
}
/// <summary>
/// Calculates F1Score ref:https://en.wikipedia.org/wiki/Precision_and_recall
/// </summary>
private static double calc_F1Score(int truePositive, int falsePositive, int falseNegative, out double precision, out double recall)
{
precision = (double)truePositive / ((double)truePositive + (double)falsePositive);
recall = (double)truePositive / ((double)truePositive + (double)falseNegative);
double div = (precision + recall);
return (div != 0d) ? 2d * precision * recall / div : 0d;
}