# took functions from practice 3
fisher_score <- function(X, y) {
scores <- numeric(ncol(X))
classes <- unique(y)
for(i in 1:ncol(X)) {
overall_mean <- mean(X[, i])
numerator <- 0
denominator <- 0
for(c in classes) {
X_c <- X[y == c, i]
n_c <- length(X_c)
mean_c <- mean(X_c)
var_c <- var(X_c)
numerator <- numerator + n_c * (mean_c - overall_mean)^2
denominator <- denominator + n_c * var_c
}
scores[i] <- numerator / denominator
}
return(scores)
}
calc_metrics <- function(conf_matrix) {
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
diag_n <- diag(conf_matrix)
col_sum <- colSums(conf_matrix)
row_sum <- rowSums(conf_matrix)
precision <- mean(diag_n / ifelse(col_sum == 0, 1, col_sum), na.rm = TRUE)
recall <- mean(diag_n / ifelse(row_sum == 0, 1, row_sum), na.rm = TRUE)
f1_score <- 2 * ((precision * recall) / (precision + recall))
return(data.frame(accuracy = accuracy, precision = precision, recall = recall, f1_score = f1_score))
}
run_experiment <- function(data) {
train_index <- createDataPartition(data$label, p = 0.7, list = FALSE)
train_data <- data[train_index, ]
test_data <- data[-train_index, ]
X_train <- train_data[, -which(names(train_data) == "label")]
y_train <- train_data$label
X_test <- test_data[, -which(names(test_data) == "label")]
y_test <- test_data$label
scores <- fisher_score(X_train, y_train)
selected_features <- order(scores, decreasing = TRUE)[1:2]
X_train_sel <- X_train[, selected_features]
X_test_sel <- X_test[, selected_features]
cat("Selected features:", colnames(X_train_sel), "\n\n")
train_control <- trainControl(method = "cv", number = 5)
grid_dt <- data.frame(cp = c(0.000001, 0.0001, 0.1))
model_dt <- train(x = X_train_sel, y = y_train,
method = "rpart", tuneGrid = grid_dt, trControl = train_control)
grid_svm <- expand.grid(sigma = c(0.1, 1), C = c(1, 10))
model_svm <- train(x = X_train_sel, y = y_train,
method = "svmRadial", tuneGrid = grid_svm, trControl = train_control)
grid_rf <- expand.grid(mtry = c(1, 2), splitrule = "gini", min.node.size = c(1, 5))
model_rf <- train(x = X_train_sel, y = y_train,
method = "ranger",
tuneGrid = grid_rf,
trControl = train_control)
pred_dt <- predict(model_dt, X_test_sel)
pred_svm <- predict(model_svm, X_test_sel)
pred_rf <- predict(model_rf, X_test_sel)
conf_dt <- table(predicted = pred_dt, Actual = y_test)
conf_svm <- table(predicted = pred_svm, Actual = y_test)
conf_rf <- table(predicted = pred_rf, Actual = y_test)
metrics_dt <- calc_metrics(conf_dt)
metrics_svm <- calc_metrics(conf_svm)
metrics_rf <- calc_metrics(conf_rf)
x_min <- min(X_test_sel[, 1]) - 1
x_max <- max(X_test_sel[, 1]) + 1
y_min <- min(X_test_sel[, 2]) - 1
y_max <- max(X_test_sel[, 2]) + 1
grid <- expand.grid(
X1 = seq(x_min, x_max, length.out = 150),
X2 = seq(y_min, y_max, length.out = 150)
)
colnames(grid) <- colnames(X_train_sel)
pred_grid_dt <- predict(model_dt, newdata = grid)
pred_grid_svm <- predict(model_svm, newdata = grid)
pred_grid_rf <- predict(model_rf, newdata = grid)
grid$Bound_DT <- pred_grid_dt
grid$Bound_SVM <- pred_grid_svm
grid$Bound_RF <- pred_grid_rf
grid_long <- data.frame(
X1 = rep(grid[[1]], 3),
X2 = rep(grid[[2]], 3),
Bound = c(grid$Bound_DT, grid$Bound_SVM, grid$Bound_RF),
Model = factor(rep(c("Decision Tree", "SVM", "Random Forest"), each = nrow(grid)),
levels = c("Decision Tree", "SVM", "Random Forest"))
)
df_plot_long <- data.frame(
X1 = rep(X_test_sel[, 1], 3),
X2 = rep(X_test_sel[, 2], 3),
true_class = rep(y_test, 3),
predicted = c(pred_dt, pred_svm, pred_rf),
Model = factor(rep(c("Decision Tree", "SVM", "Random Forest"), each = length(y_test)), levels = c("Decision Tree", "SVM", "Random Forest"))
)
p_combined <- ggplot() +
geom_tile(data = grid_long, aes(x = X1, y = X2, fill = Bound), alpha = 0.2) +
geom_point(data = df_plot_long, aes(x = X1, y = X2, fill = true_class, color = predicted), shape = 21, size = 2, stroke = 1) +
facet_wrap(~ Model, ncol = 3) +
labs(x = colnames(X_train_sel)[1], y = colnames(X_train_sel)[2],
fill = "true class", color = "predicted class") +
theme_minimal(base_size = 14) +
theme(legend.position = "bottom", legend.text = element_blank())
print(p_combined)
results <- rbind(DecisionTree = metrics_dt, SVM = metrics_svm, RandomForest = metrics_rf)
return(results)
}
all_metrics <- list()
for (file in c("blobs.csv", "halfmoons.csv", "happy_face.csv")) {
cat("\nprocessing dataset:", file, "\n")
dataset <- read.csv(file)
label_col_index <- ncol(dataset)
dataset[, label_col_index] <- as.factor(dataset[, label_col_index])
levels(dataset[, label_col_index]) <- paste0("Class", 1:nlevels(dataset[, label_col_index]))
colnames(dataset)[label_col_index] <- "label"
metrics <- run_experiment(dataset)
all_metrics[[file]] <- metrics
print(knitr::kable(metrics, digits = 3, caption = paste("Classification metrics:", file)))
}