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.

threshold
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 = "")
  1. 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, noactual
  2. prob ← 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.6
    values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80prob
  3. threshold ← 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.6threshold
  4. predicted ← 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.6threshold
  5. tp ← 2

    4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")
    values this step2tp3 yesactual3 yespredicted
  6. fp ← 1

    5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")
    values this step1fp3 noactual3 yespredicted
  7. label ← 2/1

    6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    values this step2/1label2tp1fp
  8. cat(label, " ", sep = "")

    7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    output2/1
    values this step2/1label
  1. 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, noactual
  2. prob ← 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.5
    values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80prob
  3. threshold ← 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.5threshold
  4. predicted ← 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.5threshold
  5. tp ← 3

    4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")
    values this step3tp3 yesactual4 yespredicted
  6. fp ← 1

    5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")
    values this step1fp3 noactual4 yespredicted
  7. label ← 3/1

    6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    values this step3/1label3tp1fp
  8. cat(label, " ", sep = "")

    7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    output3/1
    values this step3/1label
  1. 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, noactual
  2. prob ← 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.7
    values this step0.90, 0.40, 0.65, 0.55, 0.30, 0.80prob
  3. threshold ← 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.7threshold
  4. predicted ← 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.7threshold
  5. tp ← 1

    4predicted <- ifelse(prob >= threshold, "yes", "no")5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")
    values this step1tp3 yesactual2 yespredicted
  6. fp ← 1

    5tp <- sum(actual == "yes" & predicted == "yes")6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")
    values this step1fp3 noactual2 yespredicted
  7. label ← 1/1

    6fp <- sum(actual == "no" & predicted == "yes")7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    values this step1/1label1tp1fp
  8. cat(label, " ", sep = "")

    7label <- paste(tp, fp, sep = "/")8cat(label, "\n", sep = "")
    output1/1
    values 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`.