set.seed(42)
# Η createDataPartition διατηρεί την αναλογία των κλάσεων (Benign/Malignant)
trainIndex <- createDataPartition(bc$Class, p = 0.7, list = FALSE)
train <- bc[trainIndex, ]
test <- bc[-trainIndex, ]
# ntree=500: Χτίζουμε 500 δέντρα
# importance=TRUE: Για να υπολογίσουμε τη σημαντικότητα των χαρακτηριστικών
modelRF <- randomForest(Class ~ .,
data = train,
ntree = 500,
importance = TRUE)
# Προβλέψεις κλάσης
predictRF <- predict(modelRF, newdata = test)
# Confusion Matrix
cm_rf <- confusionMatrix(predictRF, test$Class)
print(cm_rf)
## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 131 2
## malignant 2 69
##
## Accuracy : 0.9804
## 95% CI : (0.9506, 0.9946)
## No Information Rate : 0.652
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9568
##
## Mcnemar's Test P-Value : 1
##
## Sensitivity : 0.9850
## Specificity : 0.9718
## Pos Pred Value : 0.9850
## Neg Pred Value : 0.9718
## Prevalence : 0.6520
## Detection Rate : 0.6422
## Detection Prevalence : 0.6520
## Balanced Accuracy : 0.9784
##
## 'Positive' Class : benign
##
# Υπολογισμός AUC (χρειάζεται τις πιθανότητες)
probRF <- predict(modelRF, newdata = test, type = "prob")
roc_rf <- roc(test$Class, probRF[, "malignant"])
## Setting levels: control = benign, case = malignant
## Setting direction: controls < cases
print(paste("AUC:", round(auc(roc_rf), 4)))
## [1] "AUC: 0.9982"
Η Ακρίβεια (Accuracy) του μοντέλου ανέρχεται στο 98,04%, υποδηλώνοντας ένα εξαιρετικά υψηλό ποσοστό σωστών προβλέψεων επί του συνόλου των βιοψιών. Ωστόσο, στο πλαίσιο ενός ογκολογικού κέντρου, η αποτυχία εντοπισμού έστω και λίγων κακοηθών περιπτώσεων (False Negatives) θέτει σε άμεσο κίνδυνο τη ζωή των ασθενών. Για τον λόγο αυτό, η Ευαισθησία (Sensitivity) αποτελεί την πλέον κρίσιμη μετρική για ένα εργαλείο υποστήριξης ιατρικών αποφάσεων· στην περίπτωσή μας, αυτή διαμορφώνεται στο 98,50%, γεγονός που αποδεικνύει την υψηλή αξιοπιστία του μοντέλου στον ορθό εντοπισμό των κακοηθών όγκων. Τέλος, η τιμή AUC (0.9982*), η οποία προσεγγίζει τη μονάδα, επιβεβαιώνει την κορυφαία ικανότητα του μοντέλου να διαχωρίζει επιτυχώς τις καλοήθεις από τις κακοήθεις περιπτώσεις, καθιστώντας το ένα πολύτιμο διαγνωστικό βοήθημα.
#varImpPlot(modelRF, main = "Variable Importance (Random Forest)")
#ggplot2
# 1. Μετατροπή των importance data σε data frame
imp_data <- as.data.frame(importance(modelRF))
imp_data$Variable <- rownames(imp_data)
# 2. Αναδιοργάνωση των δεδομένων (Long Format)
# Μετατρέπουμε το table έτσι ώστε τα Accuracy και Gini να είναι σε μία στήλη
imp_long <- imp_data %>%
pivot_longer(cols = c(MeanDecreaseAccuracy, MeanDecreaseGini),
names_to = "Metric",
values_to = "Value")
# 3. Δημιουργία του Faceted Plot
ggplot(imp_long, aes(x = Value, y = reorder(Variable, Value))) +
geom_segment(aes(x = 0, xend = Value, y = Variable, yend = Variable), color = "black") +
geom_point(aes(color = Metric), size = 3) +
# Διαχωρισμός σε δύο panels
facet_wrap(~Metric, scales = "free_x") +
theme_minimal() +
labs(
title = "Variable Importance Analysis",
subtitle = "Comparison of Accuracy and Gini Importance",
x = "Importance Score",
y = NULL
) +
theme(
legend.position = "none",
strip.text = element_text(face = "bold", size = 11),
panel.grid.major.y = element_blank()
) +
scale_color_manual(values = c("MeanDecreaseAccuracy" = "#90D5FF", "MeanDecreaseGini" = "#FFC5D3"))
### Συμπεράσματα
Σύμφωνα με το κριτήριο MeanDecreaseGini, το οποίο
μετρά πόσο συμβάλλει κάθε μεταβλητή στην ομοιογένεια των κόμβων σε όλα
τα δέντρα του δάσους, τα τρία σημαντικότερα κυτταρολογικά
χαρακτηριστικά για τη διάγνωση είναι:
Cell.size (Μέγεθος Κυττάρου), Cell.shape (Σχήμα Κυττάρου) και
Bare.nuclei(Γυμνοί Πυρήνες),που στην κυτταρολογία αναφέρεται σε
πυρήνες κυττάρων που έχουν χάσει το κυτταρόπλασμά
τους.
# Το XGBoost απαιτεί αριθμητικούς πίνακες (matrices) και labels 0/1
train_x <- as.matrix(train[, 1:9])
test_x <- as.matrix(test[, 1:9])
# Μετατροπή target σε 0 (benign) και 1 (malignant)
train_y <- ifelse(train$Class == "malignant", 1, 0)
test_y <- ifelse(test$Class == "malignant", 1, 0)
# Δημιουργία DMatrix για βελτιστοποίηση ταχύτητας και early stopping
dtrain <- xgb.DMatrix(data = train_x, label = train_y)
dtest <- xgb.DMatrix(data = test_x, label = test_y)
set.seed(42)
params <- list(
objective = "binary:logistic", # Για δυαδική κατηγοριοποίηση
max_depth = 4, # Βάθος δέντρου
eta = 0.1, # Learning rate (ρυθμός μάθησης)
eval_metric = "error"
)
model_xgb <- xgb.train(
params = params,
data = dtrain,
nrounds = 500,
evals = list(val = dtest, train = dtrain),
early_stopping_rounds = 20, # Σταματά αν δεν βελτιωθεί για 20 γύρους
verbose = 0
)
# Προβλέψεις (μετατροπή πιθανοτήτων σε κλάσεις 0/1)
pred_probs <- predict(model_xgb, test_x)
pred_xgb <- ifelse(pred_probs > 0.5, "malignant", "benign")
pred_xgb <- factor(pred_xgb, levels = c("benign", "malignant"))
cm_xgb <- confusionMatrix(pred_xgb, test$Class)
# Υπολογισμός AUC για XGBoost
roc_xgb <- roc(test$Class, pred_probs)
## Setting levels: control = benign, case = malignant
## Setting direction: controls < cases
# Δημιουργία συγκριτικού πίνακα
comparison_table <- data.frame(
Metric = c("Accuracy", "Sensitivity", "Specificity", "AUC"),
Random_Forest = c(cm_rf$overall["Accuracy"], cm_rf$byClass["Sensitivity"],
cm_rf$byClass["Specificity"], as.numeric(auc(roc_rf))),
XGBoost = c(cm_xgb$overall["Accuracy"], cm_xgb$byClass["Sensitivity"],
cm_xgb$byClass["Specificity"], as.numeric(auc(roc_xgb)))
)
print(comparison_table)
## Metric Random_Forest XGBoost
## Accuracy Accuracy 0.9803922 0.9705882
## Sensitivity Sensitivity 0.9849624 0.9849624
## Specificity Specificity 0.9718310 0.9436620
## AUC 0.9981997 0.9972466
Στη συγκεκριμένη υλοποίηση, το μοντέλο Random Forest
αναδεικνύεται νικητής έναντι του XGBoost στις περισσότερες
μετρικές: Accuracy (Ακρίβεια): Το Random Forest υπερέχει με 0.9804
έναντι 0.9706 του XGBoost (διαφορά ~1%). Sensitivity (Ευαισθησία): Και
τα δύο μοντέλα πέτυχαν την ίδια κορυφαία επίδοση (0.9850), γεγονός
εξαιρετικά σημαντικό για την ανίχνευση κακοήθειας.
Specificity (Ειδικότητα): Το Random Forest παρουσιάζει καλύτερη
ικανότητα στον εντοπισμό των καλοήθων όγκων (0.9718) σε σχέση με το
XGBoost (0.9437). AUC: Το Random Forest προηγείται οριακά με 0.9982
έναντι 0.9972.
Συνήθως, το XGBoost (Gradient Boosting) αναμένεται να έχει ελαφρώς
καλύτερες επιδόσεις από το Random Forest, καθώς διορθώνει σειριακά τα
σφάλματα των προηγούμενων δέντρων. Ωστόσο, στην περίπτωση αυτή το Random
Forest αποδείχθηκε πιο ισχυρό. Αυτό μπορεί να οφείλεται στους εξής
παράγοντες:
Tuning (Παραμετροποίηση): Το XGBoost είναι πολύ ευαίσθητο στις
παραμέτρους του.
Μέγεθος Δεδομένων: Το Random Forest είναι εξαιρετικά σταθερό και
αξιόπιστο σε datasets μεσαίου μεγέθους, όπως οι 699 βιοψίες του
BreastCancer.
Σταθερότητα (Stability): Η τυχαιότητα του Random Forest στην επιλογή
χαρακτηριστικών και δειγμάτων το καθιστά ιδιαίτερα ανθεκτικό,
αποφεύγοντας την υπερεκπαίδευση (overfitting) που μερικές φορές
επηρεάζει το Boosting.
(# 8. Δοκιμή eta 0.01 και 0.3)
# Σχεδίαση της πρώτης καμπύλης (Random Forest)
plot(roc_rf, col = "#90D5FF", lwd = 3, main = "Σύγκριση ROC: Random Forest vs XGBoost")
# Προσθήκη της δεύτερης καμπύλης (XGBoost)
plot(roc_xgb, col = "#FFC5D3", lwd = 3, add = TRUE)
# Προσθήκη υπομνήματος
legend("bottomright", legend = c(
paste("Random Forest (AUC =", round(auc(roc_rf), 3), ")"),
paste("XGBoost (AUC =", round(auc(roc_xgb), 3), ")")
), col = c("#90D5FF", "#FFC5D3"), lwd = 3)
# Συμπεράσματα
Το γεγονός ότι και οι δύο καμπύλες σχεδόν συμπίπτουν δείχνει ότι τα μοντέλα διαχωρίζουν τις καλοήθεις από τις κακοήθεις βιοψίες με σχεδόν απόλυτη επιτυχία. Το Random Forest υπερέχει οριακά με AUC = 0.998 έναντι 0.997 του XGBoost. Στην ιατρική, αυτή η ελάχιστη διαφορά μπορεί να σημαίνει μεγαλύτερη σταθερότητα στις διαγνώσεις.
Επίσης,η περιοχή κάτω από την καμπύλη (AUC) είναι τόσο υψηλή, που επιβεβαιώνει ότι το μοντέλο είναι έτοιμο να χρησιμοποιηθεί ως Decision Support Tool για τους γιατρούς, ελαχιστοποιώντας το ρίσκο λανθασμένης διάγνωσης.