File size: 4,197 Bytes
bfde63f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import os
import sys

# Ensure project root is in sys.path
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

import joblib
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, accuracy_score, mean_squared_error, silhouette_score

from ml.features.feature_engineering import CustomerFeatureEngineer, FEATURE_COLUMNS
from ml.models.segmentation.segmentation_model import CustomerSegmentationModel
from ml.models.churn.churn_model import ChurnPredictionModel
from ml.models.propensity.propensity_model import PurchasePropensityModel
from ml.models.clv.clv_model import CustomerLifetimeValueModel
from ml.explainability.shap_explainer import ShapExplainabilityEngine
from scripts.generate_dataset import generate_customer_dataset

ARTIFACTS_DIR = "ml/models/artifacts"

def train_pipeline():
    print("=== [1/5] Loading or Generating Training Data ===")
    dataset_path = "ml/data/customer_signals.csv"
    if not os.path.exists(dataset_path):
        df_raw = generate_customer_dataset(500)
    else:
        df_raw = pd.read_csv(dataset_path)

    print("=== [2/5] Engineering Features ===")
    feature_engineer = CustomerFeatureEngineer()
    X = feature_engineer.transform(df_raw)
    y_churn = df_raw["churn_label"]
    y_intent = df_raw["purchase_intent_label"]
    y_clv = df_raw["clv"]

    # Train/Test Splits
    X_train, X_test, y_churn_train, y_churn_test = train_test_split(X, y_churn, test_size=0.2, random_state=42)
    _, _, y_intent_train, y_intent_test = train_test_split(X, y_intent, test_size=0.2, random_state=42)
    _, _, y_clv_train, y_clv_test = train_test_split(X, y_clv, test_size=0.2, random_state=42)

    os.makedirs(ARTIFACTS_DIR, exist_ok=True)

    print("=== [3/5] Training Models ===")
    # 1. Customer Segmentation
    print(" -> Training Segmentation Model (K-Means)...")
    seg_model = CustomerSegmentationModel(n_clusters=5)
    seg_model.fit(X, df_raw)
    segments = seg_model.predict(X_test)
    sil_score = silhouette_score(seg_model.scaler.transform(X_test), seg_model.kmeans.predict(seg_model.scaler.transform(X_test)))
    print(f"    Segmentation Silhouette Score: {sil_score:.4f}")

    # 2. Churn Model
    print(" -> Training Churn Prediction Model (XGBoost)...")
    churn_model = ChurnPredictionModel(use_xgboost=True)
    churn_model.fit(X_train, y_churn_train)
    churn_preds_prob = churn_model.predict_proba(X_test)
    churn_auc = roc_auc_score(y_churn_test, churn_preds_prob)
    print(f"    Churn Model ROC-AUC: {churn_auc:.4f}")

    # 3. Purchase Propensity Model
    print(" -> Training Purchase Propensity Model (XGBoost)...")
    prop_model = PurchasePropensityModel(use_xgboost=True)
    prop_model.fit(X_train, y_intent_train)
    prop_preds_prob = prop_model.predict_proba(X_test)
    prop_auc = roc_auc_score(y_intent_test, prop_preds_prob)
    print(f"    Purchase Propensity ROC-AUC: {prop_auc:.4f}")

    # 4. CLV Model
    print(" -> Training Customer Lifetime Value Model...")
    clv_model = CustomerLifetimeValueModel(use_xgboost=True)
    clv_model.fit(X_train, y_clv_train)
    clv_preds = clv_model.predict(X_test)
    clv_rmse = np.sqrt(mean_squared_error(y_clv_test, clv_preds))
    print(f"    CLV Model RMSE: Rs.{clv_rmse:,.2f}")

    print("=== [4/5] Initializing SHAP Explainer ===")
    shap_engine = ShapExplainabilityEngine(churn_model.model, FEATURE_COLUMNS)

    print("=== [5/5] Serializing Artifacts ===")
    joblib.dump(feature_engineer, os.path.join(ARTIFACTS_DIR, "feature_engineer.joblib"))
    joblib.dump(seg_model, os.path.join(ARTIFACTS_DIR, "seg_model.joblib"))
    joblib.dump(churn_model, os.path.join(ARTIFACTS_DIR, "churn_model.joblib"))
    joblib.dump(prop_model, os.path.join(ARTIFACTS_DIR, "prop_model.joblib"))
    joblib.dump(clv_model, os.path.join(ARTIFACTS_DIR, "clv_model.joblib"))
    joblib.dump(shap_engine, os.path.join(ARTIFACTS_DIR, "shap_engine.joblib"))

    print(f"\n[SUCCESS] All models trained & saved successfully to '{ARTIFACTS_DIR}'!")

if __name__ == "__main__":
    train_pipeline()