import os import json import argparse from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score from src.data import generate_synthetic_data, prepare_data from src.model import ChurnClassifier def train_pipeline(n_samples: int = 1500, test_size: float = 0.2, model_path: str = "models/churn_model.pkl", metrics_path: str = "models/metrics.json"): print("Generating synthetic dataset...") df = generate_synthetic_data(n_samples=n_samples, random_state=42) print("Preparing train and test splits...") X_train, X_test, y_train, y_test, preprocessor = prepare_data(df, test_size=test_size, random_state=42) print(f"Train set size: {X_train.shape[0]} samples, Test set size: {X_test.shape[0]} samples.") print("Fitting Random Forest Churn Classifier...") classifier = ChurnClassifier(n_estimators=100, max_depth=8, random_state=42) classifier.fit(X_train, y_train, preprocessor=preprocessor) print("Evaluating trained model on testing dataset...") y_pred = classifier.predict(X_test) y_prob = classifier.predict_proba(X_test)[:, 1] metrics = { "accuracy": float(accuracy_score(y_test, y_pred)), "precision": float(precision_score(y_test, y_pred, zero_division=0)), "recall": float(recall_score(y_test, y_pred, zero_division=0)), "f1_score": float(f1_score(y_test, y_pred, zero_division=0)), "roc_auc": float(roc_auc_score(y_test, y_prob)) } print(f"Metrics: {json.dumps(metrics, indent=2)}") print(f"Saving model and preprocessor to {model_path}...") classifier.save(model_path) print(f"Saving evaluation metrics to {metrics_path}...") os.makedirs(os.path.dirname(os.path.abspath(metrics_path)), exist_ok=True) with open(metrics_path, 'w') as f: json.dump(metrics, f, indent=2) print("Training pipeline completed successfully.") if __name__ == "__main__": parser = argparse.ArgumentParser(description="Train customer churn model.") parser.add_argument("--samples", type=int, default=1500, help="Number of synthetic samples to generate") parser.add_argument("--test_size", type=float, default=0.2, help="Proportion of dataset to use for test split") parser.add_argument("--model_path", type=str, default="models/churn_model.pkl", help="Filepath to save the trained model pickle") parser.add_argument("--metrics_path", type=str, default="models/metrics.json", help="Filepath to save the JSON metrics") args = parser.parse_args() train_pipeline( n_samples=args.samples, test_size=args.test_size, model_path=args.model_path, metrics_path=args.metrics_path )