DIP+CV · Programming Exercise

EP01_03 — 📈 Mean Average Precision (mAP) — Precision-Recall Curve

1.19.6 EP01_03 📈 Mean Average Precision (mAP) — Precision-Recall Curve

In this activity, you will evaluate a binary classifier (e.g., deforestation detection in satellite images, see dgi.inpe.br) using the Precision-Recall curve and the mAP (Mean Average Precision) metric. mAP is standard in competitions such as COCO (Common Objects in Context) and PASCAL VOC (Visual Object Classes) and in YOLO (You Only Look Once) models.

1.19.6.1 🧠 Why is mAP the standard metric?

In EP01_02, you saw that the choice of threshold significantly alters Precision and Recall. The mAP (Mean Average Precision) addresses this: it evaluates the model at multiple thresholds (each threshold should generate a different confusion matrix) and summarizes performance by the area under the Precision-Recall (P-R) curve.

While the F1-Score examines a single equilibrium point, mAP considers the entire curve. The closer to 1.0, the better the detector across all thresholds and classes (e.g., coins of 25, 50, and 1 real).

Metric What it summarizes Limitation
F1-Score P × R balance at a single threshold Depends on the chosen threshold
AP Area under the P-R curve for one class Valid only for a single class
mAP Average of APs across all classes More complex to implement

References: Roboflow — mAP · Explanatory video

1.19.6.2 🔢 How mAP is calculated — step by step

  1. Fixed thresholds (always use this list):

    limiares = [0.00, 0.09, 0.21, 0.31, 0.39, 0.52, 0.60, 0.71, 0.81, 0.89, 1.00]
  2. For each threshold (t), classify the samples: predito = 1 if confiança ≥ t, else 0.
    Compute TP, FP, FN, TN and obtain Precision((t)) and Recall((t)).

  3. Build the P-R curve: pairs (Recall((t)), Precision((t))), ordered by increasing Recall.

  4. Monotonize Precision: \[P_{\text{mono}}[i] = \max_{j \ge i} P[j]\]

  5. Compute the AP (area under the monotonic curve) using the trapezoidal rule (a more accurate approximation than the simple Riemann sum): \[AP = \sum_{i=1}^{m-1} \frac{P_{\text{mono}}[i-1] + P_{\text{mono}}[i]}{2} \cdot (S[i] - S[i-1])\]

  6. mAP = average of the APs across all classes. In this assignment, there is only 1 class, so mAP = AP.

Note

📐 Summary of the difference:
The Riemann sum approximates the area using rectangles, which may underestimate or overestimate. The trapezoidal rule uses trapezoids, reducing error by considering the average of the values at the interval endpoints, and is generally more accurate for piecewise smooth functions, such as the Precision-Recall curve.

1.19.6.3 📋 Task

Read an integer n (number of samples). Then read n lines, each containing: true (0 or 1) and confidence (float 0.0–1.0).

Calculate and print, for the threshold 0.85 (index 9 in the list):

  • Confusion Matrix (TP, FN, FP, TN)
  • Accuracy, Precision, Recall, and F1-Score

Then, for all thresholds, print:

  • Raw Precisions, monotonic Precisions, and Recalls, separated by ,
  • Final mAP

1.19.6.4 📌 Important

  • Fixed threshold for the individual metrics: 0.85
  • Safe division: if the denominator is zero, use 0
  • Formatting: two decimal places
  • Monotonize from back to front
  • Figure 1.13 presents a simulation of this problem

1.19.6.5 📌 Example Run

Input Expected Output
7
0 0.94
1 0.80
1 0.69
0 0.67
1 0.30
1 0.15
1 0.15
# METRICS FOR THRESHOLD 0.85 #
Confusion Matrix:
TP = 0, FN = 5
FP = 1, TN = 1

Evaluation Metrics:
Accuracy: 0.14
Precision: 0.00
Recall: 0.00
F1-Score: 0.00

# METRICS FOR ALL THRESHOLDS #
Precisions: 0.00, 0.00, 0.00, 0.50, 0.50, 0.50, 0.50, 0.50, 0.60, 0.71, 0.71
Monotonic Precisions: 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71, 0.71
Recalls: 0.00, 0.00, 0.00, 0.20, 0.40, 0.40, 0.40, 0.40, 0.60, 1.00, 1.00
mAP: 0.71

1.19.6.6 🐍 Tip for calculating AP (with trapezoid rule)

def calcular_AP(verdades, confiancas, limiares):
    m = len(limiares)
    precisoes = [0.0] * m
    sensibilidades = [0.0] * m
    for i in range(m):
        p, s = calcular_metricas(verdades, confiancas, limiares[i])
        precisoes[m-1-i] = p
        sensibilidades[m-1-i] = s
    prec_mono = precisoes.copy()
    for i in range(m-2, -1, -1):
        if prec_mono[i] < prec_mono[i+1]:
            prec_mono[i] = prec_mono[i+1]
    AP = 0.0
    for i in range(1, m):
        # Trapezoid rule: average of heights times the base
        area_trapezio = (prec_mono[i-1] + prec_mono[i]) / 2.0
        AP += area_trapezio * (sensibilidades[i] - sensibilidades[i-1])
    return precisoes, prec_mono, sensibilidades, AP
📊 Simulator EP01_03: Precision-Sensitivity Curve & mAP mAP & P-S Curve

Edit the samples (true class and confidence) or choose a predefined scenario to visualize the confusion matrix, the P-S curve, and the mAP value in real time.

SAMPLES (TRUE CLASS | CONFIDENCE)
# Truth Confidence
THRESHOLD FOR INDIVIDUAL METRICS
0.85
Thresholds: 0.00 · 0.09 · 0.21 · 0.31 · 0.39 · 0.52 · 0.60 · 0.71 · 0.81 · 0.89 · 1.00
METRICS AT THRESHOLD 0.85
Pred +
Pred −
Real +
TP
0
FN
5
Real −
FP
1
TN
1
Accuracy
0.14
Precision
0.00
Sens.
0.00
F1
0.00
PRECISION-SENSITIVITY CURVE
mAP = 0.71
P-S Curve Monotonic Area (AP)
Threshold Prec. P.mono Sens.
Figure 1.13: Simulator EP01_03: Mean Average Precision (mAP) and P-R Curve
%%writefile EP01_03.cpp
// your solution
Overwriting EP01_03.cpp
TestSuite("EP01_03.cpp").run()
✔️ EP01_03.cases already exists in casos/
📋 5 case(s) loaded from casos/EP01_03.cases

🔍 Testing C++: EP01_03.cpp
⚠️ EP01_03.cpp: Empty file (fewer than 3 lines). Tests skipped.