1. Project Overview and Objectives

This project aims to build a classification model to predict whether a telecom customer will churn or not. By identifying high-risk customers using service behavior and contract-related features, the company can implement retention strategies to reduce churn and maintain revenue.

2. Workflow Summary

Step Process Description
1 Load libraries Import required R packages (randomForest, caret, ggplot2)
2 Load and clean data Read the dataset, remove missing values, and ensure target variable is a factor
3 Feature selection Select relevant features such as contract type, billing amount, support usage
4 Data splitting Split the dataset into training (80%) and testing (20%) subsets
5 Model training Train a Random Forest classifier with 200 trees
6 Model prediction Generate predictions on the test set
7 Evaluation metrics Calculate accuracy, RMSE, precision, recall, F1 score
8 Confusion matrix display Show the classification matrix with true vs predicted values
9 Feature importance Output feature importance scores from the Random Forest model
10 Visualization Plot a bar chart comparing predicted vs actual churn results
11 Save summary Export key evaluation results and model info to a text file

3. Load Libraries

library(randomForest)
library(caret)
library(ggplot2)

4. Load and Clean Data

out <- "output"
if (!dir.exists(out)) dir.create(out)

df <- read.csv("customer_churn_telecom_services.csv", stringsAsFactors = TRUE)
df <- na.omit(df)
df$Churn <- as.factor(df$Churn)

write.csv(df, file.path(out, "cleaned_data.csv"), row.names = FALSE)

5. Feature Selection

sel <- df[, c("Churn", "Contract", "tenure", "MonthlyCharges", "InternetService",
              "PaymentMethod", "OnlineSecurity", "OnlineBackup", "DeviceProtection",
              "TechSupport", "StreamingTV", "StreamingMovies", "MultipleLines")]

6. Train-Test Split

set.seed(123)
i <- createDataPartition(sel$Churn, p = 0.8, list = FALSE)
tr <- sel[i, ]
ts <- sel[-i, ]

7. Train Random Forest Model

mdl <- randomForest(Churn ~ ., data = tr, ntree = 200, importance = TRUE)
pred <- predict(mdl, ts)

8. Model Evaluation Metrics

cm <- confusionMatrix(pred, ts$Churn)

acc <- cm$overall["Accuracy"]
rmse <- sqrt(mean((as.numeric(pred) - as.numeric(ts$Churn))^2))
prec <- posPredValue(pred, ts$Churn, positive = "Yes")
rec <- sensitivity(pred, ts$Churn, positive = "Yes")
f1 <- 2 * prec * rec / (prec + rec)

list(
  Accuracy = acc,
  RMSE = rmse,
  Precision = prec,
  Recall = rec,
  F1_Score = f1
)
## $Accuracy
##  Accuracy 
## 0.8035587 
## 
## $RMSE
## [1] 0.443217
## 
## $Precision
## [1] 0.6456456
## 
## $Recall
## [1] 0.5764075
## 
## $F1_Score
## [1] 0.6090652

9. Confusion Matrix

cm
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  No Yes
##        No  914 158
##        Yes 118 215
##                                          
##                Accuracy : 0.8036         
##                  95% CI : (0.7818, 0.824)
##     No Information Rate : 0.7345         
##     P-Value [Acc > NIR] : 9.176e-10      
##                                          
##                   Kappa : 0.4784         
##                                          
##  Mcnemar's Test P-Value : 0.0189         
##                                          
##             Sensitivity : 0.8857         
##             Specificity : 0.5764         
##          Pos Pred Value : 0.8526         
##          Neg Pred Value : 0.6456         
##              Prevalence : 0.7345         
##          Detection Rate : 0.6505         
##    Detection Prevalence : 0.7630         
##       Balanced Accuracy : 0.7310         
##                                          
##        'Positive' Class : No             
## 

10. Feature Importance

mdl
## 
## Call:
##  randomForest(formula = Churn ~ ., data = tr, ntree = 200, importance = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 200
## No. of variables tried at each split: 3
## 
##         OOB estimate of  error rate: 20.97%
## Confusion matrix:
##       No Yes class.error
## No  3650 481   0.1164367
## Yes  699 797   0.4672460
importance(mdl)
##                          No       Yes MeanDecreaseAccuracy MeanDecreaseGini
## Contract         -6.7833838 25.866991            27.806895        194.81836
## tenure           10.3030068 41.308323            31.717224        380.60250
## MonthlyCharges   11.3996016 10.439007            20.050967        312.32972
## InternetService   9.9705540 14.630484            16.766423         76.88417
## PaymentMethod    -4.3063370 14.566111             8.335510        112.35160
## OnlineSecurity    0.8365918 22.257239            14.388882         86.73827
## OnlineBackup      3.2824784 10.557927             9.833020         49.93962
## DeviceProtection  7.1047051  1.014956             8.017648         43.13440
## TechSupport       3.6608031 20.345184            15.391365         79.38950
## StreamingTV       6.3061389  1.446131             7.633675         33.81143
## StreamingMovies   7.2862507  1.287617             8.247824         32.52817
## MultipleLines     1.2929768  8.242170             7.728753         45.46728

11. Visualization: Prediction vs Actual

df_out <- data.frame(Actual = ts$Churn, Predicted = pred)
ggplot(df_out, aes(x = Actual, fill = Predicted)) +
  geom_bar(position = "dodge") +
  labs(title = "Prediction vs Actual", x = "Actual", y = "Count") +
  theme_minimal()

12. Save Evaluation Summary (Optional)

sink(file.path(out, "summary.txt"))
cat("Model Evaluation Summary\n\n")
cat("1. Accuracy: ", round(acc, 4), "\n")
cat("2. RMSE: ", round(rmse, 4), "\n")
cat("3. Precision: ", round(prec, 4), "\n")
cat("4. Recall: ", round(rec, 4), "\n")
cat("5. F1 Score: ", round(f1, 4), "\n\n")

cat("Confusion Matrix\n\n")
print(cm)

cat("\n Model Summary \n\n")
print(mdl)

cat("\n Feature Importance\n\n")
print(importance(mdl))
sink()