Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎯 CV-Screening — Hiring Prediction Model

A logistic regression model that predicts whether a job candidate will be Hired based on their experience, project history, certifications, education, and the role they applied for.


📌 Overview

This project builds an end-to-end machine learning pipeline — from raw candidate data to a trained, evaluated, and stress-tested classifier — to predict hiring outcomes. The goal wasn't just to fit a model, but to demonstrate a full, honest ML workflow: EDA, cleaning, encoding, class-imbalance handling, evaluation, and validation on unseen data.

⚠️ Note on the data: cv_dataset.csv, cv_dataset_test1.csv, and cv_dataset_test2.csv are synthetically generated datasets, built to mimic realistic hiring patterns (moderate, non-deterministic correlation between experience/projects/certifications and hiring outcome). It does not represent real candidates, companies, or hiring decisions.


🗂️ Dataset

Column Description
Name, Email, Phone Candidate identifiers (dropped before modeling)
Years_Experience Years of professional experience (0–15)
Education bachelor / master / phd
Projects_Count Number of completed projects (0–7)
Certifications_Count Number of certifications held (0–4)
Role_Applied One of 9 data-related job titles
Hired Target — 1 = Hired, 0 = Not Hired
  • 1,000 rows, no missing values, no duplicates
  • Target balance: ~61% Hired / 39% Not Hired

🔍 Methodology

  1. EDA — distribution checks, correlation heatmap, IQR-based outlier screening (none found), hiring breakdown by role
  2. Cleaning — dropped PII columns (Name, Email, Phone), one-hot encoded Education and Role_Applied
  3. Splitting — 80/20 train/test split (random_state=42)
  4. ScalingStandardScaler applied to the three continuous numerical features
  5. ModelingLogisticRegression(class_weight='balanced', max_iter=1000) to correct for class imbalance
  6. Evaluation — confusion matrix, classification report, and 5-fold cross-validation

📊 Results

The model was evaluated on three independent test sets — the original held-out split, plus two freshly generated, never-before-seen synthetic samples — to check that performance holds up beyond a single lucky split.

Test Set 1 — Original 20% split (n=200)

Class Precision Recall F1-score Support
0 (Not Hired) 0.63 0.62 0.62 81
1 (Hired) 0.74 0.76 0.75 119

Accuracy: 0.70 | Macro F1: 0.69 | 5-fold CV: [0.68, 0.645, 0.72, 0.66, 0.715]mean 0.684

Test Set 2 — Fresh dummy data (n=60)

Class Precision Recall F1-score Support
0 (Not Hired) 0.60 0.69 0.64 26
1 (Hired) 0.73 0.65 0.69 34

Accuracy: 0.67 | Macro F1: 0.67 | 5-fold CV: [0.683, 0.70, 0.60, 0.70, 0.75]mean 0.687

Test Set 3 — Fresh dummy data (n=60)

Class Precision Recall F1-score Support
0 (Not Hired) 0.41 0.60 0.49 15
1 (Hired) 0.84 0.71 0.77 45

Accuracy: 0.68 | Macro F1: 0.63 | 5-fold CV: [0.667, 0.65, 0.60, 0.65, 0.75]mean 0.663

📈 Summary across all three test sets

Metric Test 1 Test 2 Test 3 Average
Accuracy 0.70 0.67 0.68 0.683

The tight spread (67–70%) across three independently sampled test sets is the key takeaway: the model's performance is stable, not a fluke of one train/test split. Test Set 3's lower class-0 precision (small support of only 15) is a reminder that metrics on small samples are noisier — worth flagging, not a red flag on its own.


🛠️ Tech Stack

Python · pandas · numpy · scikit-learn · matplotlib · seaborn


🚀 How to Run

pip install pandas numpy scikit-learn matplotlib seaborn
jupyter notebook cv_model_dummy.ipynb

💡 Key Takeaways

  • Correcting for class imbalance with class_weight='balanced' meaningfully improved recall on the minority class (Not Hired) without an unreasonable accuracy trade-off.
  • Validating on multiple freshly generated test sets — not just one split — gives much more confidence that ~68–70% accuracy reflects genuine generalization rather than overfitting to a single sample.
  • The moderate accuracy ceiling (~70%) is expected and intentional: the underlying data has realistic, non-deterministic correlation between features and the hiring outcome, similar to how messy real-world hiring signals actually are.

🔭 Future Improvements

  • Hyperparameter tuning via GridSearchCV
  • Comparison against tree-based models (Random Forest, Gradient Boosting)
  • Threshold tuning on predict_proba for use-case-specific precision/recall trade-offs