This is an R Markdown notebook to evaluate how your classification results reflect the real-world. Using a toy dataset, we explain how to compute common metrics that are often used in accuracy assessment.
Most code has been taken from a blog written by Said Bleik, Shaheen Gauher, Data Scientists at Microsoft, which you may visit here
library(raster)
## Loading required package: sp
Create a vector object with the classification values:
(clas_val <- c(10,10,10,50,50,20,20,20, 30,30,
10,10,10,50,50,20,20,20, 30,30,
40,40,40,50,50,50,50,30, 30,30,
40,40,40,10,10,50,50,20, 20,30,
40,40,40,10,10,20,20,20, 30,30,
60,60,60,10,10,50,50,50, 50,50,
60,60,20,40,50,50,50,50, 50,50,
20,20,20,40,60,60,60,60, 60,30,
20,20,40,40,40,40,60,60, 50,30,
20,20,40,40,40,40,60,60, 50,30))
## [1] 10 10 10 50 50 20 20 20 30 30 10 10 10 50 50 20 20 20 30 30 40 40 40 50 50
## [26] 50 50 30 30 30 40 40 40 10 10 50 50 20 20 30 40 40 40 10 10 20 20 20 30 30
## [51] 60 60 60 10 10 50 50 50 50 50 60 60 20 40 50 50 50 50 50 50 20 20 20 40 60
## [76] 60 60 60 60 30 20 20 40 40 40 40 60 60 50 30 20 20 40 40 40 40 60 60 50 30
Create a raster object:
clas <- raster(ncol=10,nrow=10)
Set the raster values:
values(clas) <- clas_val
Define the raster extent:
extent(clas) <- c(0,10, 0,10)
Plot the classsified raster:
plot(clas)
text(clas)
Define the reference values (some people refer to these values as the ground truth):
(ref_val <- c(10,10,50,50,50,20,20,30, 30,30,
10,10,10,50,50,20,20,30, 30,30,
40,40,40,50,50,50,50,20, 30,30,
40,40,40,10,10,50,50,20, 30,30,
40,40,40,10,10,20,20,20, 20,20,
60,60,60,40,10,50,50,50, 50,50,
60,60,60,40,10,50,50,50, 50,50,
20,20,60,60,60,60,60,60, 50,30,
20,20,40,40,40,60,60,60, 30,30,
20,20,40,40,40,40,50,50, 50,50))
## [1] 10 10 50 50 50 20 20 30 30 30 10 10 10 50 50 20 20 30 30 30 40 40 40 50 50
## [26] 50 50 20 30 30 40 40 40 10 10 50 50 20 30 30 40 40 40 10 10 20 20 20 20 20
## [51] 60 60 60 40 10 50 50 50 50 50 60 60 60 40 10 50 50 50 50 50 20 20 60 60 60
## [76] 60 60 60 50 30 20 20 40 40 40 60 60 60 30 30 20 20 40 40 40 40 50 50 50 50
Copy the raster:
ref <- clas
Set raster reference values:
values(ref) <- ref_val
Plot the reference raster:
plot(ref)
text(ref)
(accmat <- table("pred" = clas_val, "ref" = ref_val))
## ref
## pred 10 20 30 40 50 60
## 10 10 0 0 1 1 0
## 20 0 14 3 0 0 2
## 30 0 3 9 0 1 0
## 40 0 0 0 17 0 2
## 50 1 0 1 0 21 0
## 60 0 0 0 0 3 11
Overall accuracy is:
(OA <- sum(diag(accmat)) / sum(accmat) * 100)
## [1] 82
Next we will define some basic variables that will be needed to compute the evaluation metrics:
n = sum(accmat) # number of instances
nc = nrow(accmat) # number of classes
diag = diag(accmat) # number of correctly classified instances per class
rowsums = apply(accmat, 1, sum) # number of instances per class
colsums = apply(accmat, 2, sum) # number of predictions per class
p = rowsums / n # distribution of instances over the actual classes
q = colsums / n # distribution of instances over the predicted classes
(accuracy = sum(diag) / n)
## [1] 0.82
precision = diag / colsums
recall = diag / rowsums
f1 = 2 * precision * recall / (precision + recall)
data.frame(precision, recall, f1)
The per-class metrics can be averaged over all the classes resulting in macro-averaged precision, recall and F-1.
(macroPrecision = mean(precision))
## [1] 0.8183997
(macroRecall = mean(recall))
## [1] 0.8093296
(macroF1 = mean(f1))
## [1] 0.8123889