Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| """ | |
| Streamlit App for Tourism Package Prediction | |
| """ | |
| %%writefile tourism_project/deployment/app.py | |
| import streamlit as st | |
| import pandas as pd | |
| import joblib | |
| from huggingface_hub import hf_hub_download | |
| import os | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Tourism Package Prediction", | |
| page_icon="โ๏ธ", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| font-size: 2.5rem; | |
| color: #1f77b4; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| .sub-header { | |
| font-size: 1.5rem; | |
| color: #2c3e50; | |
| margin-top: 1rem; | |
| margin-bottom: 1rem; | |
| } | |
| .prediction-box { | |
| padding: 2rem; | |
| border-radius: 10px; | |
| margin-top: 2rem; | |
| } | |
| .success-box { | |
| background-color: #d4edda; | |
| border: 2px solid #28a745; | |
| } | |
| .danger-box { | |
| background-color: #f8d7da; | |
| border: 2px solid #dc3545; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Cache the model loading to avoid reloading on every interaction | |
| def load_model_and_preprocessor(): | |
| """Load model and preprocessor from HuggingFace""" | |
| try: | |
| with st.spinner("Loading model and preprocessor from HuggingFace..."): | |
| model_path = hf_hub_download( | |
| repo_id="dararaje/Tourism_Package_Prediction", | |
| filename="tourism_model.pkl", | |
| repo_type="model" | |
| ) | |
| preprocessor_path = hf_hub_download( | |
| repo_id="dararaje/Tourism_Package_Prediction", | |
| filename="tourism_preprocessor.pkl", | |
| repo_type="model" | |
| ) | |
| model = joblib.load(model_path) | |
| preprocessor = joblib.load(preprocessor_path) | |
| return model, preprocessor | |
| except Exception as e: | |
| st.error(f"Error loading model: {str(e)}") | |
| st.error("Make sure you have run upload_model.py to upload the model files to HuggingFace") | |
| st.stop() | |
| # Load model and preprocessor | |
| model, preprocessor = load_model_and_preprocessor() | |
| # Main title | |
| st.markdown('<h1 class="main-header">๐ Tourism Package Prediction</h1>', unsafe_allow_html=True) | |
| st.markdown("### Predict if a customer will purchase the Tourism Package") | |
| st.markdown("---") | |
| # Create sidebar for information | |
| with st.sidebar: | |
| st.image("https://img.icons8.com/fluency/96/000000/around-the-world.png", width=100) | |
| st.markdown("## About This App") | |
| st.info( | |
| """ | |
| This application uses machine learning to predict whether a customer | |
| will purchase the Tourism Package based on: | |
| - Customer demographics | |
| - Travel preferences | |
| - Sales interaction quality | |
| """ | |
| ) | |
| st.markdown("## Model Information") | |
| st.markdown(""" | |
| - **Algorithm**: Machine Learning Classifier | |
| - **Features**: 18 customer attributes | |
| - **Output**: Purchase probability | |
| """) | |
| st.markdown("## How to Use") | |
| st.markdown(""" | |
| 1. Fill in customer details in the form | |
| 2. Click 'Predict Purchase Likelihood' | |
| 3. View prediction results with confidence scores | |
| """) | |
| # Create three columns for organized input | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.markdown('<p class="sub-header">๐ค Customer Demographics</p>', unsafe_allow_html=True) | |
| age = st.number_input("Age", min_value=18, max_value=100, value=30, step=1) | |
| gender = st.selectbox("Gender", options=["Male", "Female"]) | |
| marital_status = st.selectbox( | |
| "Marital Status", | |
| options=["Single", "Married", "Divorced", "Unmarried"] | |
| ) | |
| city_tier = st.selectbox( | |
| "City Tier", | |
| options=[1, 2, 3], | |
| format_func=lambda x: f"Tier {x} {'(Metro)' if x==1 else '(Tier-2)' if x==2 else '(Tier-3)'}" | |
| ) | |
| occupation = st.selectbox( | |
| "Occupation", | |
| options=["Salaried", "Small Business", "Large Business", "Free Lancer"] | |
| ) | |
| designation = st.selectbox( | |
| "Designation", | |
| options=["Executive", "Manager", "Senior Manager", "AVP", "VP"] | |
| ) | |
| monthly_income = st.number_input( | |
| "Monthly Income (โน)", | |
| min_value=0, | |
| max_value=1000000, | |
| value=20000, | |
| step=1000 | |
| ) | |
| with col2: | |
| st.markdown('<p class="sub-header">๐งณ Travel Preferences</p>', unsafe_allow_html=True) | |
| num_person_visiting = st.number_input( | |
| "Number of Persons Visiting", | |
| min_value=1, | |
| max_value=10, | |
| value=2, | |
| step=1 | |
| ) | |
| num_children_visiting = st.number_input( | |
| "Number of Children Visiting (below 5 years)", | |
| min_value=0, | |
| max_value=5, | |
| value=0, | |
| step=1 | |
| ) | |
| preferred_property_star = st.selectbox( | |
| "Preferred Property Star Rating", | |
| options=[3.0, 4.0, 5.0], | |
| format_func=lambda x: f"{int(x)} Star" | |
| ) | |
| num_trips = st.number_input( | |
| "Number of Trips per Year", | |
| min_value=0, | |
| max_value=20, | |
| value=2, | |
| step=1 | |
| ) | |
| passport = st.selectbox( | |
| "Has Passport?", | |
| options=[1, 0], | |
| format_func=lambda x: "Yes" if x == 1 else "No" | |
| ) | |
| own_car = st.selectbox( | |
| "Owns Car?", | |
| options=[1, 0], | |
| format_func=lambda x: "Yes" if x == 1 else "No" | |
| ) | |
| with col3: | |
| st.markdown('<p class="sub-header">๐ผ Sales Interaction Details</p>', unsafe_allow_html=True) | |
| type_of_contact = st.selectbox( | |
| "Type of Contact", | |
| options=["Company Invited", "Self Inquiry"] | |
| ) | |
| product_pitched = st.selectbox( | |
| "Product Pitched", | |
| options=["Basic", "Standard", "Deluxe", "Super Deluxe", "King"] | |
| ) | |
| pitch_satisfaction_score = st.slider( | |
| "Pitch Satisfaction Score", | |
| min_value=1, | |
| max_value=5, | |
| value=3, | |
| step=1 | |
| ) | |
| num_followups = st.number_input( | |
| "Number of Follow-ups", | |
| min_value=0, | |
| max_value=10, | |
| value=3, | |
| step=1 | |
| ) | |
| duration_of_pitch = st.number_input( | |
| "Duration of Pitch (minutes)", | |
| min_value=0, | |
| max_value=120, | |
| value=15, | |
| step=1 | |
| ) | |
| # Center the predict button | |
| st.markdown("---") | |
| col_button1, col_button2, col_button3 = st.columns([1, 1, 1]) | |
| with col_button2: | |
| predict_button = st.button("๐ฎ Predict Purchase Likelihood", type="primary", use_container_width=True) | |
| # Prediction logic | |
| if predict_button: | |
| try: | |
| # Create input dataframe | |
| input_data = pd.DataFrame({ | |
| 'Age': [age], | |
| 'TypeofContact': [type_of_contact], | |
| 'CityTier': [city_tier], | |
| 'Occupation': [occupation], | |
| 'Gender': [gender], | |
| 'NumberOfPersonVisiting': [num_person_visiting], | |
| 'PreferredPropertyStar': [preferred_property_star], | |
| 'MaritalStatus': [marital_status], | |
| 'NumberOfTrips': [num_trips], | |
| 'Passport': [passport], | |
| 'OwnCar': [own_car], | |
| 'NumberOfChildrenVisiting': [num_children_visiting], | |
| 'Designation': [designation], | |
| 'MonthlyIncome': [monthly_income], | |
| 'PitchSatisfactionScore': [pitch_satisfaction_score], | |
| 'ProductPitched': [product_pitched], | |
| 'NumberOfFollowups': [num_followups], | |
| 'DurationOfPitch': [duration_of_pitch] | |
| }) | |
| # Preprocess and predict | |
| processed_data = preprocessor.transform(input_data) | |
| prediction = model.predict(processed_data) | |
| probability = model.predict_proba(processed_data) | |
| # Display results | |
| st.markdown("---") | |
| if prediction[0] == 1: | |
| st.markdown('<div class="prediction-box success-box">', unsafe_allow_html=True) | |
| st.markdown("### โ Prediction: WILL PURCHASE") | |
| st.markdown(f"#### Confidence: {probability[0][1] * 100:.2f}%") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| else: | |
| st.markdown('<div class="prediction-box danger-box">', unsafe_allow_html=True) | |
| st.markdown("### โ Prediction: WILL NOT PURCHASE") | |
| st.markdown(f"#### Confidence: {probability[0][0] * 100:.2f}%") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Probability breakdown | |
| st.markdown("### ๐ Probability Breakdown") | |
| col_prob1, col_prob2 = st.columns(2) | |
| with col_prob1: | |
| st.metric( | |
| label="Purchase Probability", | |
| value=f"{probability[0][1] * 100:.2f}%", | |
| delta=f"{(probability[0][1] - 0.5) * 100:.2f}% from baseline" | |
| ) | |
| with col_prob2: | |
| st.metric( | |
| label="No Purchase Probability", | |
| value=f"{probability[0][0] * 100:.2f}%", | |
| delta=f"{(probability[0][0] - 0.5) * 100:.2f}% from baseline" | |
| ) | |
| # Progress bars for visualization | |
| st.markdown("#### Visual Probability Distribution") | |
| st.progress(probability[0][1], text=f"Purchase: {probability[0][1] * 100:.1f}%") | |
| st.progress(probability[0][0], text=f"No Purchase: {probability[0][0] * 100:.1f}%") | |
| # Recommendation | |
| st.markdown("### ๐ก Recommendation") | |
| if prediction[0] == 1: | |
| if probability[0][1] > 0.75: | |
| st.success("**High Priority Lead**: Strong likelihood of purchase. Recommend immediate follow-up with premium package details.") | |
| else: | |
| st.info("**Moderate Priority Lead**: Good potential for purchase. Consider personalized follow-up with package benefits.") | |
| else: | |
| if probability[0][0] > 0.75: | |
| st.warning("**Low Priority Lead**: Low likelihood of purchase. May require additional nurturing or different product offering.") | |
| else: | |
| st.info("**Uncertain Lead**: Probability is borderline. Additional information or engagement might help.") | |
| except Exception as e: | |
| st.error(f"Error making prediction: {str(e)}") | |
| st.exception(e) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style='text-align: center; color: #7f8c8d;'> | |
| <p>Built with โค๏ธ using Streamlit and HuggingFace | Tourism Package Prediction MLOps Project</p> | |
| </div> | |
| """, unsafe_allow_html=True) |