LianHP commited on
Commit
1b4fadc
·
verified ·
1 Parent(s): 1613eae

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +48 -120
  2. shap_plot.png +0 -0
app.py CHANGED
@@ -1,147 +1,75 @@
1
  import gradio as gr
2
  import shap
3
  import xgboost as xgb
4
- import numpy as np
5
  import pandas as pd
 
6
  import matplotlib.pyplot as plt
7
 
8
- # Make sure matplotlib does not try to open any GUI backend
9
- plt.switch_backend("Agg")
10
-
11
- # ---------------------------
12
- # 1. CREATE SYNTHETIC DATA & TRAIN MODEL
13
- # ---------------------------
14
- np.random.seed(42)
15
-
16
- # Simple synthetic dataset: "health-like" features and a fake cost
17
- df = pd.DataFrame({
18
  "age": np.random.randint(20, 80, 200),
19
- "bmi": np.random.uniform(18, 35, 200),
20
- "steps": np.random.randint(2000, 14000, 200),
21
  })
 
22
 
23
- # Fake target: cost in dollars
24
- df["cost"] = (
25
- 10 * df["age"] +
26
- 50 * (df["bmi"] - 25) -
27
- 0.001 * df["steps"] +
28
- np.random.normal(0, 50, size=len(df))
29
- )
30
-
31
- FEATURE_COLUMNS = ["age", "bmi", "steps"]
32
-
33
- X = df[FEATURE_COLUMNS]
34
- y = df["cost"]
35
-
36
- # Train a tiny XGBoost regressor
37
- model = xgb.XGBRegressor(
38
- n_estimators=40,
39
- max_depth=3,
40
- learning_rate=0.1,
41
- subsample=0.8,
42
- colsample_bytree=0.8,
43
- random_state=42
44
- )
45
  model.fit(X, y)
46
 
47
- # ---------------------------
48
- # 2. BUILD A SHAP TREE EXPLAINER (SAFE FOR TREE MODELS)
49
- # ---------------------------
50
- # DO NOT use shap.Explainer(model, X) -> causes TypeError on some setups
51
  explainer = shap.TreeExplainer(model)
52
 
 
 
 
 
53
 
54
- # ---------------------------
55
- # 3. FUNCTION TO EXPLAIN A SINGLE PREDICTION
56
- # ---------------------------
57
- def explain_cost(age: float, bmi: float, steps: int):
58
- """
59
- Take user inputs, compute predicted cost, and generate a SHAP waterfall plot.
60
- Returns:
61
- - predicted cost (float)
62
- - path to saved waterfall PNG (string)
63
- """
64
- # Build a single-row DataFrame with the same columns as training
65
- input_df = pd.DataFrame([{
66
  "age": age,
67
  "bmi": bmi,
68
- "steps": steps
69
  }])
70
 
71
- # Model prediction
72
- pred = model.predict(input_df)[0]
73
 
74
- # Compute SHAP values for this single instance
75
- shap_explanation = explainer(input_df) # returns shap.Explanation object
76
 
77
- # Make a waterfall plot for the first (and only) instance
78
  plt.figure(figsize=(8, 5))
79
- shap.plots.waterfall(shap_explanation[0], show=False)
80
- plt.title("SHAP Waterfall Explanation", fontsize=12)
81
-
82
- # Save plot to file for Gradio to show
83
- output_path = "shap_waterfall.png"
84
  plt.tight_layout()
85
- plt.savefig(output_path, bbox_inches="tight")
86
  plt.close()
87
 
