Portfolio Project: Credit Card Fraud Detection & Imbalanced Learning
Production-grade financial anomaly detection portfolio project: Highly imbalanced transaction data (0.17% fraud), SMOTE resampling inside cross-validation, XGBoost classifier, Recall/PR-AUC optimization, and SHAP feature attribution.
End-to-End Machine Learning Portfolio Project: Credit Card Fraud Detection
Role: Machine Learning Engineer Project Type: Supervised Binary Classification (Severe Class Imbalance / Anomaly Detection) Dataset: Credit Card Fraud Detection (Kaggle / ULB ML Group) Stack: Scikit-Learn, Imbalanced-Learn (
imblearn), XGBoost, SHAP, FastAPI
Table of Contents#
- Problem Statement & Financial Impact
- Data Source & Class Imbalance Analysis
- Preprocessing & Leak-Proof Resampling Pipeline
- Model Training & Stratified Hyperparameter Tuning
- Evaluation Metrics & Precision-Recall Thresholding
- Explainable AI & Feature Attribution (SHAP)
- Real-Time Production Architecture
- Conclusion & Business Value Delivered
1. Problem Statement & Financial Impact#
1.1 The Business Problem#
Global unauthorized payment fraud costs financial institutions over \30> $5,000$"*) produce excessive False Positives, degrading customer trust and card authorization rates, while failing to detect sophisticated coordinated fraud rings.
1.2 The Machine Learning Challenge#
- Extreme Class Imbalance: Fraudulent transactions constitute only of total traffic (roughly 1 fraud event per 578 valid charges).
- Asymmetric Cost Matrix: A False Negative (missing actual fraud) results in direct chargeback losses and liability. A False Positive (declining a legitimate customer) causes cardholder friction and transaction abandonment.
1.3 Key Performance Indicators (KPIs)#
- Primary Metric: Maximize Recall () on the positive fraud class.
- Secondary Metric: Maintain PR-AUC (Precision-Recall Area Under Curve) and keep False Positive Rate below .
2. Data Source & Class Imbalance Analysis#
🐍 PythonInteractive WebAssemblyimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.metrics import (
confusion_matrix, classification_report,
precision_score, recall_score, f1_score,
roc_auc_score, precision_recall_curve, auc
)
from imblearn.over_sampling import SMOTE
from imblearn.pipeline import Pipeline as ImbPipeline
from sklearn.linear_model import LogisticRegression
import xgboost as xgb
import shap
# Visualization Configuration
sns.set(style="whitegrid")
plt.rcParams['figure.figsize'] = (12, 6)
# Load Dataset
df = pd.read_csv('creditcard.csv')
print(f"Transaction Matrix Dimensions: {df.shape}")
print("\nClass Counts:")
print(df['Class'].value_counts())
fraud_pct = (df['Class'].sum() / len(df)) * 100
print(f"Positive Class Proportion: {fraud_pct:.3f}%")
🐍 PythonInteractive WebAssembly# Visualize Class Imbalance and Transaction Amounts
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
sns.countplot(x='Class', data=df, ax=axes[0], palette=['royalblue', 'crimson'])
axes[0].set_title('Severe Class Distribution (0: Normal, 1: Fraud)')
axes[0].set_yscale('log')
sns.boxplot(x='Class', y='Amount', data=df, ax=axes[1], palette=['royalblue', 'crimson'])
axes[1].set_title('Transaction Amount by Class')
axes[1].set_yscale('log')
plt.show()
3. Preprocessing & Leak-Proof Resampling Pipeline#
Features through are principal components derived from PCA. The Time and Amount features exist on disparate unscaled ranges and require normalization.
Resampling Constraint: Resampling techniques such as SMOTE must strictly execute within training partitions during cross-validation. Applying SMOTE to validation or test data leads to catastrophic data leakage.
🐍 PythonInteractive WebAssembly# Separate Features and Target
X = df.drop('Class', axis=1)
y = df['Class']
# Stratified Partitioning (80% Train, 20% Test)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Standardize Time and Amount features, pass V1-V28 through unchanged
preprocessor = ColumnTransformer(
transformers=[
('scale', StandardScaler(), ['Time', 'Amount'])
],
remainder='passthrough'
)
# Configure SMOTE Generator
smote = SMOTE(sampling_strategy=0.1, random_state=42) # Resample minority to 10% ratio of majority
4. Model Training & Stratified Hyperparameter Tuning#
We compare a regularized baseline against an optimized gradient booster:
- Baseline Model: Regularized Logistic Regression (L2 penalty)
- Challenger Model: XGBoost Classifier with
scale_pos_weightand SMOTE
🐍 PythonInteractive WebAssemblycv_strategy = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
# --- Model 1: Logistic Regression Pipeline ---
lr_pipeline = ImbPipeline([
('preprocessor', preprocessor),
('sampler', smote),
('model', LogisticRegression(max_iter=1000, solver='liblinear'))
])
lr_param_grid = {'model__C': [0.01, 0.1, 1.0]}
lr_grid = GridSearchCV(
lr_pipeline, lr_param_grid, cv=cv_strategy, scoring='roc_auc', n_jobs=-1
)
lr_grid.fit(X_train, y_train)
# --- Model 2: XGBoost Pipeline ---
xgb_pipeline = ImbPipeline([
('preprocessor', preprocessor),
('sampler', smote),
('model', xgb.XGBClassifier(
random_state=42,
eval_metric='aucpr',
use_label_encoder=False
))
])
xgb_param_grid = {
'model__n_estimators': [100, 200],
'model__max_depth': [3, 5],
'model__learning_rate': [0.05, 0.1],
'model__subsample': [0.8]
}
xgb_grid = GridSearchCV(
xgb_pipeline, xgb_param_grid, cv=cv_strategy, scoring='roc_auc', n_jobs=-1, verbose=1
)
xgb_grid.fit(X_train, y_train)
print(f"Logistic Regression Best CV ROC-AUC: {lr_grid.best_score_:.4f}")
print(f"XGBoost Best CV ROC-AUC: {xgb_grid.best_score_:.4f}")
best_model = xgb_grid.best_estimator_
5. Evaluation Metrics & Precision-Recall Thresholding#
We evaluate model performance on the holdout test set with threshold calibration.
🐍 PythonInteractive WebAssembly# Predict Probabilities on Test Set
y_probs = best_model.predict_proba(X_test)[:, 1]
y_pred_default = (y_probs >= 0.50).astype(int)
# Compute Primary Metrics
test_auc = roc_auc_score(y_test, y_probs)
precision_arr, recall_arr, thresholds = precision_recall_curve(y_test, y_probs)
pr_auc = auc(recall_arr, precision_arr)
print(f"Holdout ROC-AUC Score: {test_auc:.4f}")
print(f"Holdout PR-AUC Score: {pr_auc:.4f}")
print(f"Default Threshold (0.5) Recall: {recall_score(y_test, y_pred_default):.4f}")
print(f"Default Threshold (0.5) Precision: {precision_score(y_test, y_pred_default):.4f}")
# Plot Precision-Recall Curve
plt.figure(figsize=(8, 5))
plt.plot(recall_arr, precision_arr, color='purple', lw=2, label=f'PR Curve (AUC = {pr_auc:.3f})')
plt.xlabel('Recall (Fraud Detection Rate)')
plt.ylabel('Precision (True Fraud / Flagged Cases)')
plt.title('Precision-Recall Curve for Imbalanced Classification')
plt.legend()
plt.show()
# Calibrated Low-Friction Decision Threshold (tau = 0.30)
optimal_threshold = 0.30
y_pred_calibrated = (y_probs >= optimal_threshold).astype(int)
cm = confusion_matrix(y_test, y_pred_calibrated)
plt.figure(figsize=(6, 4))
sns.heatmap(
cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['Pred Legitimate', 'Pred Fraud'],
yticklabels=['Act Legitimate', 'Act Fraud']
)
plt.title(f'Confusion Matrix at Threshold {optimal_threshold}')
plt.ylabel('Ground Truth')
plt.xlabel('Prediction')
plt.show()
6. Explainable AI & Feature Attribution (SHAP)#
🐍 PythonInteractive WebAssembly# Extract fitted estimator and transformed test matrix
fitted_xgb = best_model.named_steps['model']
X_test_transformed = best_model.named_steps['preprocessor'].transform(X_test)
# Compute Shapley Values via TreeExplainer
explainer = shap.TreeExplainer(fitted_xgb)
shap_values = explainer.shap_values(X_test_transformed)
# Plot Global Feature Importance Summary
plt.figure(figsize=(10, 6))
shap.summary_plot(
shap_values,
X_test_transformed,
feature_names=X.columns.tolist(),
max_display=10,
show=False
)
plt.title('SHAP Feature Attribution for Fraud Classification')
plt.show()
Latent features , , , and demonstrate the highest marginal impact on the log-odds of positive fraud determinations.
7. Real-Time Production Architecture#
Architecture & Data FlowIncoming Transaction Stream (Kafka) | v [ FastAPI Scoring Engine (< 50ms) ] | +---> Probability >= 0.85: [ AUTO-BLOCK & SMS Alert ] | +---> 0.30 <= Probability < 0.85: [ FLAG FOR FRAUD ANALYST QUEUE ] | +---> Probability < 0.30: [ AUTHORIZE TRANSACTION ]
Production Scoring Endpoint (scoring_api.py)#
🐍 PythonInteractive WebAssemblyfrom fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import joblib
import numpy as np
app = FastAPI(title="Real-Time Fraud Scoring Engine", version="1.0.0")
fraud_pipeline = joblib.load('fraud_detection_pipeline.pkl')
class TransactionPayload(BaseModel):
Time: float
Amount: float
V1: float
V2: float
# Features V3 through V28 mapped here
@app.post("/score-transaction")
async def score_transaction(txn: TransactionPayload):
try:
data_vector = np.array([[txn.Time, txn.Amount, txn.V1, txn.V2, ...]])
fraud_prob = float(fraud_pipeline.predict_proba(data_vector)[0][1])
if fraud_prob >= 0.85:
decision = "BLOCK"
elif fraud_prob >= 0.30:
decision = "MANUAL_REVIEW"
else:
decision = "APPROVE"
return {
"fraud_probability": round(fraud_prob, 4),
"recommended_action": decision
}
except Exception as err:
raise HTTPException(status_code=500, detail=str(err))
8. Conclusion & Business Value Delivered#
8.1 Summary of Deliverables#
- Imbalance Handling: Integrated SMOTE within an
imblearnpipeline to synthesize minority samples strictly inside training folds. - Model Optimization: Trained regularized XGBoost models achieving a PR-AUC and ROC-AUC .
- Threshold Calibration: Implemented cost-aware thresholding () to recover of fraudulent events while suppressing false positive alarm volume.
- Explainability: Deployed SHAP TreeExplainer to deliver real-time feature contributions for manual review queues.
8.2 Business Impact#
- Financial Protection: Intercepts of unauthorized charges before settlement.
- Operational Scalability: Tiered decision boundaries reduce manual review queues by over , routing human analysts to edge cases.
Portfolio Project: Credit Card Fraud Detection Checkpoint
Finished studying this notebook?
Mark this guide as completed to update your course progress roadmap.