Salta el contingut

Avaluació dels models

Acabem d’acabar d’entrenar un model, hem aplicat filtres per millorar-ne les deteccions i hem observat que és capaç de detectar correctament pomes, taronges i peres. Tanmateix, encara no sabem fins a quin punt el model funciona realment bé.

En aquesta lliçó, aprendrem com avaluar models de detecció d’objectes. Explorarem el significat de cada mètrica d’avaluació i què revela sobre el rendiment del model. Aquesta comprensió ens ajudarà a avaluar la qualitat real del nostre model. A més, ens permetrà comparar múltiples models per identificar el millor, guiant-nos en la selecció dels paràmetres més adequats per entrenar futurs models.

Quan entrenem models, com vam fer en la lliçó anterior, es crea automàticament una carpeta per a cada execució a la ruta: runs/detection/created_folder, normalment anomenada " train" seguida d’un identificador, tret que s’hagi especificat un nom personalitzat a la configuració.

Aquesta carpeta conté tots els plots i gràfics que comentarem en aquesta lliçó, juntament amb un fitxer results.csv que emmagatzema les mètriques d’avaluació. Dins d’aquest directori, també hi ha una subcarpeta anomenada weights on es desen els pesos del model.

Tingueu en compte que els gràfics mostrats en aquesta lliçó poden diferir lleugerament dels de la carpeta d’entrenament, ja que són versions simplificades pensades per ajudar-vos a entendre els conceptes amb més claredat.

Afegir la ruta del mòdul d’ajuda

Primer, afegim el mòdul d’ajuda:

addpath('help-module');

Carregar un model

Amb aquest codi, estem carregant el model entrenat en la lliçó anterior.

datasetFolder = "datasets/fruits_3_4998/";    
modelPath = fullfile(pwd, 'runs', 'detect', 'train', 'weights');
configFile  = datasetFolder + "data.yaml";

disp("Loading Model....");
Loading Model....
model = utils.loadModel(modelPath, configFile);
disp("Model loaded!");
Model loaded!

Predir sobre el conjunt de validació

En aprenentatge automàtic, no n’hi ha prou que un model funcioni bé amb les dades que ha vist durant l’entrenament. Si avaluem el model utilitzant aquestes mateixes dades, correm el risc de sobreestimar-ne el rendiment real. Això passa perquè el model podria haver "memoritzat" les respostes en comptes d’haver après realment a generalitzar.

Per determinar si un model ha après realment, cal provar-lo amb dades noves que no hagi vist abans. Això es coneix com a conjunt de validació. Avaluar el model sobre aquestes dades no vistes ens dona una idea molt més realista de com es comportarà en situacions del món real.

En el codi següent, utilitzem les dades de validació del nostre dataset per obtenir les prediccions del model sobre aquest conjunt. En les seccions següents, utilitzarem aquestes prediccions per calcular les mètriques de rendiment del model.

splitFolder = datasetFolder + "val";
classNames =  utils.ReadClassNames(configFile);
disp("Calculating predictions...")
Calculating predictions...
predictions = utils.getPredictions(model, splitFolder, classNames);
disp("Done!")
Done!

calculateIoU

En aquesta secció, incorporem la funció calculateIoU que vam implementar en la lliçó anterior de Postprocessament.

function iou = calculateIoU(b1, b2)
    % Calculates the Intersection over Union (IoU) between two bounding boxes.
    %
    % Inputs:
    %   b1 - 1x4 vector representing the first bounding box [x1 y1 x2 y2]
    %   b2 - 1x4 vector representing the second bounding box [x1 y1 x2 y2]
    %
    % Output:
    %   iou - Scalar value between 0 and 1 representing the IoU.
    %         IoU = 0 if there is no overlap.
    %         IoU = 1 if boxes are identical.
    x1 = max(b1(1), b2(1));
    y1 = max(b1(2), b2(2));
    x2 = min(b1(3), b2(3));
    y2 = min(b1(4), b2(4));
    inter = max(0, x2-x1) * max(0, y2-y1);
    area1 = (b1(3)-b1(1))*(b1(4)-b1(2));
    area2 = (b2(3)-b2(1))*(b2(4)-b2(2));
    union = area1 + area2 - inter;
    if union>0
        iou = inter/union;
    else
        iou = 0;
    end
end

Matriu de confusió

