Spaces:
Running
Running
File size: 6,613 Bytes
6feeae4 cfbc198 6feeae4 cfbc198 6feeae4 1c2b61a cfbc198 241ea1d cfbc198 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# with cluster profiles
import gradio as gr
import pickle
import pandas as pd
import shap
import matplotlib.pyplot as plt
# Load model
filename = 'xgb_h_new.pkl'
with open(filename, 'rb') as f:
loaded_model = pickle.load(f)
# Setup SHAP
explainer = shap.Explainer(loaded_model)
# Employee Profiles (From SPSS 3-Cluster Solution)
employee_profiles = {
"π Leslie Knope": [4.716, 4.792, 4.864, 4.588, 4.849, 4.601], # Cluster group 1 averages - high engagement, strong support, high workload
"β οΈ Kevin Malone": [3.045, 3.122, 3.129, 2.886, 3.113, 2.197], # Cluster group 2 averages - disengaged, low recognition, weak support
"π± Jim Halpert": [3.885, 3.992, 4.119, 3.704, 4.090, 3.377] # Cluster group 3 averages - Moderately engaged, could be more recognized - room to grow
}
# Define the prediction function
def main_func(WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit):
new_row = pd.DataFrame({
'WellBeing': [WellBeing],
'SupportiveGM': [SupportiveGM],
'Engagement': [Engagement],
'Workload': [Workload],
'WorkEnvironment': [WorkEnvironment],
'Merit': [Merit]
})
# Predict probability
prob = loaded_model.predict_proba(new_row)
shap_values = explainer(new_row)
# Calculate probability values
stay_prob = round((1 - float(prob[0][0])) * 100, 2)
leave_prob = round(float(prob[0][0]) * 100, 2)
# Dynamic risk label: Changes color & text based on probability
risk_label = "π΄ High Risk of Turnover" if leave_prob > 50 else "π’ Low Risk of Turnover"
risk_color = "red" if leave_prob > 50 else "green"
risk_html = f"""
<div style='padding: 15px; border-radius: 8px;'>
<span style='color: {risk_color}; font-size: 26px; font-weight: bold;'>{risk_label}</span>
<ul style='list-style-type: none; padding-left: 0; font-size: 20px; font-weight: bold; color: #0057B8;'>
<li>π§² Likelihood of Staying: {stay_prob}%</li>
<li>πͺ Likelihood of Leaving: {leave_prob}%</li>
</ul>
</div>
"""
# Key Insights (Updated for 0.1-point increments)
insights_html = "<div style='font-size: 18px;'>"
for feature, shap_val in dict(zip(new_row.columns, shap_values.values[0])).items():
impact = round(shap_val * 10, 2) # Scaling impact for 0.1 changes
icon = "π" if shap_val > 0 else "π"
effect = "raises turnover risk" if shap_val > 0 else "improves retention"
insights_html += f"<p style='margin: 5px 0;'> {icon} <b>Each 0.1-point increase in {feature} {effect} by {abs(impact)}%.</b></p>"
insights_html += "</div>"
# Final Layout (Risk + Key Insights)
final_layout = f"""
<table style='width:100%; border-collapse: collapse; margin-top: 10px; background-color: #FFFFFF;'>
<tr>
<td style='width: 33%; padding: 15px; background-color: #FFFFFF; border-radius: 8px; vertical-align: top;'>
{risk_html}
</td>
<td style='width: 67%; padding: 15px; background-color: #FFFFFF; border-radius: 8px; vertical-align: top;'>
<b style='color: #0057B8; font-size: 22px;'>Key Insights:</b>
{insights_html}
</td>
</tr>
</table>
"""
# Retention vs. Turnover Chart
fig, ax = plt.subplots()
categories = ["Stay", "Leave"]
values = [stay_prob, leave_prob]
colors = ["#0057B8", "#D43F00"]
ax.barh(categories, values, color=colors)
for i, v in enumerate(values):
ax.text(v + 2, i, f"{v:.2f}%", va='center', fontweight='bold', fontsize=12)
ax.set_xlabel("Probability (%)")
ax.set_title("Retention vs. Turnover Probability")
plt.tight_layout()
prob_chart_path = "prob_chart.png"
plt.savefig(prob_chart_path, transparent=True)
plt.close()
# SHAP Chart
fig, ax = plt.subplots()
shap.plots.bar(shap_values[0], max_display=6, show=False)
ax.set_title("Key Drivers of Turnover Risk")
plt.tight_layout()
shap_plot_path = "shap_plot.png"
plt.savefig(shap_plot_path, transparent=True)
plt.close()
return final_layout, prob_chart_path, shap_plot_path
# UI Setup
with gr.Blocks() as demo:
gr.HTML("""
<div style="text-align: center;">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Hilton_Worldwide_Logo_2010.svg/2560px-Hilton_Worldwide_Logo_2010.svg.png" width="250px">
</div>
""")
gr.Markdown("<h1 style='color: #0057B8;'>Hilton Team Member Retention Predictor</h1>")
gr.Markdown("""
<div style='font-size: 20px; color: #0057B8;'>
β¨ <b>Welcome to Hiltonβs Employee Retention Predictor</b><br>
This tool helps <b>HR leaders & managers</b> assess <b>team member engagement</b>
and predict <b>turnover risk</b> using AI-powered insights.<br>
π <b>See what factors drive retention & make data-driven decisions.</b>
</div>
""")
# Dropdown for Employee Profiles
profile_dropdown = gr.Dropdown(choices=list(employee_profiles.keys()), label="Select Employee Profile")
# Sliders for input features
with gr.Row():
WellBeing = gr.Slider(label="WellBeing Score", minimum=1, maximum=5, value=4, step=0.1)
SupportiveGM = gr.Slider(label="Supportive GM Score", minimum=1, maximum=5, value=4, step=0.1)
Engagement = gr.Slider(label="Engagement Score", minimum=1, maximum=5, value=4, step=0.1)
with gr.Row():
Workload = gr.Slider(label="Workload Score", minimum=1, maximum=5, value=4, step=0.1)
WorkEnvironment = gr.Slider(label="Work Environment Score", minimum=1, maximum=5, value=4, step=0.1)
Merit = gr.Slider(label="Merit Score", minimum=1, maximum=5, value=4, step=0.1)
submit_btn = gr.Button("π Click Here to Analyze Retention")
# Output elements
prediction = gr.HTML()
with gr.Row():
prob_chart = gr.Image(label="Retention vs. Turnover Probability", type="filepath")
shap_plot = gr.Image(label="Key Drivers of Turnover Risk", type="filepath")
# Allow profile selection to update sliders
def update_sliders(profile):
if profile in employee_profiles:
return employee_profiles[profile]
return [4, 4, 4, 4, 4, 4]
profile_dropdown.change(update_sliders, inputs=[profile_dropdown], outputs=[WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit])
submit_btn.click(main_func, [WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit], [prediction, prob_chart, shap_plot])
demo.launch()
|