This project implements a complete end-to-end Machine Learning Operations (MLOps) pipeline in R for predicting heart disease.
The objective of this work is not only to train a machine learning model, but also to follow industry-style ML workflows, including:
This report acts as the execution and documentation layer of the pipeline, while the core logic is implemented in separate R scripts.
The project follows a modular and production-oriented structure: r_project/ ├── R/ │ ├── load_data.R │ ├── preprocess.R │ ├── train.R │ └── evaluate.R ├── data/ │ └── heart_cleaned1.csv ├── models/ │ └── rf_model.rds ├── tests/ │ └── test_schema.R │ └── test_reproducibility.R │ └── test_prediction.R │ └── test_failure.R ├── run_train.R ├── run_evaluate.R ├── app.R └── Heart_Disease_Report.Rmd
Each stage of the ML lifecycle is implemented independently and reused across training, evaluation, testing, and reporting.
The dataset is loaded using the centralized data ingestion module.
source("D:/MLOPS/r_project/R/load_data.R")
data <- load_data("D:/MLOPS/r_project/data/heart_cleaned1.csv")
head(data)
## # A tibble: 6 × 14
## age sex chest_pain_type resting_blood_pressure serum_cholesterol
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 63 1 1 145 233
## 2 67 1 4 160 286
## 3 67 1 4 120 229
## 4 37 1 3 130 250
## 5 41 0 2 130 204
## 6 56 1 2 120 236
## # ℹ 9 more variables: fasting_blood_sugar <dbl>,
## # resting_electrocardiographic_results <dbl>,
## # maximum_heart_rate_achieved <dbl>, exercise_induced_angina <dbl>,
## # st_depression_exercise <dbl>, st_slope <dbl>,
## # number_of_major_vessels <dbl>, thalassemia <dbl>,
## # heart_disease_target <dbl>
The load_data() function abstracts file reading and ensures consistent data ingestion across all stages of the pipeline. # 4.Data Preprocessing Preprocessing and train–test splitting are handled using the existing preprocessing module.
source("D:/MLOPS/r_project/R/preprocess.R")
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Loading required package: ggplot2
## Loading required package: lattice
data$heart_disease_target <- factor(
data$heart_disease_target,
levels = c(0, 1),
labels = c("no_disease", "disease")
)
splits <- preprocess_data(data, "heart_disease_target")
train_data <- splits$train
test_data <- splits$test
dim(train_data)
## [1] 238 14
dim(test_data)
## [1] 59 14
The target variable is converted into a binary factor
Train–test split ensures unbiased model evaluation
All preprocessing logic is centralized for reproducibility
source("D:/MLOPS/r_project/R/train.R")
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
##
## Attaching package: 'randomForest'
## The following object is masked from 'package:ggplot2':
##
## margin
## The following object is masked from 'package:dplyr':
##
## combine
set.seed(42)
model <- train_model(
train_data,
target_col = "heart_disease_target",
model_type = "random_forest"
)
model
## Random Forest
##
## 238 samples
## 13 predictor
## 2 classes: 'no_disease', 'disease'
##
## No pre-processing
## Resampling: Cross-Validated (5 fold)
## Summary of sample sizes: 191, 190, 190, 190, 191
## Resampling results across tuning parameters:
##
## mtry ROC Sens Spec
## 2 0.8953147 0.8904615 0.7454545
## 7 0.8777972 0.8116923 0.7454545
## 13 0.8690280 0.8116923 0.7545455
##
## ROC was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 2.
dir.create("models", showWarnings = FALSE)
saveRDS(model, "models/rf_model.rds")
Saving the model as an .rds file enables:
Reproducibility
Versioning
Deployment without retraining
source("D:/MLOPS/r_project/R/evaluate.R")
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
metrics <- evaluate_model(
model,
test_data,
target_col = "heart_disease_target"
)
## Setting levels: control = no_disease, case = disease
## Setting direction: controls < cases
metrics
## $accuracy
## Accuracy
## 0.779661
##
## $roc_auc
## Area under the curve: 0.9271
The evaluation step computes standard classification metrics such as:
Accuracy
ROC-AUC
This ensures objective assessment of model performance.
set.seed(42)
model_repro <- train_model(
train_data,
"heart_disease_target",
"random_forest"
)
all.equal(model$results, model_repro$results)
## [1] TRUE
Identical results under a fixed seed confirm that the pipeline is deterministic and reproducible.
This project demonstrates several core MLOps principles: - Modular code design - Reusable preprocessing and training functions - Reproducible experiments - Model persistence - Automated testing compatibility (testthat) - CI/CD compatibility (GitHub Actions) - Deployment readiness (Plumber API)
This report validates a fully functional MLOps pipeline implemented in R for heart disease prediction.
By separating data ingestion, preprocessing, training, evaluation, and reporting into independent components, the project mirrors real-world production ML systems.
Overall, the project demonstrates both machine learning knowledge and MLOps workflow implementation using R.