Una matriu de confusió resumeix amb quina freqüència el model prediu correctament o incorrectament cada classe per als objectes detectats.

Cada fila representa la classe real, i cada columna representa la classe predita.

La diagonal conté les prediccions correctes (classe predita = classe real).

Els valors fora de la diagonal indiquen confusions entre classes (per exemple, ha predit "apple" quan en realitat era "pear").

Per construir la matriu, només es consideren les deteccions amb prou confiança i IoU:

  • True Positive (TP): confiança > llindar i IoU > llindar.
  • False Positive (FP): confiança > llindar i IoU < llindar.
  • False/True Negative (FN/TN): confiança < llindar, és a dir, el model no ha detectat l’objecte.

La matriu ajuda a identificar quines classes es confonen més sovint i avaluar el rendiment per classe.

És útil per analitzar errors a nivell de classe i avaluar el rendiment del model per classe.

El codi següent calcula la matriu de confusió per al model utilitzant la funció que heu creat abans:

classNames =  utils.ReadClassNames(configFile);
confidenceThreshold = 0.25;

confMat = utils.computeConfusionMatrix(predictions, classNames, confidenceThreshold, @calculateIoU);

El codi següent mostra la matriu de confusió:

allClassNames = [classNames(:); {'background'}];
utils.displayConfusionMatrix(confMat, allClassNames);

figure_0.png

Exercici 2 - Extreure TP, FP, FN de cada classe

Implementa una funció que extregui els valors de true positive, false positive i false negative per a cada classe.

function [TP, FP, FN] = extractConfusionMatrixValues(confusionMat)
    % Extracts True Positive, False Positive, and False Negative values for each class
    %
    % Input:
    %   confusionMat - Square confusion matrix where rows represent actual classes
    %                  and columns represent predicted classes.
    %
    % Outputs:
    %   TP - Vector of true positives per class (correct predictions)
    %   FP - Vector of false positives per class (incorrect predictions assigned to the class)
    %   FN - Vector of false negatives per class (missed detections of the class)

    numClasses = size(confusionMat, 1);
    TP = zeros(numClasses, 1);
    FP = zeros(numClasses, 1);
    FN = zeros(numClasses, 1);


end
function [TP, FP, FN] = extractConfusionMatrixValues(confusionMat)
    % Extracts True Positive, False Positive, and False Negative values for each class
    %
    % Input:
    %   confusionMat - Square confusion matrix where rows represent actual classes
    %                  and columns represent predicted classes.
    %
    % Outputs:
    %   TP - Vector of true positives per class (correct predictions)
    %   FP - Vector of false positives per class (incorrect predictions assigned to the class)
    %   FN - Vector of false negatives per class (missed detections of the class)

    numClasses = size(confusionMat, 1);
    TP = zeros(numClasses, 1);
    FP = zeros(numClasses, 1);
    FN = zeros(numClasses, 1);
    for i = 1:numClasses
        TP(i) = confusionMat(i, i);
        FP(i) = sum(confusionMat(i, :)) - TP(i);
        FN(i) = sum(confusionMat(:, i)) - TP(i);
    end
end

El codi següent genera taules de true positives, false positives i false negatives per visualitzar els valors extrets per a cada classe.

[TP, FP, FN] = extractConfusionMatrixValues(confMat);

tableTP = table(string(allClassNames), TP, 'VariableNames', {'ClassName', 'True Positive'});
tableFP = table(string(allClassNames), FP, 'VariableNames', {'ClassName', 'False Positive'});
tableFN = table(string(allClassNames), FN, 'VariableNames', {'ClassName', 'False Negative'});

disp(tableTP)
     ClassName      True Positive
    ____________    _____________

    "apple"              150     
    "orange"              46     
    "pear"               155     
    "background"           0     
disp(tableFP)
     ClassName      False Positive
    ____________    ______________

    "apple"              221      
    "orange"             137      
    "pear"               439      
    "background"          31      
disp(tableFN)
     ClassName      False Negative
    ____________    ______________

    "apple"                3      
    "orange"              38      
    "pear"                34      
    "background"         753      

Precisió

La precisió mesura l’exactitud del model per a una classe determinada. Es defineix com la proporció de true positives (TP) respecte al nombre total de positius predits (TP + FP).

Matemàticament: \(\textrm{Precision}=\frac{\textrm{TP}}{\textrm{TP}+\textrm{FP}}\)

