Amit-kr26's picture
HF Spaces deployment
c9f187d
Raw
History Blame Contribute Delete
5.03 kB
"""Training orchestrator: feature computation → model fit → MLflow logging → registry."""
import mlflow
import mlflow.sklearn
import mlflow.xgboost
from sklearn.model_selection import train_test_split
from sqlalchemy import Engine
from customer_intelligence.config import settings
from customer_intelligence.features.clv import compute_clv_features
from customer_intelligence.features.delivery import compute_delivery_features
from customer_intelligence.features.rfm import compute_rfm
from customer_intelligence.ml.churn import ChurnModel
from customer_intelligence.ml.registry import register_model, write_scores_to_warehouse
from customer_intelligence.ml.segmentation import CustomerSegmentationModel
def run_segmentation_training(
engine: Engine,
n_clusters: int = 5,
mlflow_tracking_uri: str | None = None,
) -> str:
"""Train KMeans segmentation, log to MLflow, register as Production."""
if mlflow_tracking_uri:
mlflow.set_tracking_uri(mlflow_tracking_uri)
else:
mlflow.set_tracking_uri(settings.mlflow_tracking_uri)
mlflow.set_experiment("customer_segmentation")
print("Computing RFM features...")
rfm_df = compute_rfm(engine)
print("Computing CLV features...")
clv_df = compute_clv_features(engine)
model = CustomerSegmentationModel(n_clusters=n_clusters)
index_df, X = model.build_feature_matrix(rfm_df, clv_df)
print(f"Training KMeans (n_clusters={n_clusters}) on {len(X):,} customers...")
with mlflow.start_run(run_name="kmeans_segmentation") as run:
model.fit(X)
metrics = model.evaluate(X)
labels = model.predict(X)
mlflow.log_params({"n_clusters": n_clusters, "algorithm": "kmeans"})
mlflow.log_metrics(metrics)
mlflow.sklearn.log_model(model.pipeline, "segmentation_pipeline")
print(f" silhouette={metrics['silhouette_score']:.4f}, inertia={metrics['inertia']:.0f}")
run_id = run.info.run_id
register_model(run_id, "customer_segmentation", "segmentation_pipeline")
# Write segment labels back to warehouse
index_df = index_df.copy()
index_df["segment_label"] = labels
scores = index_df[["customer_unique_id", "segment_label"]]
# Also add RFM segment and CLV score
scores = scores.merge(rfm_df[["customer_unique_id", "rfm_segment"]], on="customer_unique_id", how="left")
scores = scores.merge(clv_df[["customer_unique_id", "predicted_clv"]], on="customer_unique_id", how="left")
scores = scores.rename(columns={"predicted_clv": "clv_score"})
print(f"Writing scores to warehouse for {len(scores):,} customers...")
write_scores_to_warehouse(engine, scores)
return run_id
def run_churn_training(
engine: Engine,
mlflow_tracking_uri: str | None = None,
) -> str:
"""Train XGBoost churn classifier, log to MLflow, register as Production."""
if mlflow_tracking_uri:
mlflow.set_tracking_uri(mlflow_tracking_uri)
else:
mlflow.set_tracking_uri(settings.mlflow_tracking_uri)
mlflow.set_experiment("churn_prediction")
print("Computing features for churn model...")
rfm_df = compute_rfm(engine)
clv_df = compute_clv_features(engine)
delivery_df = compute_delivery_features(engine)
churn_model = ChurnModel()
feature_df, y = churn_model.build_feature_matrix(rfm_df, clv_df, delivery_df)
X = feature_df[churn_model.feature_cols].values
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"Training XGBoost churn model on {len(X_train):,} samples...")
with mlflow.start_run(run_name="xgboost_churn") as run:
churn_model.fit(X_train, y_train)
train_metrics = churn_model.evaluate(X_train, y_train)
test_metrics = churn_model.evaluate(X_test, y_test)
mlflow.log_params(
{
"algorithm": "xgboost",
"n_estimators": 200,
"max_depth": 5,
"learning_rate": 0.05,
"churn_threshold_days": 180,
"features": churn_model.feature_cols,
}
)
mlflow.log_metrics({f"train_{k}": v for k, v in train_metrics.items()})
mlflow.log_metrics({f"test_{k}": v for k, v in test_metrics.items()})
mlflow.xgboost.log_model(churn_model.model, "churn_model")
print(
f" test AUC-ROC={test_metrics['auc_roc']:.4f}, "
f"F1={test_metrics['f1']:.4f}, "
f"churn_rate={test_metrics['churn_rate']:.4f}"
)
run_id = run.info.run_id
register_model(run_id, "churn_classifier", "churn_model")
# Write churn probabilities back to warehouse for all customers
all_proba = churn_model.predict_proba(X)
scores = feature_df[["customer_unique_id"]].copy()
scores["churn_probability"] = all_proba
print(f"Writing churn scores to warehouse for {len(scores):,} customers...")
write_scores_to_warehouse(engine, scores)
return run_id