Danielescp commited on
Commit
f6cfaae
·
verified ·
1 Parent(s): 26f589e

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -257
app.py DELETED
@@ -1,257 +0,0 @@
1
- """
2
- Restaurant Health Grade Predictor
3
- ----------------------------------
4
- A Gradio app that predicts health inspection grades (A/B/C)
5
- using a placeholder Random Forest model trained on synthetic data.
6
-
7
- Requirements:
8
- pip install gradio scikit-learn matplotlib numpy pandas
9
- """
10
-
11
- import gradio as gr
12
- import numpy as np
13
- import pandas as pd
14
- import matplotlib.pyplot as plt
15
- import matplotlib.patches as mpatches
16
- from sklearn.ensemble import RandomForestClassifier
17
- from sklearn.preprocessing import LabelEncoder
18
- import warnings
19
-
20
- warnings.filterwarnings("ignore")
21
-
22
- # ──────────────────────────────────────────────────────────────────────────────
23
- # 1. Build a placeholder Random Forest model on synthetic data
24
- # ──────────────────────────────────────────────────────────────────────────────
25
-
26
- CUISINE_TYPES = [
27
- "American", "Chinese", "Italian", "Mexican", "Japanese",
28
- "Indian", "Thai", "Mediterranean", "French", "Korean",
29
- ]
30
-
31
- VIOLATION_CODES = [
32
- "No Violation",
33
- "02A - No food safety certificate",
34
- "04L - Evidence of mice or rats",
35
- "06C - Food not protected",
36
- "08A - Facility not sanitized",
37
- "10B - Plumbing not properly installed",
38
- "15L - Workers not using proper hygiene",
39
- ]
40
-
41
- GRADE_LABELS = ["A", "B", "C"]
42
-
43
- # Encode categorical features
44
- cuisine_enc = LabelEncoder().fit(CUISINE_TYPES)
45
- violation_enc = LabelEncoder().fit(VIOLATION_CODES)
46
-
47
- def encode_inputs(cuisine: str, violation: str, score: float) -> np.ndarray:
48
- c = cuisine_enc.transform([cuisine])[0]
49
- v = violation_enc.transform([violation])[0]
50
- return np.array([[c, v, score]])
51
-
52
-
53
- def generate_synthetic_data(n: int = 2000, seed: int = 42) -> tuple:
54
- rng = np.random.default_rng(seed)
55
- cuisines = rng.integers(0, len(CUISINE_TYPES), n)
56
- violations = rng.integers(0, len(VIOLATION_CODES), n)
57
- scores = rng.uniform(0, 100, n)
58
-
59
- # Grade logic: score drives grade; violations add noise
60
- grades = []
61
- for i in range(n):
62
- base = scores[i]
63
- penalty = violations[i] * 3 # higher code → worse grade
64
- effective = base - penalty
65
- if effective >= 60:
66
- grades.append(0) # A
67
- elif effective >= 40:
68
- grades.append(1) # B
69
- else:
70
- grades.append(2) # C
71
-
72
- X = np.column_stack([cuisines, violations, scores])
73
- y = np.array(grades)
74
- return X, y
75
-
76
-
77
- print("Training placeholder Random Forest model …")
78
- X_train, y_train = generate_synthetic_data()
79
- model = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1)
80
- model.fit(X_train, y_train)
81
- print("Model ready ✓")
82
-
83
-
84
- # ──────────────────────────────────────────────────────────────────────────────
85
- # 2. Prediction + chart function
86
- # ──────────────────────────────────────────────────────────────────────────────
87
-
88
- GRADE_COLORS = {
89
- "A": "#2ECC71", # green
90
- "B": "#F39C12", # amber
91
- "C": "#E74C3C", # red
92
- }
93
-
94
- def predict_grade(cuisine: str, violation: str, score: float):
95
- """Run inference and return a grade label and a probability bar chart."""
96
- X = encode_inputs(cuisine, violation, score)
97
- proba = model.predict_proba(X)[0] # shape (3,)
98
- pred_idx = int(np.argmax(proba))
99
- grade = GRADE_LABELS[pred_idx]
100
- confidence = proba[pred_idx] * 100
101
-
102
- # ── build the bar chart ──────────────────────────────────────────────────
103
- fig, ax = plt.subplots(figsize=(6, 3.5))
104
- fig.patch.set_facecolor("#1A1A2E")
105
- ax.set_facecolor("#16213E")
106
-
107
- bar_colors = [GRADE_COLORS[g] for g in GRADE_LABELS]
108
- bars = ax.bar(
109
- GRADE_LABELS,
110
- proba * 100,
111
- color=bar_colors,
112
- width=0.5,
113
- edgecolor="none",
114
- zorder=3,
115
- )
116
-
117
- # highlight the predicted grade with a glow border
118
- pred_bar = bars[pred_idx]
119
- pred_bar.set_linewidth(2.5)
120
- pred_bar.set_edgecolor("white")
121
-
122
- # value labels on bars
123
- for bar, p in zip(bars, proba * 100):
124
- ax.text(
125
- bar.get_x() + bar.get_width() / 2,
126
- bar.get_height() + 1.5,
127
- f"{p:.1f}%",
128
- ha="center", va="bottom",
129
- color="white", fontsize=11, fontweight="bold",
130
- )
131
-
132
- ax.set_ylim(0, 110)
133
- ax.set_xlabel("Predicted Grade", color="#AAAACC", fontsize=11, labelpad=8)
134
- ax.set_ylabel("Probability (%)", color="#AAAACC", fontsize=11, labelpad=8)
135
- ax.set_title(
136
- f"Model Confidence — Predicted Grade: {grade} ({confidence:.1f}%)",
137
- color="white", fontsize=13, fontweight="bold", pad=12,
138
- )
139
- ax.tick_params(colors="white", labelsize=12)
140
- for spine in ax.spines.values():
141
- spine.set_visible(False)
142
- ax.yaxis.grid(True, color="#2A2A4A", linewidth=0.8, zorder=0)
143
- ax.set_axisbelow(True)
144
-
145
- plt.tight_layout()
146
-
147
- # ── compose the text output ───────────────────────────────────────────────
148
- emoji = {"A": "🟢", "B": "🟡", "C": "🔴"}[grade]
149
- summary = (
150
- f"{emoji} Predicted Health Grade: **{grade}**\n\n"
151
- f"Confidence: {confidence:.1f}%\n\n"
152
- f"---\n"
153
- f"| Input | Value |\n"
154
- f"|---|---|\n"
155
- f"| Cuisine | {cuisine} |\n"
156
- f"| Violation | {violation} |\n"
157
- f"| Inspection Score | {score:.1f} |\n\n"
158
- f"*Note: This uses a placeholder Random Forest model trained on "
159
- f"synthetic data. Replace `generate_synthetic_data()` and re-train "
160
- f"with real inspection records for production use.*"
161
- )
162
-
163
- return summary, fig
164
-
165
-
166
- # ──────────────────────────────────────────────────────────────────────────────
167
- # 3. Gradio UI
168
- # ──────────────────────────────────────────────────────────────────────────────
169
-
170
- DESCRIPTION = """
171
- ## 🍽️ Restaurant Health Grade Predictor
172
-
173
- Enter inspection details below to get a predicted **A / B / C** health grade
174
- and a probability breakdown from the Random Forest model.
175
- """
176
-
177
- with gr.Blocks(
178
- title="Health Grade Predictor",
179
- theme=gr.themes.Soft(
180
- primary_hue="violet",
181
- secondary_hue="slate",
182
- neutral_hue="slate",
183
- ),
184
- css="""
185
- .predict-btn { font-size: 1.1rem !important; padding: 0.7rem !important; }
186
- #grade-output .prose { font-size: 1.05rem !important; }
187
- """,
188
- ) as demo:
189
-
190
- gr.Markdown(DESCRIPTION)
191
-
192
- with gr.Row():
193
- with gr.Column(scale=1):
194
- cuisine_input = gr.Dropdown(
195
- choices=CUISINE_TYPES,
196
- value="American",
197
- label="🍜 Cuisine Type",
198
- )
199
- violation_input = gr.Dropdown(
200
- choices=VIOLATION_CODES,
201
- value="No Violation",
202
- label="⚠️ Violation Code",
203
- )
204
- score_input = gr.Slider(
205
- minimum=0,
206
- maximum=100,
207
- value=85,
208
- step=0.5,
209
- label="📊 Inspection Score (0 = worst, 100 = best)",
210
- )
211
- predict_btn = gr.Button(
212
- "🔍 Predict Grade",
213
- variant="primary",
214
- elem_classes="predict-btn",
215
- )
216
-
217
- with gr.Column(scale=2):
218
- grade_output = gr.Markdown(
219
- value="*Fill in the inputs and click **Predict Grade**.*",
220
- elem_id="grade-output",
221
- )
222
- chart_output = gr.Plot(label="Grade Probability Distribution")
223
-
224
- predict_btn.click(
225
- fn=predict_grade,
226
- inputs=[cuisine_input, violation_input, score_input],
227
- outputs=[grade_output, chart_output],
228
- )
229
-
230
- gr.Examples(
231
- examples=[
232
- ["Italian", "No Violation", 95],
233
- ["Chinese", "04L - Evidence of mice or rats", 55],
234
- ["Mexican", "08A - Facility not sanitized", 40],
235
- ["Japanese", "02A - No food safety certificate",72],
236
- ["Mediterranean","15L - Workers not using proper hygiene", 30],
237
- ],
238
- inputs=[cuisine_input, violation_input, score_input],
239
- outputs=[grade_output, chart_output],
240
- fn=predict_grade,
241
- cache_examples=True,
242
- label="📌 Quick Examples",
243
- )
244
-
245
- gr.Markdown(
246
- """
247
- ---
248
- **How grades work (synthetic rules used for training)**
249
- `Effective Score = Inspection Score − (Violation Code Index × 3)`
250
- • **A** → Effective ≥ 60 &nbsp;|&nbsp; **B** → 40–59 &nbsp;|&nbsp; **C** → < 40
251
-
252
- Replace `generate_synthetic_data()` with a real labelled dataset to make this production-ready.
253
- """
254
- )
255
-
256
- if __name__ == "__main__":
257
- demo.launch(share=False)