Hi ha diferents maneres de calcular la precisió:

  • Precisió per classe: un valor per a cada classe.
  • Precisió global: precisió global en totes les classes.
  • Precisió equilibrada (mitjana macro): mitjana de la precisió per classe (excloent el background).

El rang de la precisió va de 0 a 1:

  • Precisió = 1 vol dir que cada predicció positiva era correcta.
  • Precisió = 0 vol dir que cap de les prediccions positives era correcta.

Exercici 3 - Calcular la precisió del model

En aquest exercici, has d’implementar una funció de MATLAB per calcular la precisió per a cada classe i la precisió global (precisió mitjana macro).

Recorda

  • (/) és divisió matricial.
  • (./) és divisió element a element
    function precision = precisionFunc(predictions, classNames, confidenceThreshold, calculateIoU)   
     % Computes per-class and macro-averaged precision from predictions.
        % Output:
        %   precision            - Row vector of precision values:
        %                          * One value per class (same order as classNames).
        %                          * One additional final value representing the macro-averaged
        %                            precision (mean of per-class precisions, excluding background).
        confMat = utils.computeConfusionMatrix(predictions, classNames, confidenceThreshold, calculateIoU);
        [TP, FP, FN] = extractConfusionMatrixValues(confMat);
    
    
        % Handle NaNs if any class has 0 TP+FP
        precisionMacro = mean(precisionWithoutBG(~isnan(precisionWithoutBG)));
        precision = [precisionWithoutBG; precisionMacro];
    
    end
    

Solució

function precision = precisionFunc(predictions, classNames, confidenceThreshold, calculateIoU)   
 % Computes per-class and macro-averaged precision from predictions.
    % Output:
    %   precision            - Row vector of precision values:
    %                          * One value per class (same order as classNames).
    %                          * One additional final value representing the macro-averaged
    %                            precision (mean of per-class precisions, excluding background).
    confMat = utils.computeConfusionMatrix(predictions, classNames, confidenceThreshold, calculateIoU);
    [TP, FP, FN] = extractConfusionMatrixValues(confMat);

    denom = (TP + FP);

    precision = TP ./ denom;
    totalTP = sum(TP);
    total = totalTP + sum(FP);

    if total == 0
        total = NaN;
    end

    precisionWithoutBG = precision(1:end-1);

    % Handle NaNs if any class has 0 TP+FP
    precisionMacro = mean(precisionWithoutBG(~isnan(precisionWithoutBG)));
    precision = [precisionWithoutBG; precisionMacro];

end

Taula de precisió

confidenceThreshold = 0.5;
precision = precisionFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
metricsClassNames = string([classNames(:); {'Overall'}]);
precisionTable = table(metricsClassNames, precision, 'VariableNames', {'ClassName', 'Precision'});
disp(precisionTable)
    ClassName    Precision
    _________    _________

    "apple"        0.4698 
    "orange"      0.24444 
    "pear"        0.23604 
    "Overall"     0.31676 

Recall

El recall mesura la sensibilitat del model per a una classe determinada. Es defineix com la proporció de true positives (TP) respecte al nombre total de positius reals (TP + FN)

Matemàticament: \(\textrm{Recall}=\frac{\textrm{TP}}{\textrm{TP}+\textrm{FN}}\)

Igual que amb la precisió, hi ha diferents maneres de calcular el recall:

  • Recall per classe: un valor per a cada classe.
  • Recall global: recall global en totes les classes.
  • Recall equilibrat (mitjana macro): mitjana del recall per classe (excloent el background).

El rang del recall va de 0 a 1:

  • Recall = 1 vol dir que el model ha trobat totes les mostres positives reals.
  • Recall = 0 vol dir que el model ha perdut totes les positives reals.

Exercici 4 - Calcular el recall del model

En aquest exercici, has d’implementar una funció de MATLAB per calcular el recall per a cada classe i el recall global (recall mitjà macro).

Recorda

  • (/) és divisió matricial.
  • (./) és divisió element a element
    function recall = recallFunc(predictions, classNames, confidenceThreshold, calculateIoU)
        % Computes per-class and macro-averaged recall from predictions.
        % Output:
        %   recall - Row vector of recall per class, with an additional entry
        %            at the end representing the macro-averaged recall.
    
        confMat = utils.computeConfusionMatrix(predictions, classNames, confidenceThreshold, calculateIoU);
        [TP, FP, FN] = extractConfusionMatrixValues(confMat);
    
        % Handle NaNs if any class has 0 TP+FN
        recallMacro = mean(recallWithoutBG(~isnan(recallWithoutBG)));
        recall = [recallWithoutBG; recallMacro];
    end
    
