import gradio as gr import numpy as np import pandas as pd import pickle # Load model and encoder from files uploaded to the Hugging Face Space with open("churn_rf_healthy_meals.pkl", "rb") as f: model = pickle.load(f) with open("churn_encoder_healthy_meals.pkl", "rb") as f: encoder = pickle.load(f) def predict(age, income_level, education, device_type, tech_comfort_score): """ Predict renewal probability for a single customer. The input values must be passed through the same encoder used during training. We build a one-row DataFrame with the raw categorical values (matching the column names the encoder was fit on), transform it, then combine with the numeric features in the same order as the training feature matrix: Training column order (from Step 4 of the training notebook): [AGE, TECH_COMFORT_SCORE, ] Bug note: do NOT recreate the one-hot logic by hand — case mismatches or category order differences will produce a constant all-zeros input and a constant prediction regardless of what the user enters. """ # Build a single-row DataFrame with the raw categorical values. # Column names must match exactly what the encoder was fit on (UPPERCASE). raw = pd.DataFrame([{ 'INCOME_LEVEL': income_level, 'EDUCATION': education, 'DEVICE_TYPE': device_type, }]) # Apply the saved encoder (transform only — never fit_transform here) encoded = encoder.transform(raw) encoded_df = pd.DataFrame(encoded, columns=encoder.get_feature_names_out()) # Build the numeric part of the feature vector numeric_df = pd.DataFrame([{ 'AGE': age, 'TECH_COMFORT_SCORE': tech_comfort_score, }]) # Combine in the same column order as the training feature matrix: # numeric columns first, then encoded dummies input_df = pd.concat([numeric_df, encoded_df], axis=1) # Predict: column 1 = P(renewed), column 0 = P(churned) probability = model.predict_proba(input_df)[0][1] risk = "Low" if probability >= 0.6 else "Medium" if probability >= 0.4 else "High" return f"Renewal Probability: {probability:.2f} | Churn Risk: {risk}" # Gradio radio values must exactly match the category strings the encoder # was trained on (check encoder.categories_ printed in the previous cell). iface = gr.Interface( fn=predict, inputs=[ gr.Number(label="Age"), gr.Radio(["Low", "Medium", "High", "Very High"], label="Income Level"), gr.Radio(["Graduate", "High School", "Other", "Post-Graduate"], label="Education"), gr.Radio(["Desktop-only", "Mobile-only", "Multi-device"], label="Device Type"), gr.Number(label="Tech Comfort Score"), ], outputs="text", title="Customer Renewal Probability Predictor", description="Enter customer attributes to predict the likelihood of subscription renewal." ) iface.launch(server_name="0.0.0.0", server_port=7860)