Download app.py from XRachel/bcs: direct link, hf CLI and curl.
- Browser
- Download file 5.06 kB
-
https://huggingface.co/spaces/XRachel/bcs/resolve/main/app.py
- Command line
-
hf download hf://spaces/XRachel/bcs/app.py
-
curl -L -o app.py https://huggingface.co/spaces/XRachel/bcs/resolve/main/app.py
5.06 kB
| import os | |
| import math | |
| from pathlib import Path | |
| import gradio as gr | |
| import pandas as pd | |
| REQUIRED_COLUMNS = [ | |
| "CreditScore", | |
| "Age", | |
| "Balance", | |
| "NumOfProducts", | |
| "IsActiveMember", | |
| "EstimatedSalary", | |
| ] | |
| def clamp(x, low=0.0, high=1.0): | |
| return max(low, min(high, x)) | |
| def churn_probability( | |
| credit_score, | |
| age, | |
| balance, | |
| num_products, | |
| is_active_member, | |
| estimated_salary, | |
| ): | |
| score = -1.2 | |
| score += max(age - 40, 0) * 0.04 | |
| score += max(650 - credit_score, 0) * 0.003 | |
| score += min(balance / 100000.0, 2.0) * 0.45 | |
| score += 0.35 if int(num_products) <= 1 else -0.15 | |
| score += -0.55 if int(is_active_member) == 1 else 0.35 | |
| score += min(estimated_salary / 200000.0, 1.0) * 0.08 | |
| prob = 1 / (1 + math.exp(-score)) | |
| return clamp(prob) | |
| def risk_label(prob): | |
| if prob < 0.30: | |
| return "Low" | |
| if prob < 0.60: | |
| return "Medium" | |
| return "High" | |
| def predict_single( | |
| credit_score, | |
| age, | |
| balance, | |
| num_products, | |
| is_active_member, | |
| estimated_salary, | |
| ): | |
| p = churn_probability( | |
| float(credit_score), | |
| float(age), | |
| float(balance), | |
| float(num_products), | |
| int(is_active_member), | |
| float(estimated_salary), | |
| ) | |
| label = 1 if p >= 0.5 else 0 | |
| summary = ( | |
| f"### Prediction Result\n\n" | |
| f"- Churn probability: **{p:.1%}**\n" | |
| f"- Predicted class: **{label}**\n" | |
| f"- Risk level: **{risk_label(p)}**" | |
| ) | |
| table = pd.DataFrame( | |
| { | |
| "metric": ["churn_probability", "predicted_class", "risk_level"], | |
| "value": [round(p, 4), label, risk_label(p)], | |
| } | |
| ) | |
| return summary, table | |
| def predict_batch(file): | |
| if file is None: | |
| return None, "Please upload a CSV file." | |
| try: | |
| df = pd.read_csv(file.name) | |
| except Exception as e: | |
| return None, f"Could not read CSV: {e}" | |
| missing = [c for c in REQUIRED_COLUMNS if c not in df.columns] | |
| if missing: | |
| return None, f"Missing required columns: {missing}" | |
| probs = [] | |
| preds = [] | |
| for _, row in df.iterrows(): | |
| p = churn_probability( | |
| row["CreditScore"], | |
| row["Age"], | |
| row["Balance"], | |
| row["NumOfProducts"], | |
| row["IsActiveMember"], | |
| row["EstimatedSalary"], | |
| ) | |
| probs.append(round(p, 4)) | |
| preds.append(1 if p >= 0.5 else 0) | |
| out = df.copy() | |
| out["churn_probability"] = probs | |
| out["churn_prediction"] = preds | |
| output_path = Path("/tmp/bank_churn_predictions.csv") | |
| out.to_csv(output_path, index=False) | |
| return str(output_path), f"Done. Processed {len(out)} rows." | |
| def sample_csv(): | |
| df = pd.DataFrame( | |
| [ | |
| [600, 45, 50000, 1, 0, 70000], | |
| [720, 31, 12000, 2, 1, 85000], | |
| ], | |
| columns=REQUIRED_COLUMNS, | |
| ) | |
| path = Path("/tmp/sample_bank_churn_input.csv") | |
| df.to_csv(path, index=False) | |
| return str(path) | |
| def build_ui(): | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🏦 Bank Churn Simple App") | |
| gr.Markdown( | |
| "This is a lightweight version built to reduce Hugging Face startup issues." | |
| ) | |
| with gr.Tab("Single Prediction"): | |
| credit_score = gr.Slider(300, 900, value=650, step=1, label="CreditScore") | |
| age = gr.Slider(18, 100, value=40, step=1, label="Age") | |
| balance = gr.Number(value=50000, label="Balance") | |
| num_products = gr.Slider(1, 4, value=2, step=1, label="NumOfProducts") | |
| is_active_member = gr.Dropdown( | |
| choices=[0, 1], value=1, label="IsActiveMember" | |
| ) | |
| estimated_salary = gr.Number(value=80000, label="EstimatedSalary") | |
| predict_btn = gr.Button("Predict") | |
| summary_out = gr.Markdown() | |
| table_out = gr.Dataframe() | |
| predict_btn.click( | |
| fn=predict_single, | |
| inputs=[ | |
| credit_score, | |
| age, | |
| balance, | |
| num_products, | |
| is_active_member, | |
| estimated_salary, | |
| ], | |
| outputs=[summary_out, table_out], | |
| ) | |
| with gr.Tab("CSV Batch Prediction"): | |
| gr.Markdown("Required columns: " + ", ".join(REQUIRED_COLUMNS)) | |
| input_file = gr.File(label="Upload CSV", file_types=[".csv"]) | |
| batch_btn = gr.Button("Run Batch Prediction") | |
| output_file = gr.File(label="Download Results") | |
| batch_msg = gr.Markdown() | |
| sample_btn = gr.Button("Download Sample CSV") | |
| batch_btn.click( | |
| fn=predict_batch, | |
| inputs=[input_file], | |
| outputs=[output_file, batch_msg], | |
| ) | |
| sample_btn.click(fn=sample_csv, outputs=[output_file]) | |
| return demo | |
| if __name__ == "__main__": | |
| demo = build_ui() | |
| port = int(os.environ.get("PORT", "7860")) | |
| demo.launch(server_name="0.0.0.0", server_port=port) | |