function recall = recallFunc(predictions, classNames, confidenceThreshold, calculateIoU)
    % Computes per-class and macro-averaged recall from predictions.
    % Output:
    %   recall - Row vector of recall per class, with an additional entry
    %            at the end representing the macro-averaged recall.

    confMat = utils.computeConfusionMatrix(predictions, classNames, confidenceThreshold, calculateIoU);
    [TP, FP, FN] = extractConfusionMatrixValues(confMat);

    denom = (TP + FN);
    recall = TP ./ denom;

    totalTP = sum(TP);
    total = totalTP + sum(FN);

    if total == 0
        total = NaN;
    end

    recallWithoutBG = recall(1:end-1);

    % Handle NaNs if any class has 0 TP+FN
    recallMacro = mean(recallWithoutBG(~isnan(recallWithoutBG)));
    recall = [recallWithoutBG; recallMacro];
end

Taula de recall

confidenceThreshold = 0.5;
recall = recallFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
metricsClassNames = string([classNames(:); {'Overall'}]);
recallTable = table(metricsClassNames, recall, 'VariableNames', {'ClassName', 'Recall'});
disp(recallTable)
    ClassName    Recall 
    _________    _______

    "apple"      0.91503
    "orange"     0.52381
    "pear"       0.69312
    "Overall"    0.71065

Exercici 5 - Precisió/Recall

En aquest exercici, has de canviar el valor de confidenceThreshold i respondre les preguntes següents.

confidenceThreshold = 0.5;
precision = precisionFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
recall = recallFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
metricsClassNames = string([classNames(:); {'Overall'}]);
metricsTable = table(metricsClassNames, precision(:), recall(:), ...
    'VariableNames', {'ClassName', 'Precision', 'Recall'});
disp(metricsTable)
    ClassName    Precision    Recall 
    _________    _________    _______

    "apple"        0.4698     0.91503
    "orange"      0.24444     0.52381
    "pear"        0.23604     0.69312
    "Overall"     0.31676     0.71065

Pregunta:

Què has observat en canviar el valor de confidenceThreshold? Per què passa això?

Resposta:

En canviar el valor de confidenceThreshold, he observat un compromís entre precisió i recall. Concretament:

  • Augmentar el llindar de confiança ha provocat una precisió més alta però un recall més baix. Això passa perquè el model es torna més selectiu i només fa prediccions quan està més segur. Com a resultat, redueix els false positives, però també perd alguns true positives.
  • Disminuir el llindar de confiança ha augmentat el recall, però ha reduït la precisió, ja que el model fa més prediccions, capturant més true positives però també augmentant el nombre de false positives.

Aquest comportament reflecteix el típic compromís precisió-recall, en què millorar una mètrica sovint comporta una disminució de l’altra. Trobar l’equilibri adequat depèn dels requisits específics de l’aplicació.

F1-Score

Com hem observat en l’exercici anterior, hi ha un compromís entre precisió i recall. Per resumir ambdues mètriques en un únic valor, utilitzem l’F1-score, que equilibra les dues.

L’F1-score és la mitjana harmònica de precisió i recall, i es defineix com:

$$ {\textrm{f1}}_{\textrm{score}} =\frac{2\cdot \textrm{presicion}\cdot \textrm{recall}}{\textrm{precision}+\textrm{recall}} $$

Igual que la precisió i el recall, l’F1-score es pot calcular de diverses maneres:

  • F1-score per classe: un valor per a cada classe.
  • F1-score global: rendiment global en totes les classes.
  • F1-score equilibrat (mitjana macro): mitjana dels F1-scores per classe (excloent la classe background, si n’hi ha).

El rang de l’F1-score va de 0 a 1 :

  • F1-score = 1 vol dir precisió i recall perfectes.
  • F1-score = 0 vol dir que la precisió o el recall és zero, és a dir, el model falla d’alguna manera clau.

Un bon F1-score indica un bon equilibri entre evitar false positives (alta precisió) i no perdre positius (alt recall).

