Χρησιμοποιούμε στρωματοποιημένη δειγματοληψία για να διατηρήσουμε την αναλογία των κλάσεων (περίπου 65/35) και στα δύο σύνολα.
train_idx <- createDataPartition(bc$Class, p = 0.7, list = FALSE)
train_set <- bc[train_idx, ]
test_set <- bc[-train_idx, ]
Εκπαιδεύουμε ένα “δάσος” 500 δέντρων. Η τυχαιοποίηση των χαρακτηριστικών σε κάθε split βοηθά στην αποσυσχέτιση των δέντρων και τη μείωση του variance.
rf_model <- randomForest(Class ~ ., data = train_set, ntree = 500, importance = TRUE)
# --- TODO 3: Αξιολόγηση Μοντέλου ---
# 1. Παραγωγή Προβλέψεων (Classes & Probabilities)
rf_pred <- predict(rf_model, test_set) # Επιστρέφει "benign" ή "malignant"
rf_prob <- predict(rf_model, test_set, type = "prob")[, "malignant"] # Πιθανότητα για κακοήθεια
# 2. Confusion Matrix (Accuracy, Sensitivity)
# Ορίζουμε ως positive = "malignant" γιατί αυτό μας ενδιαφέρει να βρούμε
rf_cm <- confusionMatrix(rf_pred, test_set$Class, positive = "malignant")
print(rf_cm)
## 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.9718
## Specificity : 0.9850
## Pos Pred Value : 0.9718
## Neg Pred Value : 0.9850
## Prevalence : 0.3480
## Detection Rate : 0.3382
## Detection Prevalence : 0.3480
## Balanced Accuracy : 0.9784
##
## 'Positive' Class : malignant
##
# 3. Υπολογισμός AUC (Area Under the Curve)
rf_roc <- roc(test_set$Class, rf_prob, levels = c("benign", "malignant"))
## Setting direction: controls < cases
cat("AUC score:", rf_roc$auc, "\n")
## AUC score: 0.9981997
Accuracy (Ακρίβεια): Είναι το ποσοστό των σωστών προβλέψεων επί του συνόλου.
Sensitivity (Ευαισθησία): Είναι η ικανότητα του μοντέλου να βρίσκει τους πραγματικά ασθενείς (Malignant).
AUC (Area Under the Curve): Μετράει πόσο καλά το μοντέλο διαχωρίζει τις δύο κλάσεις σε όλα τα πιθανά επίπεδα πιθανότητας.
1.0: Τέλειο μοντέλο.
0.5: Το μοντέλο μαντεύει στην τύχη.
0.99: Εξαιρετικός διαχωρισμός.
# --- TODO 4: Variable Importance ---
# Εμφάνιση του γραφήματος σπουδαιότητας
varImpPlot(rf_model,
main = "Σπουδαιότητα Μεταβλητών - Διάγνωση Καρκίνου Μαστού",
col = "darkblue",
pch = 19)
# Εναλλακτικά, εμφάνιση των τιμών σε πίνακα
importance_values <- as.data.frame(importance(rf_model))
print(importance_values[order(-importance_values$MeanDecreaseGini), ])
## benign malignant MeanDecreaseAccuracy MeanDecreaseGini
## Cell.size 11.976588 15.948203 19.900875 58.301150
## Cell.shape 10.011263 21.083813 22.370249 53.470968
## Bare.nuclei 19.069891 20.454103 24.973998 36.838280
## Normal.nucleoli 11.431501 11.709221 15.365021 22.570651
## Bl.cromatin 5.943408 14.599084 16.079432 13.093756
## Epith.c.size 10.025874 4.762791 11.224042 12.617603
## Cl.thickness 13.435500 21.454365 19.592274 12.492423
## Marg.adhesion 4.951799 13.487285 13.528026 6.915326
## Mitoses 4.732594 1.147448 4.710676 1.322268
Το Accuracy είναι 98.04%.
Με βάση το Mean Decrease Gini, τα σημαντικότερα χαρακτηριστικά είναι συνήθως το Cell.size (Το πόσο ομοιόμορφα είναι τα μεγέθη των κυττάρων. Τα καρκινικά κύτταρα τείνουν να έχουν μεγάλες αποκλίσεις στο μέγεθος.), το Cell.shape (οι ανωμαλίες στο σχήμα είναι κλασικός δείκτης κακοήθειας) και το Bare.nuclei (Η παρουσία κυτταρικών πυρήνων που δεν περιβάλλονται από κυτταρόπλασμα).
Όχι απαραίτητα. Σε μια βιοψία, το κόστος ενός False Negative (να διαγνώσουμε έναν κακοήθη όγκο ως καλοήθη) είναι ασύμμετρα μεγαλύτερο από ένα False Positive. Επομένως, μας ενδιαφέρει περισσότερο η Sensitivity (Ευαισθησία). Ένα μοντέλο με 97% Accuracy αλλά χαμηλό Sensitivity είναι επικίνδυνο.
# --- TODO 5: Προετοιμασία δεδομένων για XGBoost ---
# Το XGBoost απαιτεί αριθμητικό matrix για τα features και 0/1 για το target
# Μετατροπή των features σε matrix (αφαιρούμε τη στήλη Class)
train_x <- as.matrix(train_set[, -10])
test_x <- as.matrix(test_set[, -10])
# Μετατροπή του target σε 0 (benign) και 1 (malignant)
train_y <- ifelse(train_set$Class == "malignant", 1, 0)
test_y <- ifelse(test_set$Class == "malignant", 1, 0)
# Δημιουργία των ειδικών αντικειμένων DMatrix (βελτιστοποιημένα για XGBoost)
dtrain <- xgb.DMatrix(data = train_x, label = train_y)
dtest <- xgb.DMatrix(data = test_x, label = test_y)
# --- TODO 6: Εκπαίδευση XGBoost με Early Stopping ---
params <- list(
objective = "binary:logistic",
eval_metric = "auc",
max_depth = 4,
eta = 0.1
)
xgb_model <- xgb.train(
params = params,
data = dtrain,
nrounds = 500,
evals = list(val = dtest), # Παρακολούθηση της απόδοσης στο test set
early_stopping_rounds = 20, # Σταμάτα αν δεν βελτιωθεί για 20 γύρους
verbose = 0 # Μην γεμίσεις την οθόνη με logs
)
# --- TODO 7: Σύγκριση XGBoost vs Random Forest ---
# Προβλέψεις XGBoost (μετατροπή πιθανοτήτων σε factor)
xgb_prob <- predict(xgb_model, dtest)
xgb_pred <- factor(ifelse(xgb_prob > 0.5, "malignant", "benign"),
levels = c("benign", "malignant"))
# Confusion Matrix και ROC για το XGBoost
xgb_cm <- confusionMatrix(xgb_pred, test_set$Class, positive = "malignant")
xgb_roc <- roc(test_set$Class, xgb_prob, levels = c("benign", "malignant"))
## Setting direction: controls < cases
# Δημιουργία του Πίνακα Σύγκρισης
comparison_table <- data.frame(
Metric = c("Accuracy", "Sensitivity", "Specificity", "AUC"),
Random_Forest = c(rf_cm$overall["Accuracy"],
rf_cm$byClass["Sensitivity"],
rf_cm$byClass["Specificity"],
rf_roc$auc),
XGBoost = c(xgb_cm$overall["Accuracy"],
xgb_cm$byClass["Sensitivity"],
xgb_cm$byClass["Specificity"],
xgb_roc$auc)
)
# Εμφάνιση του πίνακα
knitr::kable(comparison_table, digits = 3, caption = "Σύγκριση Επιδόσεων Μοντέλων")
| Metric | Random_Forest | XGBoost | |
|---|---|---|---|
| Accuracy | Accuracy | 0.980 | 0.975 |
| Sensitivity | Sensitivity | 0.972 | 0.958 |
| Specificity | Specificity | 0.985 | 0.985 |
| AUC | 0.998 | 0.997 |
Στη συγκεκριμένη εκτέλεση, το Random Forest επικράτησε οριακά με Accuracy 98% έναντι 97.5% του XGBoost και AUC 0.998 έναντι 0.997. Παρόλο που το XGBoost θεωρείται συνήθως πιο ισχυρό, η καθαρότητα του dataset επέτρεψε στο Random Forest να φτάσει σε σχεδόν τέλεια αποτελέσματα.
Μας εξέπληξε το γεγονός ότι το Random Forest απέδωσε ελαφρώς καλύτερα από το XGBoost. Αυτό υποδηλώνει ότι οι σχέσεις μεταξύ των χαρακτηριστικών είναι αρκετά σαφείς και δεν χρειαζόταν η περίπλοκη σειριακή διόρθωση λαθών (boosting) για να επιτευχθεί η μέγιστη ακρίβεια. Επίσης, το AUC (0.998) είναι εντυπωσιακά κοντά στο τέλειο 1.0.
Με βάση τον πίνακα σύγκρισης, το Random Forest σημείωσε ελαφρώς καλύτερες επιδόσεις σε όλες τις μετρικές (Accuracy: 0.980, Sensitivity: 0.972, AUC: 0.998) σε σχέση με το XGBoost. Η ελαφρώς χαμηλότερη Sensitivity του XGBoost (95.8% έναντι 97.2% του RF) μας οδηγεί στο να προτείνουμε το Random Forest ως το κύριο εργαλείο μας, καθώς στην ογκολογία η ελαχιστοποίηση των False Negatives είναι η απόλυτη προτεραιότητα.