import pickle import pandas as pd import shap from shap.plots._force_matplotlib import draw_additive_plot import gradio as gr import numpy as np import matplotlib.pyplot as plt from PIL import Image # Load model loaded_model = pickle.load(open("default_xgb.pkl", 'rb')) # SHAP Explainer explainer = shap.Explainer(loaded_model) # Load images for different profiles img_mary = Image.open("mary_profile.png") img_james = Image.open("james_profile.png") img_landon = Image.open("landon_profile.png") # Define main function def main_func(LIMIT_BAL, PAY_0, PAY_2, PAY_3, PAY_4, PAY_5, PAY_6, b1, b2, b3, b4, b5, b6, profile=""): new_row = pd.DataFrame.from_dict({ 'LIMIT_BAL': [LIMIT_BAL], 'PAY_0': [PAY_0], 'PAY_2': [PAY_2], 'PAY_3': [PAY_3], 'PAY_4': [PAY_4], 'PAY_5': [PAY_5], 'PAY_6': [PAY_6], 'b1': [b1], 'b2': [b2], 'b3': [b3], 'b4': [b4], 'b5': [b5], 'b6': [b6] }) prob = loaded_model.predict_proba(new_row)[0][1] shap_values = explainer(new_row) plt.figure(figsize=(10, 6)) shap.plots.bar(shap_values[0], max_display=10, show=False) plt.tight_layout() local_plot = plt.gcf() plt.close() # Select image based on profile if profile == "Mary": image = img_mary elif profile == "James": image = img_james elif profile == "Landon": image = img_landon else: image = None return {"No Default": 1 - float(prob), "Default": float(prob)}, local_plot, image # UI Text title = "**Credit Card Default Risk Predictor** 📊" description1 = """ This app uses financial data such as credit limits, repayment behavior, and bill balances to estimate the probability that a person may **default on their next credit payment**. """ description2 = """ To use the app, either adjust the values or click one of the examples. Then click on **Analyze** to get predictions and interpretations. 🔍 """ # Launch Gradio app with gr.Blocks(title=title) as demo: gr.Markdown(f"## {title}") gr.Markdown(description1) gr.Markdown("---") gr.Markdown(description2) gr.Markdown("---") with gr.Row(): with gr.Column(): LIMIT_BAL = gr.Slider(label="Credit Limit (LIMIT_BAL)", minimum=10000, maximum=1000000, value=150000, step=5000) PAY_0 = gr.Slider(label="PAY_0 (Most recent payment status)", minimum=-2, maximum=8, value=0, step=1) PAY_2 = gr.Slider(label="PAY_2", minimum=-2, maximum=8, value=-1, step=1) PAY_3 = gr.Slider(label="PAY_3", minimum=-2, maximum=8, value=-1, step=1) PAY_4 = gr.Slider(label="PAY_4", minimum=-2, maximum=8, value=-1, step=1) PAY_5 = gr.Slider(label="PAY_5", minimum=-2, maximum=8, value=-1, step=1) PAY_6 = gr.Slider(label="PAY_6", minimum=-2, maximum=8, value=-1, step=1) b1 = gr.Slider(label="Balance 1 (b1)", minimum=-100000, maximum=100000, value=5000, step=1000) b2 = gr.Slider(label="Balance 2 (b2)", minimum=-100000, maximum=100000, value=4500, step=1000) b3 = gr.Slider(label="Balance 3 (b3)", minimum=-100000, maximum=100000, value=4700, step=1000) b4 = gr.Slider(label="Balance 4 (b4)", minimum=-100000, maximum=100000, value=4300, step=1000) b5 = gr.Slider(label="Balance 5 (b5)", minimum=-100000, maximum=100000, value=4000, step=1000) b6 = gr.Slider(label="Balance 6 (b6)", minimum=-100000, maximum=100000, value=3900, step=1000) profile_input = gr.Textbox(visible=False) submit_btn = gr.Button("Analyze") with gr.Column(visible=True, scale=1, min_width=600): label = gr.Label(label="Predicted Default Risk") local_plot = gr.Plot(label="SHAP Explanation Plot") profile_image = gr.Image(label="Customer Profile Image", width=400, height=400) submit_btn.click( main_func, [LIMIT_BAL, PAY_0, PAY_2, PAY_3, PAY_4, PAY_5, PAY_6, b1, b2, b3, b4, b5, b6, profile_input], [label, local_plot, profile_image], api_name="Default_Risk" ) gr.Markdown("""### Example inputs to try: 3 credit profiles - Mary: Did not miss payments in last 6 months, with a decreasing remaining balance and credit limit = 200,000. - James: Constantly missed payments in last 6 months, with an increasing remaining balance and credit limit = 80,000. - Landon: Missed payments in early months, with high fluctuations in remaining balance and credit limit = 300,000. """) gr.Examples( examples=[ [200000, -1, -1, -1, -1, -1, -1, 7500, 10000, 12500, 15000, 17500, 20000, "Mary"], [80000, 2, 2, 2, 3, 2, 2, 20000, 17500, 15500, 12500, 10000, 7500, "James"], [300000, -1, 1, -1, 1, 2, 2, 15000, 20000, 0, 10000, 25000, 10000, "Landon"] ], inputs=[LIMIT_BAL, PAY_0, PAY_2, PAY_3, PAY_4, PAY_5, PAY_6, b1, b2, b3, b4, b5, b6, profile_input], outputs=[label, local_plot, profile_image], fn=main_func, cache_examples=True ) demo.launch()