Exercici 6 - Calcular l’F1-Score del model

En aquest exercici, has d’implementar una funció de MATLAB per calcular:

  • L’F1-score per a cada classe, i
  • L’F1-score global utilitzant mitjana macro.

Per fer-ho, reutilitzaràs les funcions precisionFunc i recallFunc que has definit abans.

function f1 = f1ScoreFunc(predictions, classNames, confidenceThreshold, calculateIoU)
    % Computes per-class and macro-averaged F1-score using recall and precision.
    % Output:
    %   f1 - Row vector of F1-score per class, with an additional entry
    %        at the end representing the macro-averaged F1-score.

    % Get precision and recall
    recall = recallFunc(predictions, classNames, confidenceThreshold, calculateIoU);
    precision = precisionFunc(predictions, classNames, confidenceThreshold, calculateIoU);



    % Concatenate per-class F1 and macro
    f1 = [f1PerClass; f1Macro];
end
function f1 = f1ScoreFunc(predictions, classNames, confidenceThreshold, calculateIoU)
    % Computes per-class and macro-averaged F1-score using recall and precision.
    % Output:
    %   f1 - Row vector of F1-score per class, with an additional entry
    %        at the end representing the macro-averaged F1-score.

    % Get precision and recall
    recall = recallFunc(predictions, classNames, confidenceThreshold, calculateIoU);
    precision = precisionFunc(predictions, classNames, confidenceThreshold, calculateIoU);

    % Remove macro values (last element)
    recallPerClass = recall(1:end-1);
    precisionPerClass = precision(1:end-1);

    % Compute F1-score per class
    f1PerClass = 2 * (precisionPerClass .* recallPerClass) ./ ...
                 (precisionPerClass + recallPerClass);

    % Handle NaNs where precision + recall = 0
    f1PerClass(isnan(f1PerClass)) = NaN;

    % Macro-averaged F1 (excluding background and NaNs)
    f1Macro = mean(f1PerClass(~isnan(f1PerClass)));

    % Concatenate per-class F1 and macro
    f1 = [f1PerClass; f1Macro];
end

Taula de l’F1-Score

confidenceThreshold = 0.53;
precision = precisionFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
recall = recallFunc(predictions, classNames, confidenceThreshold, @calculateIoU);
f1 = f1ScoreFunc(predictions, classNames, confidenceThreshold, @calculateIoU);

metricsClassNames = string([classNames(:); {'Overall'}]);
metricsTable = table(metricsClassNames, precision(:), recall(:), f1(:), ...
    'VariableNames', {'ClassName', 'Precision', 'Recall', 'F1-Score'});
disp(metricsTable)
    ClassName    Precision    Recall     F1-Score
    _________    _________    _______    ________

    "apple"       0.48929     0.89542    0.63279 
    "orange"      0.24852         0.5    0.33202 
    "pear"        0.25097     0.68254      0.367 
    "Overall"     0.32959     0.69265    0.44394 

Corbes

En aquesta secció, presentem les corbes següents: precisió vs. confiança, recall vs. confiança i F1-score vs. confiança. Aquests gràfics proporcionen una visualització més clara del compromís entre precisió i recall comentat a l’Exercici 5, i il·lustren com l’F1-score equilibra aquestes dues mètriques.

Corba Precisió / Confiança

El codi següent genera la corba precisió vs confiança:

utils.plotMetric('Precision', predictions, classNames, @precisionFunc, @calculateIoU); 
Computing plot...
     1    21

figure_1.png

Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.
Warning: Graphics timeout occurred. To share details of this issue with MathWorks technical support, please include that this is an unresponsive graphics client with your service request.

La imatge següent mostra exemples de com pot ser la corba precisió vs confiança en escenaris bons, regulars i dolents.

image_0.png

Corba Recall / Confiança

El codi següent genera la corba recall vs confiança:

utils.plotMetric('Recall', predictions, classNames, @recallFunc, @calculateIoU);
Computing plot...
     1    21

figure_2.png

La imatge següent mostra exemples de com pot ser la corba recall vs confiança en escenaris bons, regulars i dolents.

image_1.png

Corba F1-Score / Confiança

El codi següent genera la corba f1-score vs confiança:

utils.plotMetric('F1-score', predictions, classNames, @f1ScoreFunc, @calculateIoU);  
Computing plot...
     1    21

