Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import joblib | |
| import pandas as pd | |
| import numpy as np | |
| MODEL_PATH = 'src/r_tips.joblib' | |
| SCALER_PATH = 'src/scaler_tips.joblib' | |
| FEATURES = [ | |
| 'total_bill', 'size', 'bill_per_person', | |
| 'sex_Male', 'smoker_Yes', | |
| 'day_Sat', 'day_Sun', 'day_Thur', | |
| 'time_Lunch' | |
| ] | |
| NUMERICAL_COLS = ['total_bill', 'size', 'bill_per_person'] | |
| def load_assets(): | |
| try: | |
| model = joblib.load(MODEL_PATH) | |
| scaler = joblib.load(SCALER_PATH) | |
| return model, scaler | |
| except Exception as e: | |
| st.error(f"Error loading assets. Ensure '{MODEL_PATH}' and '{SCALER_PATH}' are uploaded. Error: {e}") | |
| return None, None | |
| def preprocess_and_predict(model, scaler, input_data): | |
| df_input = pd.DataFrame([input_data]) | |
| df_processed = pd.get_dummies(df_input, columns=["sex", "smoker", "day", "time"], drop_first=True) | |
| for col in FEATURES: | |
| if col not in df_processed.columns: | |
| df_processed[col] = 0 | |
| final_features = df_processed[FEATURES] | |
| numerical_part = final_features[NUMERICAL_COLS] | |
| scaled_numerical = scaler.transform(numerical_part) | |
| final_input_array = final_features.values.copy() | |
| final_input_array[:, 0:len(NUMERICAL_COLS)] = scaled_numerical | |
| prediction = model.predict(final_input_array) | |
| return float(prediction[0]) | |
| # --- Streamlit Interface --- | |
| st.set_page_config(page_title="Waiter Tip Predictor", layout="centered") | |
| st.title("💰 Waiter Tip Prediction") | |
| st.markdown("Enter bill details and dining context to predict the tip amount ($).") | |
| model, scaler = load_assets() | |
| if model is not None and scaler is not None: | |
| st.sidebar.header("Dining Details") | |
| total_bill = st.sidebar.number_input("Total Bill ($):", min_value=1.0, value=25.0, step=0.5) | |
| size = st.sidebar.number_input("Party Size:", min_value=1, max_value=10, value=3) | |
| bill_per_person = total_bill / size if size > 0 else 0 | |
| sex = st.sidebar.selectbox("Server/Diner Sex:", options=["Female", "Male"]) | |
| smoker = st.sidebar.selectbox("Smoker at Table?", options=["No", "Yes"]) | |
| day = st.sidebar.selectbox("Day of the Week:", options=["Thur", "Fri", "Sat", "Sun"]) | |
| time = st.sidebar.selectbox("Time of Day:", options=["Lunch", "Dinner"]) | |
| input_data = { | |
| 'total_bill': total_bill, | |
| 'size': size, | |
| 'bill_per_person': bill_per_person, | |
| 'sex': sex, | |
| 'smoker': smoker, | |
| 'day': day, | |
| 'time': time | |
| } | |
| st.subheader("Input Summary:") | |
| st.dataframe(pd.DataFrame([input_data]), hide_index=True) | |
| if st.button("Predict Tip Amount"): | |
| with st.spinner('Calculating prediction...'): | |
| predicted_tip = preprocess_and_predict(model, scaler, input_data) | |
| st.success("Prediction Successful!") | |
| st.markdown("### Predicted Tip:") | |
| st.markdown(f"**${predicted_tip:,.2f}**") | |
| st.info(f"The predicted tip is approximately {predicted_tip/total_bill:.1%} of the total bill.") |