DATA 607 – Week 2B: Classification Metrics

Author

Professor Reginald Dorcely

Published

October 25, 2026

Introduction

This Code Base assignment demonstrates how to evaluate a binary classification model in R. I use the built-in iris dataset to classify flowers as virginica (positive class, 1) or versicolor (negative class, 0). Logistic regression estimates probabilities from sepal length and sepal width. I then evaluate out-of-sample predictions using a confusion matrix and five classification metrics.

Data Preparation and Model

# Load and prepare the data
data(iris)
flowers <- subset(iris, Species %in% c("versicolor", "virginica"))
flowers$Target <- ifelse(flowers$Species == "virginica", 1L, 0L)

# Stratified training/testing split, approximately 70/30
set.seed(123)
train_id <- unlist(lapply(split(seq_len(nrow(flowers)), flowers$Target),
                          function(ids) sample(ids, floor(0.7 * length(ids)))))
train <- flowers[train_id, ]
test <- flowers[-train_id, ]

# Fit logistic regression model (sepal predictors have more overlap)
model <- glm(Target ~ Sepal.Length + Sepal.Width,
             data = train, family = binomial())
summary(model)

Call:
glm(formula = Target ~ Sepal.Length + Sepal.Width, family = binomial(), 
    data = train)

Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept)  -13.4001     3.7084  -3.613 0.000302 ***
Sepal.Length   2.2560     0.6719   3.358 0.000785 ***
Sepal.Width   -0.2715     1.0883  -0.249 0.803001    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 97.041  on 69  degrees of freedom
Residual deviance: 73.443  on 67  degrees of freedom
AIC: 79.443

Number of Fisher Scoring iterations: 4
# Predict probabilities and binary outcomes at a 0.50 threshold
test$probability <- predict(model, newdata = test, type = "response")
test$predicted <- ifelse(test$probability >= 0.5, 1L, 0L)

Confusion Matrix and Classification Metrics

cm <- table(
  Actual = factor(test$Target, levels = c(0, 1)),
  Predicted = factor(test$predicted, levels = c(0, 1))
)
cm
      Predicted
Actual  0  1
     0 10  5
     1  8  7
TN <- unname(cm["0", "0"])
FP <- unname(cm["0", "1"])
FN <- unname(cm["1", "0"])
TP <- unname(cm["1", "1"])

safe_divide <- function(a, b) if (is.na(b) || b == 0) NA_real_ else as.numeric(a / b)
accuracy <- safe_divide(TP + TN, sum(cm))
precision <- safe_divide(TP, TP + FP)
recall <- safe_divide(TP, TP + FN)
specificity <- safe_divide(TN, TN + FP)
f1 <- safe_divide(2 * TP, 2 * TP + FP + FN)

metrics <- data.frame(
  Metric = c("Accuracy", "Precision", "Recall (Sensitivity)",
             "Specificity", "F1-Score"),
  Value = round(c(accuracy, precision, recall, specificity, f1), 3)
)
knitr::kable(metrics, caption = "Classification performance on the test set")
Classification performance on the test set
Metric Value
Accuracy 0.567
Precision 0.583
Recall (Sensitivity) 0.467
Specificity 0.667
F1-Score 0.519

Interpretation of Results

The confusion matrix shows how many flowers were correctly and incorrectly classified. A true positive (TP) is a virginica flower correctly predicted as virginica; a true negative (TN) is a versicolor flower correctly predicted as versicolor. A false positive (FP) is versicolor incorrectly classified as virginica; a false negative (FN) is virginica incorrectly classified as versicolor.

The test set contains 30 flowers. The model correctly classified 17 of them, giving an accuracy of 56.7%. Its precision is 58.3%, meaning that this proportion of predicted virginica flowers were actually virginica. Its recall is 46.7%, representing the proportion of all actual virginica flowers it detected. Its specificity is 66.7%, indicating how well it identified versicolor. The F1-score is 0.519, summarizing the balance of precision and recall.

These metrics should be considered together: accuracy summarizes overall correctness, while precision and recall reveal different consequences of positive-class errors. The results describe performance on this particular held-out sample, not guaranteed performance on every future observation.

Reflection

This assignment helped me distinguish classification from predicting a continuous outcome. Logistic regression predicts the probability of membership in a category, and a decision threshold converts that probability into a predicted class. The confusion matrix makes the consequences of correct and incorrect predictions visible.

I also encountered warnings in my initial model: “algorithm did not converge” and “fitted probabilities numerically 0 or 1 occurred.” The original task—classifying setosa from other iris flowers—can produce complete or near-complete separation. I revised the example to compare versicolor with virginica, using two overlapping sepal measurements. This experience taught me to investigate warnings and reconsider the modeling setup rather than merely hiding messages. Although the revised specification reduces separation risk, convergence must still be checked if the model is changed.

Connection to Educational Research

As a mathematics educator and educational researcher, I can see how classification metrics apply to models designed to identify students who may need academic support. In such an application, a false negative could mean overlooking an at-risk student, while a false positive could mean offering unnecessary intervention to a student not actually at risk. Recall is important when missing a student in need has serious consequences; precision also matters for making responsible use of limited support resources. Predictive classifications should inform, not replace, human judgment, and require validation and fairness checks before being used for student decisions.

Conclusion

Week 2B showed me that model evaluation involves more than checking overall accuracy. A confusion matrix, precision, recall, specificity, and F1-score help assess different dimensions of classification performance. I also learned to recognize the importance of model diagnostics, appropriate predictors, and careful interpretation. These concepts provide a useful foundation for future work in student retention, academic performance, and data-informed educational support.