VJBharathkumar commited on
Commit
395fcc8
·
verified ·
1 Parent(s): 16b6754

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +187 -0
  2. requirements.txt +6 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import joblib
3
+ import numpy as np
4
+ import pandas as pd
5
+ import streamlit as st
6
+ from huggingface_hub import hf_hub_download
7
+
8
+ # -------------------------
9
+ # CONFIG (EDIT IF NEEDED)
10
+ # -------------------------
11
+ HF_MODEL_REPO = "VJBharathkumar/tourism-prod-prediction" # <-- your model repo on HF
12
+ HF_DATASET_REPO = "VJBharathkumar/tourism-wellness" # <-- your dataset repo on HF
13
+ MODEL_FILENAME = "model.joblib"
14
+ METRICS_FILENAME = "metrics.json"
15
+ TRAIN_FILENAME_IN_DATASET = "train.csv" # uploaded in Step 5
16
+
17
+ TARGET = "ProdTaken"
18
+
19
+ # These are the expected feature columns (18) from your dataset
20
+ FEATURE_COLS = [
21
+ "Age",
22
+ "TypeofContact",
23
+ "CityTier",
24
+ "DurationOfPitch",
25
+ "Occupation",
26
+ "Gender",
27
+ "NumberOfPersonVisiting",
28
+ "NumberOfFollowups",
29
+ "ProductPitched",
30
+ "PreferredPropertyStar",
31
+ "MaritalStatus",
32
+ "NumberOfTrips",
33
+ "Passport",
34
+ "PitchSatisfactionScore",
35
+ "OwnCar",
36
+ "NumberOfChildrenVisiting",
37
+ "Designation",
38
+ "MonthlyIncome",
39
+ ]
40
+
41
+ @st.cache_resource
42
+ def load_model_and_metadata():
43
+ model_path = hf_hub_download(
44
+ repo_id=HF_MODEL_REPO,
45
+ filename=MODEL_FILENAME,
46
+ repo_type="model",
47
+ )
48
+ model = joblib.load(model_path)
49
+
50
+ metrics = None
51
+ try:
52
+ metrics_path = hf_hub_download(
53
+ repo_id=HF_MODEL_REPO,
54
+ filename=METRICS_FILENAME,
55
+ repo_type="model",
56
+ )
57
+ with open(metrics_path, "r", encoding="utf-8") as f:
58
+ metrics = json.load(f)
59
+ except Exception:
60
+ metrics = None
61
+
62
+ return model, metrics
63
+
64
+ @st.cache_data
65
+ def load_train_for_ui_hints():
66
+ """
67
+ Pull train.csv from HF dataset repo to:
68
+ - get dropdown options for categorical columns
69
+ - get min/max for numeric sliders
70
+ """
71
+ train_path = hf_hub_download(
72
+ repo_id=HF_DATASET_REPO,
73
+ filename=TRAIN_FILENAME_IN_DATASET,
74
+ repo_type="dataset",
75
+ )
76
+ df = pd.read_csv(train_path)
77
+
78
+ # If ProdTaken exists, drop it for UI feature work
79
+ if TARGET in df.columns:
80
+ df = df.drop(columns=[TARGET])
81
+
82
+ # Keep only expected features (protects against accidental extra columns)
83
+ df = df[[c for c in FEATURE_COLS if c in df.columns]].copy()
84
+ return df
85
+
86
+ def build_input_form(train_df: pd.DataFrame) -> pd.DataFrame:
87
+ st.subheader("Enter customer details")
88
+
89
+ # Determine categorical vs numeric from training df
90
+ cat_cols = train_df.select_dtypes(include=["object"]).columns.tolist()
91
+ num_cols = [c for c in train_df.columns if c not in cat_cols]
92
+
93
+ left, right = st.columns(2)
94
+ values = {}
95
+
96
+ # Helper to draw widget
97
+ def draw_widget(col_name, container):
98
+ if col_name in cat_cols:
99
+ options = sorted([x for x in train_df[col_name].dropna().unique().tolist()])
100
+ default = options[0] if options else ""
101
+ values[col_name] = container.selectbox(col_name, options=options, index=0)
102
+ else:
103
+ # numeric
104
+ series = pd.to_numeric(train_df[col_name], errors="coerce")
105
+ min_v = float(np.nanmin(series.values))
106
+ max_v = float(np.nanmax(series.values))
107
+ med_v = float(np.nanmedian(series.values))
108
+
109
+ # If it's basically an integer field, use number_input with step 1
110
+ if np.all(np.isclose(series.dropna() % 1, 0)):
111
+ values[col_name] = container.number_input(
112
+ col_name,
113
+ min_value=int(min_v),
114
+ max_value=int(max_v),
115
+ value=int(round(med_v)),
116
+ step=1,
117
+ )
118
+ else:
119
+ values[col_name] = container.number_input(
120
+ col_name,
121
+ min_value=float(min_v),
122
+ max_value=float(max_v),
123
+ value=float(med_v),
124
+ )
125
+
126
+ # Alternate columns for nicer layout
127
+ for i, col_name in enumerate(FEATURE_COLS):
128
+ if col_name not in train_df.columns:
129
+ continue
130
+ container = left if i % 2 == 0 else right
131
+ draw_widget(col_name, container)
132
+
133
+ input_df = pd.DataFrame([values], columns=[c for c in FEATURE_COLS if c in values])
134
+ return input_df
135
+
136
+ def main():
137
+ st.set_page_config(page_title="Tourism Package Prediction", layout="wide")
138
+
139
+ st.title("Tourism Package Prediction")
140
+ st.write("Predict whether the customer will take the package (`ProdTaken = 1`).")
141
+
142
+ model, metrics = load_model_and_metadata()
143
+ train_df = load_train_for_ui_hints()
144
+
145
+ # Sidebar: show metrics + model info
146
+ with st.sidebar:
147
+ st.header("Model Info")
148
+ st.write(f"Model repo: `{HF_MODEL_REPO}`")
149
+ if metrics:
150
+ st.subheader("Test Metrics")
151
+ st.write(f"Accuracy: **{metrics.get('accuracy', 'NA')}**")
152
+ st.write(f"F1: **{metrics.get('f1', 'NA')}**")
153
+ st.write(f"ROC-AUC: **{metrics.get('roc_auc', 'NA')}**")
154
+ else:
155
+ st.info("metrics.json not found in model repo (optional).")
156
+
157
+ input_df = build_input_form(train_df)
158
+
159
+ st.divider()
160
+
161
+ predict_btn = st.button("Predict", type="primary")
162
+
163
+ if predict_btn:
164
+ # Ensure column order matches training expectation
165
+ input_df = input_df[[c for c in FEATURE_COLS if c in input_df.columns]].copy()
166
+
167
+ proba = None
168
+ pred = None
169
+
170
+ # Some sklearn models support predict_proba; our pipeline does
171
+ pred = int(model.predict(input_df)[0])
172
+ proba = float(model.predict_proba(input_df)[0][1])
173
+
174
+ st.subheader("Prediction")
175
+ st.write(f"Predicted class: **{pred}** (1 = will take package, 0 = will not)")
176
+ st.write(f"Probability of ProdTaken=1: **{proba:.3f}**")
177
+
178
+ if pred == 1:
179
+ st.success("Likely to take the package ✅")
180
+ else:
181
+ st.warning("Unlikely to take the package ⚠️")
182
+
183
+ with st.expander("Show input row"):
184
+ st.dataframe(input_df)
185
+
186
+ if __name__ == "__main__":
187
+ main()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ numpy
4
+ scikit-learn
5
+ joblib
6
+ huggingface_hub