# ============================================================
# UCI Breast Cancer Wisconsin - Clean End-to-End MLOps
# ============================================================
# -----------------------------
# 1. Libraries
# -----------------------------
library(caret)
library(randomForest)
library(data.table)
suppressMessages(library(mlflow))
# -----------------------------
# 2. Load Dataset
# -----------------------------
DATA_PATH <- "C:/Users/Dhanushkumar/OneDrive/Desktop/MLOPS PRO/MINI PROJECT/breast cancer/data.csv"
if (!file.exists(DATA_PATH)) {
stop("Dataset not found. Check file path.")
}
data <- fread(DATA_PATH)
data <- as.data.frame(data)
# -----------------------------
# 3. Fix Column Names (IMPORTANT)
# -----------------------------
# Remove spaces & special characters
colnames(data) <- make.names(colnames(data))
# Remove completely empty columns
data <- data[, colSums(is.na(data)) < nrow(data)]
# Rename diagnosis column if needed
colnames(data)[2] <- "diagnosis"
# Remove ID column
data <- data[, -1]
# Convert diagnosis to factor
data$diagnosis <- as.factor(data$diagnosis)
# -----------------------------
# 4. Handle Missing Values
# -----------------------------
# Replace NA in numeric columns with median
for(i in 1:ncol(data)){
if(is.numeric(data[,i])){
data[is.na(data[,i]), i] <- median(data[,i], na.rm = TRUE)
}
}
cat("Remaining NA values:", sum(is.na(data)), "\n")
## Remaining NA values: 0
# -----------------------------
# 5. Train-Test Split
# -----------------------------
set.seed(42)
train_index <- createDataPartition(
y = data$diagnosis,
p = 0.8,
list = FALSE
)
train_set <- data[train_index, ]
test_set <- data[-train_index, ]
# -----------------------------
# 6. MLflow (Safe Local Mode)
# -----------------------------
mlflow_set_tracking_uri("file:./mlruns")
try({
mlflow_set_experiment("Breast_Cancer_MLOps")
mlflow_start_run()
}, silent = TRUE)
# -----------------------------
# 7. Model Training
# -----------------------------
N_TREES <- 500
try(mlflow_log_param("model_type", "RandomForest"), silent = TRUE)
try(mlflow_log_param("ntree", N_TREES), silent = TRUE)
rf_model <- randomForest(
diagnosis ~ .,
data = train_set,
ntree = N_TREES,
importance = TRUE
)
# -----------------------------
# 8. Prediction & Evaluation
# -----------------------------
predictions <- predict(rf_model, test_set)
cm <- confusionMatrix(predictions, test_set$diagnosis)
accuracy <- as.numeric(cm$overall["Accuracy"])
sensitivity <- as.numeric(cm$byClass["Sensitivity"])
try(mlflow_log_metric("accuracy", accuracy), silent = TRUE)
try(mlflow_log_metric("sensitivity", sensitivity), silent = TRUE)
# -----------------------------
# 9. Model Versioning
# -----------------------------
MODEL_PATH <- "rf_model_v1.rds"
saveRDS(rf_model, MODEL_PATH)
try(mlflow_log_artifact(MODEL_PATH), silent = TRUE)
# -----------------------------
# 10. Final Output
# -----------------------------
cat("\n==============================\n")
##
## ==============================
cat(" Final Model Performance\n")
## Final Model Performance
cat("==============================\n")
## ==============================
cat(" Accuracy :", round(accuracy, 4), "\n")
## Accuracy : 0.9823
cat(" Sensitivity :", round(sensitivity, 4), "\n")
## Sensitivity : 0.9718
cat("==============================\n")
## ==============================
try(mlflow_end_run(), silent = TRUE)