Model Evaluation
Confusion Counts
Thresholded Predictions
Classification evaluation compares predicted labels with actual labels. A probability threshold changes those counts.
Program
Play the script to change the threshold and see true-positive and false-positive counts.
confusion_counts.R
Replay: real traced execution (multi-file project)
actual <- c("yes", "no", "yes", "yes", "no", "no")
prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)
threshold <- 0.6
predicted <- ifelse(prob >= threshold, "yes", "no")
tp <- sum(actual == "yes" & predicted == "yes")
fp <- sum(actual == "no" & predicted == "yes")
label <- paste(tp, fp, sep = "/")
cat(label, "\n", sep = "")
actual <- c("yes", "no", "yes", "yes", "no", "no")
prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)
threshold <- 0.5
predicted <- ifelse(prob >= threshold, "yes", "no")
tp <- sum(actual == "yes" & predicted == "yes")
fp <- sum(actual == "no" & predicted == "yes")
label <- paste(tp, fp, sep = "/")
cat(label, "\n", sep = "")
actual <- c("yes", "no", "yes", "yes", "no", "no")
prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)
threshold <- 0.7
predicted <- ifelse(prob >= threshold, "yes", "no")
tp <- sum(actual == "yes" & predicted == "yes")
fp <- sum(actual == "no" & predicted == "yes")
label <- paste(tp, fp, sep = "/")
cat(label, "\n", sep = "")
actual ← yes, no, yes, yes, no, no
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)values this stepyes, no, yes, yes, no, noactualprob ← 0.90, 0.40, 0.65, 0.55, 0.30, 0.80
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.6values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80probthreshold ← 0.6
2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.64predicted <- ifelse(prob >= threshold, "yes", "no")values this step0.6thresholdpredicted ← yes, no, yes, no, no, yes
3threshold <- 0.64predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")values this stepyes, no, yes, no, no, yespredicted6 scoresprob0.6thresholdtp ← 2
4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")values this step2tp3 yesactual3 yespredictedfp ← 1
5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")values this step1fp3 noactual3 yespredictedlabel ← 2/1
6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")values this step2/1label2tp1fpcat(label, " ", sep = "")
7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")output2/1values this step2/1label
actual ← yes, no, yes, yes, no, no
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)values this stepyes, no, yes, yes, no, noactualprob ← 0.90, 0.40, 0.65, 0.55, 0.30, 0.80
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.5values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80probthreshold ← 0.5
2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.54predicted <- ifelse(prob >= threshold, "yes", "no")values this step0.5thresholdpredicted ← yes, no, yes, yes, no, yes
3threshold <- 0.54predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")values this stepyes, no, yes, yes, no, yespredicted6 scoresprob0.5thresholdtp ← 3
4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")values this step3tp3 yesactual4 yespredictedfp ← 1
5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")values this step1fp3 noactual4 yespredictedlabel ← 3/1
6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")values this step3/1label3tp1fpcat(label, " ", sep = "")
7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")output3/1values this step3/1label
actual ← yes, no, yes, yes, no, no
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)values this stepyes, no, yes, yes, no, noactualprob ← 0.90, 0.40, 0.65, 0.55, 0.30, 0.80
1actual <- c("yes", "no", "yes", "yes", "no", "no")2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.7values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80probthreshold ← 0.7
2prob <- c(0.90, 0.40, 0.65, 0.55, 0.30, 0.80)3threshold <- 0.74predicted <- ifelse(prob >= threshold, "yes", "no")values this step0.7thresholdpredicted ← yes, no, no, no, no, yes
3threshold <- 0.74predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")values this stepyes, no, no, no, no, yespredicted6 scoresprob0.7thresholdtp ← 1
4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")values this step1tp3 yesactual2 yespredictedfp ← 1
5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")values this step1fp3 noactual2 yespredictedlabel ← 1/1
6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")values this step1/1label1tp1fpcat(label, " ", sep = "")
7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")output1/1values this step1/1label
threshold
`prob >= threshold` turns probabilities into predicted labels.
true positive
`tp` counts rows where actual and predicted labels are both `yes`.
false positive
`fp` counts `no` rows predicted as `yes`.