88
- # Return prediction and image path
89
- return float(pred), output_path
90
-
91
-
92
- # ---------------------------
93
- # 4. GRADIO UI
94
- # ---------------------------
95
- with gr.Blocks() as demo:
96
- gr.Markdown(
97
- """
98
- # SHAP Explainability Demo
99
-
100
- This app trains a tiny XGBoost regression model on synthetic data
101
- and explains each prediction using **SHAP TreeExplainer**.
102
-
103
- Adjust the sliders and click **Explain Prediction** to see:
104
- - The model's predicted cost
105
- - A SHAP waterfall plot showing how each feature pushes the prediction
106
- higher or lower relative to the model's base value.
107
- """
108
- )
109
-
110
- with gr.Row():
111
- age = gr.Slider(
112
- minimum=20,
113
- maximum=80,
114
- value=40,
115
- step=1,
116
- label="Age"
117
- )
118
- bmi = gr.Slider(
119
- minimum=18,
120
- maximum=35,
121
- value=25,
122
- step=0.1,
123
- label="BMI"
124
- )
125
- steps = gr.Slider(
126
- minimum=2000,
127
- maximum=15000,
128
- value=8000,
129
- step=500,
130
- label="Daily Steps"
131
- )
132
-
133
- explain_button = gr.Button("Explain Prediction")
134
-
135
- with gr.Row():
136
- pred_output = gr.Number(label="Predicted Cost ($)")
137
- shap_output = gr.Image(label="SHAP Waterfall", type="filepath")
138
-
139
- explain_button.click(
140
- fn=explain_cost,
141
- inputs=[age, bmi, steps],
142
- outputs=[pred_output, shap_output]
143
- )
144
 
145
- # For local debugging; on Hugging Face this is ignored but harmless
146
  if __name__ == "__main__":
147
  demo.launch(share=True)
 
1
  import gradio as gr
2
  import shap
3
  import xgboost as xgb
 
4
  import pandas as pd
5
+ import numpy as np
6
  import matplotlib.pyplot as plt
7
 
8
+ # -----------------------------
9
+ # 1. Load a simple demo model
10
+ # -----------------------------
11
+ # Create fake training data
12
+ np.random.seed(0)
13
+ X = pd.DataFrame({
 
 
 
 
14
  "age": np.random.randint(20, 80, 200),
15
+ "bmi": np.random.uniform(18, 40, 200),
16
+ "bp": np.random.uniform(80, 160, 200)
17
  })
18
+ y = 0.3*X["age"] + 0.5*X["bmi"] + 0.2*X["bp"] + np.random.normal(0, 3, 200)
19
 
20
+ model = xgb.XGBRegressor()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  model.fit(X, y)
22
 
23
+ # Correct SHAP explainer for XGBoost tree models
 
 
 
24
  explainer = shap.TreeExplainer(model)
25
 
26
+ # -----------------------------
27
+ # 2. Prediction + SHAP function
28
+ # -----------------------------
29
+ def predict_and_explain(age, bmi, bp):
30
 
31
+ df = pd.DataFrame([{
 
 
 
 
 
 
 
 
 
 
 
32
  "age": age,
33
  "bmi": bmi,
34
+ "bp": bp
35
  }])
36
 
37
+ # Prediction
38
+ pred = model.predict(df)[0]
39
 
40
+ # SHAP values
41
+ shap_values = explainer(df)
42
 
43
+ # SHAP waterfall plot
44
  plt.figure(figsize=(8, 5))
45
+ shap.plots.waterfall(shap_values[0], show=False)
 
 
 
 
46
  plt.tight_layout()
47
+ plt.savefig("shap_plot.png")
48
  plt.close()
49
 
50
+ return pred, "shap_plot.png"
51
+
52
+ # -----------------------------
53
+ # 3. Gradio Interface
54
+ # -----------------------------
55
+ inputs = [
56
+ gr.Number(label="Age"),
57
+ gr.Number(label="BMI"),
58
+ gr.Number(label="Blood Pressure")
59
+ ]
60
+
61
+ outputs = [
62
+ gr.Number(label="Prediction"),
63
+ gr.Image(label="SHAP Explanation")
64
+ ]
65
+
66
+ demo = gr.Interface(
67
+ fn=predict_and_explain,
68
+ inputs=inputs,
69
+ outputs=outputs,
70
+ title="XGBoost + SHAP Demo",
71
+ description="Working Hugging Face deployment without SHAP model errors."
72
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
 
74
  if __name__ == "__main__":
75
  demo.launch(share=True)
shap_plot.png CHANGED