File size: 7,147 Bytes
cfbc198
 
 
 
 
 
 
84f4e93
cfbc198
 
 
 
 
 
84f4e93
 
 
 
 
 
 
 
 
 
 
cfbc198
84f4e93
 
 
 
1c2b61a
cfbc198
 
84f4e93
 
 
cfbc198
84f4e93
cfbc198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84f4e93
cfbc198
 
 
 
84f4e93
 
 
 
 
 
 
 
 
 
cfbc198
 
84f4e93
 
 
 
 
 
cfbc198
 
ef2db7a
84f4e93
 
cfbc198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84f4e93
cfbc198
84f4e93
 
cfbc198
 
 
 
 
 
84f4e93
 
 
 
 
 
 
cfbc198
 
 
009f44b
4aab73b
a34f24d
 
4aab73b
241ea1d
a34f24d
cfbc198
 
 
a34f24d
84f4e93
 
 
 
a34f24d
cfbc198
84f4e93
 
 
 
cfbc198
84f4e93
 
 
 
cfbc198
84f4e93
 
 
cfbc198
84f4e93
 
 
cfbc198
 
 
 
84f4e93
 
cfbc198
 
 
 
 
 
84f4e93
 
cfbc198
84f4e93
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
157
158
159
160
161
162
163
164
165
166
167
168
import gradio as gr
import pickle
import pandas as pd
import shap
import matplotlib.pyplot as plt

# Load model
filename = 'xgb_h_generation.pkl'
with open(filename, 'rb') as f:
    loaded_model = pickle.load(f)

# Setup SHAP
explainer = shap.Explainer(loaded_model)

# Generation Mapping (Radio Button Labels β†’ Numeric Values)
generation_mapping = {
    "Before 1927": 1,
    "Silent Generation": 2,
    "Baby Boomers": 3,
    "Generation X": 4,
    "Millennials": 5,
    "Generation Z": 6
}

# Employee Profiles (Updated Default Dream Employee Values)
employee_profiles = {
    "πŸ₯‡ Default Dream Employee": [5.0, 5.0, 5.0, 4.8, 4.8, 4.9],  
    "πŸ† Leslie Knope": [4.716, 4.792, 4.864, 4.588, 4.849, 4.601],
    "⚠️ Kevin Malone": [3.045, 3.122, 3.129, 2.886, 3.113, 2.197],
    "🌱 Jim Halpert": [3.885, 3.992, 4.119, 3.704, 4.090, 3.377]
}

# Define the prediction function
def main_func(Generation_Label, WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit):
    Generation = generation_mapping.get(Generation_Label, 5)  # Convert label to numeric value

    new_row = pd.DataFrame({
        'Generation': [Generation],
        '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
    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='border: 1px solid black; padding: 15px; border-radius: 8px; display: flex;'>
        <div style='width: 50%; padding-right: 15px;'>
            <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>
        <div style='width: 50%; border-left: 1px solid black; padding-left: 15px;'>
            <b style='color: #0057B8; font-size: 22px;'>Key Insights:</b>
    """

    # Key Insights (excluding Generation)
    shap_values_df = pd.DataFrame(shap_values.values, columns=new_row.columns)
    shap_values_df = shap_values_df.drop(columns=["Generation"])  # Drop Generation
    for feature in shap_values_df.columns:
        shap_val = shap_values_df[feature].values[0]
        impact = round(shap_val * 10, 2)
        icon = "πŸ“ˆ" if shap_val > 0 else "πŸ“‰"
        effect = "raises turnover risk" if shap_val > 0 else "improves retention"
        risk_html += f"<p style='margin: 5px 0;'> {icon} <b>Each 1-point increase in {feature} {effect} by {abs(impact)}%.</b></p>"

    risk_html += "</div></div>"

    # 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 (excluding Generation)
    fig, ax = plt.subplots()
    shap_values_filtered = shap_values[:, 1:]  # Remove Generation from SHAP values
    shap.plots.bar(shap_values_filtered[0], max_display=6, show=False)  # Adjust max_display if needed
    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 risk_html, prob_chart_path, shap_plot_path

# Function to update sliders based on selected profile
def update_sliders(profile):
    if profile in employee_profiles:
        return employee_profiles[profile]
    return [5.0, 5.0, 5.0, 4.8, 4.8, 4.9]

# UI Setup
with gr.Blocks() as demo:
 
    gr.Image("HiltonLogoSmall.jpg")
    gr.Markdown("""
    <div style="display: flex; justify-content: center; align-items: center;">
        <img src="file=assets/HiltonLogoSmall.jpg" alt="Hilton Logo" 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 and People Analytics professionals</b> assess  
    <b>Sales, Marketing, and Front Office Operations teams</b>β€”<span style='color: #0057B8;'>The Face of Hilton</span>β€”  
    by analyzing <b>team member engagement</b> and predicting <b>turnover risk</b> using  
    <span style='color: #0057B8;'>AI-powered insights</span>.<br>  
    πŸ” <b>Understand what drives retention and make data-driven decisions to keep top talent.</b>  
    </div>
    """)

    # Generation Filter (Radio Button - Independent)
    generation_filter = gr.Radio(choices=list(generation_mapping.keys()), label="Select Generation", value="Millennials")

    # Dropdown for Employee Profiles (Updates Sliders)
    profile_dropdown = gr.Dropdown(choices=list(employee_profiles.keys()), label="Select Employee Profile", value="πŸ₯‡ Default Dream Employee")

    # Sliders for input features (Updated Order)
    with gr.Row():
        WellBeing = gr.Slider(label="WellBeing Score", minimum=1, maximum=5, value=5.0, step=0.1)
        SupportiveGM = gr.Slider(label="Supportive GM Score", minimum=1, maximum=5, value=5.0, step=0.1)
        Engagement = gr.Slider(label="Engagement Score", minimum=1, maximum=5, value=5.0, step=0.1)
    with gr.Row():
        Workload = gr.Slider(label="Workload Score", minimum=1, maximum=5, value=4.8, step=0.1)
        WorkEnvironment = gr.Slider(label="Work Environment Score", minimum=1, maximum=5, value=4.8, step=0.1)
        Merit = gr.Slider(label="Merit Score", minimum=1, maximum=5, value=4.9, step=0.1)

    submit_btn = gr.Button("πŸ”Ž Click Here to Analyze Retention")

    prediction = gr.HTML()

    # Charts Side by Side
    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")

    profile_dropdown.change(update_sliders, inputs=[profile_dropdown], outputs=[WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit])

    submit_btn.click(main_func, [generation_filter, WellBeing, SupportiveGM, Engagement, Workload, WorkEnvironment, Merit], 
                     [prediction, prob_chart, shap_plot])

demo.launch()