Spaces:
Runtime error
Runtime error
Update app (2).py
Browse files- app (2).py +135 -113
app (2).py
CHANGED
|
@@ -18,68 +18,127 @@ def safe_convert(value, default, min_val, max_val):
|
|
| 18 |
except (TypeError, ValueError):
|
| 19 |
return default
|
| 20 |
|
| 21 |
-
|
| 22 |
-
def main_func(Category, InventoryBucket, Product, Conference, Geography,
|
| 23 |
-
Baseball, Event, LearningDevelopment, WorkEnvironment, Engagement, WellBeing):
|
| 24 |
-
|
| 25 |
-
category_mapping = {
|
| 26 |
-
"Food": 1,
|
| 27 |
-
"Beverage": 2,
|
| 28 |
-
"Merchandise": 3,
|
| 29 |
-
"Experiences": 4
|
| 30 |
-
}
|
| 31 |
-
|
| 32 |
inventory_mapping = {
|
| 33 |
-
"
|
| 34 |
-
"
|
| 35 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
}
|
| 37 |
|
| 38 |
-
|
| 39 |
-
"
|
| 40 |
-
"
|
| 41 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
|
| 44 |
-
|
| 45 |
-
"
|
| 46 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
}
|
| 48 |
|
| 49 |
geography_mapping = {
|
| 50 |
-
"
|
| 51 |
-
"
|
| 52 |
-
"
|
| 53 |
-
"West": 4
|
|
|
|
| 54 |
}
|
| 55 |
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
WellBeing = safe_convert(WellBeing, 3.0, 1, 5)
|
| 63 |
|
| 64 |
-
# Create input dataframe
|
| 65 |
new_row = pd.DataFrame({
|
| 66 |
-
'Category': [category_mapping[Category]],
|
| 67 |
'InventoryBucket': [inventory_mapping[InventoryBucket]],
|
|
|
|
| 68 |
'Product': [product_mapping[Product]],
|
| 69 |
-
'Conference': [conference_mapping[Conference]],
|
| 70 |
'Geography': [geography_mapping[Geography]],
|
| 71 |
-
'
|
| 72 |
-
'Merit': [Merit],
|
| 73 |
-
'LearningDevelopment': [LearningDevelopment],
|
| 74 |
-
'WorkEnvironment': [WorkEnvironment],
|
| 75 |
-
'Engagement': [Engagement],
|
| 76 |
-
'WellBeing': [WellBeing]
|
| 77 |
}).astype(float)
|
| 78 |
|
| 79 |
-
# Predict revenue
|
| 80 |
prediction = loaded_model.predict(new_row)[0]
|
| 81 |
-
|
| 82 |
-
# SHAP analysis
|
| 83 |
shap_values = explainer(new_row)
|
| 84 |
|
| 85 |
fig, ax = plt.subplots(figsize=(8, 4))
|
|
@@ -94,85 +153,48 @@ def main_func(Category, InventoryBucket, Product, Conference, Geography,
|
|
| 94 |
|
| 95 |
return f"Predicted Revenue: ${prediction:,.2f}", local_plot
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
""
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
# Gradio UI
|
| 110 |
-
with gr.Blocks(title=title) as demo:
|
| 111 |
-
gr.Markdown(f"## {title}")
|
| 112 |
-
gr.Markdown(description1)
|
| 113 |
-
gr.Markdown("""---""")
|
| 114 |
-
gr.Markdown(description2)
|
| 115 |
-
gr.Markdown("""---""")
|
| 116 |
-
|
| 117 |
with gr.Row():
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
value="Medium"
|
| 128 |
-
)
|
| 129 |
-
Product = gr.Radio(
|
| 130 |
-
["Standard", "Premium", "Bundle"],
|
| 131 |
-
label="Product Type",
|
| 132 |
-
value="Standard"
|
| 133 |
-
)
|
| 134 |
-
Conference = gr.Radio(
|
| 135 |
-
["Yes", "No"],
|
| 136 |
-
label="Part of Conference Package?",
|
| 137 |
-
value="No"
|
| 138 |
-
)
|
| 139 |
-
Geography = gr.Dropdown(
|
| 140 |
-
["North", "South", "East", "West"],
|
| 141 |
-
label="Geography",
|
| 142 |
-
value="North"
|
| 143 |
-
)
|
| 144 |
-
SupportiveGM = gr.Slider(label="Supportive GM", minimum=1, maximum=5, value=4, step=0.1)
|
| 145 |
-
Merit = gr.Slider(label="Merit", minimum=1, maximum=5, value=4, step=0.1)
|
| 146 |
-
LearningDevelopment = gr.Slider(label="Learning & Development", minimum=1, maximum=5, value=4, step=0.1)
|
| 147 |
-
WorkEnvironment = gr.Slider(label="Work Environment", minimum=1, maximum=5, value=4, step=0.1)
|
| 148 |
-
Engagement = gr.Slider(label="Engagement", minimum=1, maximum=5, value=4, step=0.1)
|
| 149 |
-
WellBeing = gr.Slider(label="Well-Being", minimum=1, maximum=5, value=4, step=0.1)
|
| 150 |
-
submit_btn = gr.Button("Analyze")
|
| 151 |
-
|
| 152 |
-
with gr.Column(visible=True, scale=1, min_width=600) as output_col:
|
| 153 |
-
label = gr.Label(label="Revenue Prediction")
|
| 154 |
-
local_plot = gr.Plot(label='SHAP Waterfall Plot')
|
| 155 |
-
|
| 156 |
-
submit_btn.click(
|
| 157 |
main_func,
|
| 158 |
-
[
|
| 159 |
-
|
| 160 |
-
[label, local_plot],
|
| 161 |
-
api_name="Revenue_Predictor"
|
| 162 |
)
|
| 163 |
|
| 164 |
-
gr.Markdown("
|
|
|
|
| 165 |
gr.Examples(
|
| 166 |
[
|
| 167 |
-
["
|
| 168 |
-
["
|
| 169 |
-
["Experiences", "Low", "Bundle", "No", "South", 4.3, 4.0, 4.3, 4.4, 4.5, 4.4]
|
| 170 |
],
|
| 171 |
-
[
|
| 172 |
-
SupportiveGM, Merit, LearningDevelopment, WorkEnvironment, Engagement, WellBeing],
|
| 173 |
[label, local_plot],
|
| 174 |
main_func,
|
| 175 |
cache_examples=True
|
| 176 |
)
|
| 177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
demo.launch()
|
|
|
|
| 18 |
except (TypeError, ValueError):
|
| 19 |
return default
|
| 20 |
|
| 21 |
+
def main_func(InventoryBucket, Category, Product, Geography, Conference):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
inventory_mapping = {
|
| 23 |
+
"Spot": 1,
|
| 24 |
+
"Field-Level Signage": 2,
|
| 25 |
+
"LED Ribbon Board Signage": 3,
|
| 26 |
+
"Season Ticket": 4,
|
| 27 |
+
"Videoboard Promotion": 5,
|
| 28 |
+
"Field or Event Access": 6,
|
| 29 |
+
"Program and Guide (Print)": 7,
|
| 30 |
+
"Rotational Signage": 8,
|
| 31 |
+
"Live Read": 9,
|
| 32 |
+
"Parking": 10,
|
| 33 |
+
"Ticket": 11,
|
| 34 |
+
"Feature": 12,
|
| 35 |
+
"Marketing Space": 13,
|
| 36 |
+
"In-Game Promotion": 14,
|
| 37 |
+
"PA Announcement": 15,
|
| 38 |
+
"Scoreboard Signage": 16,
|
| 39 |
+
"Activation": 17,
|
| 40 |
+
"Suite": 18,
|
| 41 |
+
"Billboard": 19,
|
| 42 |
+
"Entitlement/Sponsorship": 20,
|
| 43 |
+
"Game Entitlement": 21,
|
| 44 |
+
"Club Ticket": 22,
|
| 45 |
+
"Post Season Revenue": 23,
|
| 46 |
+
"Display": 24,
|
| 47 |
+
"Miscellaneous Signage": 25,
|
| 48 |
+
"Program and Guide (Digital)": 26,
|
| 49 |
+
"Concourse Signage": 27,
|
| 50 |
+
"Giveaway": 28,
|
| 51 |
+
"Tabling": 29,
|
| 52 |
+
"Game Sponsor": 30,
|
| 53 |
+
"Yearbook": 31,
|
| 54 |
+
"Live Mention": 32,
|
| 55 |
+
"Rights & Licensing": 33,
|
| 56 |
+
"Schedule": 34,
|
| 57 |
+
"Virtual Signage": 35,
|
| 58 |
+
"Venue": 36,
|
| 59 |
+
"Tailgating": 37,
|
| 60 |
+
"Trip": 38,
|
| 61 |
+
"Presenting Sponsor": 39,
|
| 62 |
+
"Concession Signage": 40,
|
| 63 |
+
"Fan Engagement Area": 41,
|
| 64 |
+
"Venue Entitlement": 42,
|
| 65 |
+
"Sideline Branding": 43,
|
| 66 |
+
"Autographed Item": 44,
|
| 67 |
+
"Post Season Ticket": 45,
|
| 68 |
+
"Poster": 46,
|
| 69 |
+
"Courtside Ticket": 47,
|
| 70 |
+
"Box Ticket": 48,
|
| 71 |
+
"Vomitory Signage": 49,
|
| 72 |
+
"Group Tickets": 50,
|
| 73 |
+
"Pre-Game Specialty Sponsor": 51,
|
| 74 |
+
"Sideline Assets": 52,
|
| 75 |
+
"Roster Card": 53,
|
| 76 |
+
"Sideline Signage": 54,
|
| 77 |
+
"Stair Sign": 55,
|
| 78 |
+
"Photo & Meet and Greet": 56,
|
| 79 |
+
"Tour": 57,
|
| 80 |
+
"On-Field Promotion": 58
|
| 81 |
}
|
| 82 |
|
| 83 |
+
category_mapping = {
|
| 84 |
+
"Signage": 1,
|
| 85 |
+
"Radio": 2,
|
| 86 |
+
"Tickets & Hospitality": 3,
|
| 87 |
+
"Promotion": 4,
|
| 88 |
+
"Print": 5,
|
| 89 |
+
"Activation": 6,
|
| 90 |
+
"Entitlement & Sponsorship": 7,
|
| 91 |
+
"Television": 8,
|
| 92 |
+
"Experiential": 9,
|
| 93 |
+
"Miscellaneous": 10,
|
| 94 |
+
"Intellectual Property": 11
|
| 95 |
}
|
| 96 |
|
| 97 |
+
product_mapping = {
|
| 98 |
+
"Football": 1,
|
| 99 |
+
"Basketball - Men's": 2,
|
| 100 |
+
"Basketball - Women's": 3,
|
| 101 |
+
"Baseball": 4,
|
| 102 |
+
"Basketball": 5,
|
| 103 |
+
"Hockey": 6,
|
| 104 |
+
"Arena Sports": 7,
|
| 105 |
+
"Volleyball": 8,
|
| 106 |
+
"Lacrosse - Men's": 9,
|
| 107 |
+
"Softball": 10,
|
| 108 |
+
"Gymnastics": 11,
|
| 109 |
+
"Soccer": 12,
|
| 110 |
+
"Olympic Sports": 13,
|
| 111 |
+
"Lacrosse": 14,
|
| 112 |
+
"Soccer - Women's": 15,
|
| 113 |
+
"Lacrosse - Women's": 16,
|
| 114 |
+
"Soccer - Men's": 17,
|
| 115 |
+
"Wrestling": 18
|
| 116 |
}
|
| 117 |
|
| 118 |
geography_mapping = {
|
| 119 |
+
"South": 1,
|
| 120 |
+
"East Coast": 2,
|
| 121 |
+
"Midwest": 3,
|
| 122 |
+
"Mountain West": 4,
|
| 123 |
+
"West Coast": 5
|
| 124 |
}
|
| 125 |
|
| 126 |
+
conference_mapping = {
|
| 127 |
+
"Power Four": 1,
|
| 128 |
+
"Group of Five": 2,
|
| 129 |
+
"Non-Power Four / Group of Five": 3,
|
| 130 |
+
"Conference": 4
|
| 131 |
+
}
|
|
|
|
| 132 |
|
|
|
|
| 133 |
new_row = pd.DataFrame({
|
|
|
|
| 134 |
'InventoryBucket': [inventory_mapping[InventoryBucket]],
|
| 135 |
+
'Category': [category_mapping[Category]],
|
| 136 |
'Product': [product_mapping[Product]],
|
|
|
|
| 137 |
'Geography': [geography_mapping[Geography]],
|
| 138 |
+
'Conference': [conference_mapping[Conference]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
}).astype(float)
|
| 140 |
|
|
|
|
| 141 |
prediction = loaded_model.predict(new_row)[0]
|
|
|
|
|
|
|
| 142 |
shap_values = explainer(new_row)
|
| 143 |
|
| 144 |
fig, ax = plt.subplots(figsize=(8, 4))
|
|
|
|
| 153 |
|
| 154 |
return f"Predicted Revenue: ${prediction:,.2f}", local_plot
|
| 155 |
|
| 156 |
+
with gr.Blocks(title="Playfly Revenue Predictor") as demo:
|
| 157 |
+
with gr.Row():
|
| 158 |
+
gr.Markdown("## Playfly Revenue Predictor & Interpreter")
|
| 159 |
+
logo = gr.Image(label="", value="logo.png", shape=(75, 75))
|
| 160 |
+
|
| 161 |
+
gr.Markdown("This app predicts **revenue** based on selected inventory, category, sport, geography, and conference.")
|
| 162 |
+
gr.Markdown("---")
|
| 163 |
+
|
| 164 |
+
label = gr.Label(label="Revenue Prediction")
|
| 165 |
+
local_plot = gr.Plot(label="SHAP Waterfall Plot")
|
| 166 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
with gr.Row():
|
| 168 |
+
InventoryBucket = gr.Dropdown(list(inventory_mapping.keys()), label="Inventory Bucket")
|
| 169 |
+
Category = gr.Dropdown(list(category_mapping.keys()), label="Category")
|
| 170 |
+
Product = gr.Dropdown(list(product_mapping.keys()), label="Product")
|
| 171 |
+
Geography = gr.Dropdown(list(geography_mapping.keys()), label="Geography")
|
| 172 |
+
Conference = gr.Dropdown(list(conference_mapping.keys()), label="Conference")
|
| 173 |
+
|
| 174 |
+
analyze_btn = gr.Button("Analyze", elem_id="analyze_btn")
|
| 175 |
+
|
| 176 |
+
analyze_btn.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
main_func,
|
| 178 |
+
[InventoryBucket, Category, Product, Geography, Conference],
|
| 179 |
+
[label, local_plot]
|
|
|
|
|
|
|
| 180 |
)
|
| 181 |
|
| 182 |
+
gr.Markdown("---")
|
| 183 |
+
|
| 184 |
gr.Examples(
|
| 185 |
[
|
| 186 |
+
["Field-Level Signage", "Signage", "Football", "East Coast", "Power Four"],
|
| 187 |
+
["Program and Guide (Digital)", "Print", "Basketball - Women's", "Midwest", "Group of Five"]
|
|
|
|
| 188 |
],
|
| 189 |
+
[InventoryBucket, Category, Product, Geography, Conference],
|
|
|
|
| 190 |
[label, local_plot],
|
| 191 |
main_func,
|
| 192 |
cache_examples=True
|
| 193 |
)
|
| 194 |
|
| 195 |
+
demo.load(None, None, js="""
|
| 196 |
+
document.getElementById("analyze_btn").style.backgroundColor = "#4169E1";
|
| 197 |
+
document.getElementById("analyze_btn").style.color = "white";
|
| 198 |
+
""")
|
| 199 |
+
|
| 200 |
demo.launch()
|