figure_3.png

La imatge següent mostra exemples de com pot ser la corba f1-score vs confiança en escenaris bons, regulars i dolents.

image_2.png

Corba Precisió / Recall i àrea sota la corba

En aquesta secció, utilitzarem les funcions integrades de MATLAB per calcular i visualitzar la corba precisió-recall.

Tot i que ho podríem implementar utilitzant les nostres pròpies funcions, aquesta és una bona oportunitat per familiaritzar-nos amb les utilitats d’avaluació de detecció d’objectes de MATLAB.

Carregar el dataset

Comencem carregant les dades de validació, que inclouen rutes d’imatges i bounding boxes:

data = load("fruitsValidationData.mat");
validationData = data.validationData;
imds = imageDatastore(validationData.imageFilename);
blds = boxLabelDatastore(validationData(:,2:end));
Loading Model....
Model loaded!

Executar la inferència

Utilitza el model per generar prediccions sobre les imatges de validació:

results = detect(model,imds,Threshold=0.01);

Avaluar les prediccions del model

metrics = evaluateObjectDetection(results, blds);

metrics = evaluateObjectDetection(results,blds);

Calcular i visualitzar la corba Precisió-Recall

La imatge següent mostra exemples de com pot ser la corba precisió vs recall en escenaris bons, regulars i dolents.

image_3.png

Extraiem els vectors de recall, precisió i score:

[recall,precision,scores] = precisionRecall(metrics);

Ara representem la corba precisió-recall per a una classe específica (per exemple, la primera):

figure
plot(recall{3},precision{3})
grid on
title("Precision vs Recall");
xlabel("Recall");
ylabel("Precision");

figure_4.png

Resum

En aquest punt, hem tractat el següent:

  • Què és la IoU (Intersection over Union).
  • Com funciona la matriu de confusió en detecció d’objectes.
  • Com calcular precisió, recall i F1-score.
  • Com representar precisió, recall i F1-score vs. confiança.
  • Com calcular i interpretar corbes precisió vs. recall.

Tanmateix, les mètriques que hem calculat fins ara no capturen completament com de ben localitzades estan les bounding boxes. Per a aquest propòsit, en detecció d’objectes s’utilitza una mètrica més completa.

Mean Average Precision (mAP)

La mean Average Precision (mAP) és una de les mètriques més habituals en detecció d’objectes per resumir tant la precisió com la qualitat de localització.

La mAP es calcula de la manera següent:

  1. Partint de la matriu de confusió, es calculen la precisió i el recall del model per a cada classe.
  2. Variant el llindar de decisió, es genera la corba precisió-recall corresponent per a cada classe, juntament amb la seva àrea sota la corba (AUC). L’àrea sota cada corba precisió-recall es coneix com a Average Precision (AP).
  3. Finalment, la mean Average Precision (mAP) es calcula fent la mitjana dels valors d’AP de totes les classes.

mAP@50 vol dir que l’AP es calcula amb un llindar d’IoU de 0.50.

mAP@95 fa referència o bé a l’AP calculada amb un llindar d’IoU de 0.95, o més habitualment, a la mitjana d’AP calculada a través de múltiples llindars d’IoU des de 0.50 fins a 0.95 en increments de 0.05.

El rang de la mAP va de 0 a 1:

  • mAP = 1 vol dir que el model té una precisió i una localització perfectes en totes les classes.
  • mAP = 0 vol dir que el model falla completament a l’hora de detectar objectes correctament.

En el fragment de codi següent, mostrem l’Average Precision per a cada classe amb un llindar d’IoU de 0.50:

ap = averagePrecision(metrics);
disp("ap")
ap
disp(ap)
    0.2110
    0.3773
    0.2517
disp("mAP") 
mAP
disp(sum(ap)/3)
    0.2800

Podem mostrar mètriques resum per a tot el dataset i per a classes individuals utilitzant:

[summaryDataset,summaryClass] = summarize(metrics);
disp(summaryDataset)
    NumObjects    mAPOverlapAvg    mAP0.5 
    __________    _____________    _______

       426           0.27999       0.27999
disp(summaryClass)
              NumObjects    APOverlapAvg     AP0.5 
              __________    ____________    _______

    apple        153          0.21101       0.21101
    orange        84          0.37729       0.37729
    pear         189          0.25167       0.25167