Project Goal: To build a comprehensive machine learning pipeline that predicts daily room rates (Regression) and classifies bookings into pricing tiers (Classification), utilizing advanced feature engineering and clustering techniques.
Project Structure & Methodology
This project follows a structured 8-part pipeline:
Structure: A mix of numeric and categorical features (e.g., Lead Time, Room Type, Market Segment).
Part 2: Exploratory Data Analysis (EDA)
Before modeling, the raw dataset underwent a rigorous cleaning and analysis process to ensure data integrity and model stability.
Data Cleaning & Logic Filters
Missing Values: Handled nulls in agent and company columns by imputing with 0 (indicating direct bookings).
Duplicate Removal: Removed duplicate records to prevent data leakage and bias.
Logical Integrity: Filtered out invalid bookings where the total number of guests (Adults + Children + Babies) was 0.
Outlier Handling:
Detected extreme price anomalies (e.g., a single booking with ADR > $5,000).
Removed non-positive prices (ADR ≤ 0) representing complimentary rooms, as they distort regression targets.
Validation: Confirmed via boxplots that remaining outliers (e.g., high prices for luxury suites or long lead times) represent legitimate business behaviors rather than errors.
ADR Distribution
Key Visual Insights
Seasonality: A clear seasonal trend was observed, with August being the peak pricing month due to summer holidays, while January remains the lowest.
ADR by Month
Room Hierarchy: The assigned_room_type feature showed a distinct price hierarchy; Room types 'G' and 'H' consistently command significantly higher rates than standard 'A' rooms.
ADR by Room Type
Market Segments: 'Direct' and 'Online TA' (Travel Agents) segments typically pay higher rates compared to 'Groups' and 'Corporate' bookings, which likely benefit from negotiated discounts.
ADR by Market Segment
Correlation Analysis: The number of Children and Adults showed the strongest positive correlation with the price, validating that occupancy drives revenue.
Correlation Heatmap
Booking Behavior: The scatter plot of Lead Time vs. ADR reveals a slight negative trend, indicating that while early bookers often secure lower rates, the highest prices are frequently associated with last-minute "Spontaneous" bookings.
Relationship between Lead Time and Average Daily Rate
Part 3: Baseline Regression Model
To establish a performance benchmark, I developed a baseline Linear Regression model. This section details the setup, training, and initial evaluation.
Goal & Methodology
Regression Goal: Predict the continuous target variable adr (Average Daily Rate) to estimate the nightly room price.
Feature Selection & Preprocessing:
Selected all relevant numerical and categorical features.
Applied One-Hot Encoding to categorical variables (e.g., market_segment, reserved_room_type) to make them interpretable for the linear model.
Train-Test Split: Partitioned the data into 80% Training and 20% Testing sets using random_state=42 to ensure reproducibility.
Model Evaluation
I trained a standard LinearRegression model from Scikit-Learn. The model achieved moderate predictive power but highlighted the limitations of linear assumptions on this complex dataset.
Metric
Value
Interpretation
MAE
$22.02
On average, the prediction is off by ~$22.
RMSE
$29.91
Penalizes larger errors more heavily.
R² Score
0.65
The model explains 65% of the variance in price.
Key Insights & Feature Importance
By analyzing the Linear Coefficients, I identified the primary drivers of price:
Seasonality (Positive Impact): Months like August, July, and September had high positive coefficients, confirming that summer/peak seasons significantly drive up prices.
Room Type Anomalies (Negative Impact):assigned_room_type_L had a strong negative coefficient (-$135), identifying a specific low-cost category or booking anomaly.
Data Quality Issues: The presence of distribution_channel_Undefined as a negative predictor highlighted the need for the robust data cleaning performed in earlier steps.
Visual Analysis: The Actual vs. Predicted scatter plot showed that while the model captures the general trend, it struggles to predict extreme high-end prices (underestimation), suggesting the need for non-linear models (addressed in Part 5).
Actual vs Predicted
Part 4: Feature Engineering & Clustering
To significantly improve model performance, I moved beyond raw features and applied advanced Feature Engineering techniques. The highlight of this step was the creation of a meta-feature using Unsupervised Learning.
Feature Transformation & Scaling
Before applying clustering algorithms, data preprocessing was essential to ensure valid results:
Feature Selection: I selected specific behavioral features (e.g., lead_time, total_of_special_requests, total_stay) while strictly excluding the target variable (adr) to prevent Data Leakage.
Scaling: Since K-Means relies on Euclidean distance, unscaled features (like 'Lead Time' vs 'Adults') would bias the model. I utilized sklearn.preprocessing.StandardScaler to normalize all behavioral features to a mean of 0 and variance of 1.
Customer Segmentation (Clustering)
I employed K-Means Clustering (sklearn.cluster.KMeans) to uncover hidden patterns in customer behavior. By setting k=4, the algorithm identified four distinct customer personas.
Cluster Interpretation:
Cluster 0 - "Early Birds": Characterized by extremely high lead times (~6 months in advance) and longer stays. Likely planned vacations.
Cluster 1 - "Spontaneous / Short Stay": The largest segment. Bookings made close to the check-in date with short duration.
Cluster 2 - "Car Travelers": A distinct group defined almost exclusively by the request for Parking Spaces.
Cluster 3 - "Families": Defined by a high average count of Children/Babies. Crucial Insight: This segment consistently showed the highest ADR ($160) compared to others (~$100).
Visualization: To visualize these high-dimensional clusters in a 2D space, I used Principal Component Analysis (PCA) (sklearn.decomposition.PCA). The resulting scatter plot confirmed distinct separations between the groups.
New Feature Creation: The cluster labels (0, 1, 2, 3) were added back to the main dataset as a new categorical feature named Cluster. This enriched the subsequent supervised models (Regression/Classification) with "behavioral context" they wouldn't have derived from raw features alone.
Part 5: Improved Regression Models
Following the baseline evaluation, I aimed to improve prediction accuracy
Methodology
Retraining Baseline: I retrained the Linear Regression model using the updated dataset (including total_stay and Cluster features) to isolate the impact of feature engineering.
Advanced Models: I selected and trained two tree-based ensemble models from the Scikit-Learn and XGBoost libraries:
###Model Comparison Results
The models were evaluated on the test set using Mean Absolute Error (MAE) and R-Squared (R2).
Model
MAE (Error in $)
R2 Score
Performance
Linear Regression (Retrained)
22.01
0.65
Baseline
XGBoost
11.84
0.87
Strong
Random Forest
9.08
0.89
Best
###Discussion and Feature Importance
The Random Forest model achieved a dramatic performance boost, reducing the Mean Absolute Error by over 50% compared to the linear baseline.
Model Comparison R2
Top Features Random Forest
Reasons for Improvement:
Non-Linearity: Hotel pricing is inherently non-linear (e.g., prices spike sharply during holidays rather than linearly). Tree-based models capture these complex patterns effectively, whereas Linear Regression fails to do so.
Key Predictors: Feature importance analysis of the winning model revealed that arrival_date_week_number (granular seasonality) and children count are the strongest drivers of price.
The Cluster Feature: While the engineered Cluster feature provided valuable business insights during EDA, it did not appear in the top 10 predictors for the Random Forest model. This is likely due to information redundancy, as the model could extract the necessary patterns directly from the raw features (Lead Time, Guest Count) that made up the clusters.
Part 7: Regression to Classification
In this phase, I reframed the business problem from predicting the exact daily rate (Regression) to classifying bookings into pricing tiers (Classification). This facilitates strategic decision-making regarding market segmentation.
Target Transformation Strategy
Objective: Convert the continuous target adr into discrete classes.
Chosen Strategy: Quantile Binning
I discretized the target variable into 3 equal-sized classes:
Class 0 (Low/Budget): Bottom 33% of prices.
Class 1 (Medium/Standard): Middle 33% of prices.
Class 2 (High/Premium): Top 33% of prices.
Rationale:
I selected Quantile Binning over arbitrary thresholds to ensure a perfectly balanced dataset. This prevents the model from becoming biased toward a majority class (a common issue with manual cutoffs) and ensures equal learning opportunity for all price tiers.
Class Balance & Metric Selection
I performed a rigorous sanity check before training:
Verification: I analyzed the class distribution in both the Training set and the Test set separately.
Result: Both sets maintained a near-perfect distribution of ~33.3% per class, confirming that the random split did not introduce bias.
Class Distribution
Metric Strategy:
Accuracy: Since the classes are balanced, Accuracy serves as a valid baseline metric.
Business KPI (Precision): However, to avoid revenue loss from overpricing empty rooms ("Inventory Spoilage"), I prioritized Precision for Class 2 (High). Minimizing "False Positives" (predicting High when it is Low) is critical to avoid scaring away budget-conscious customers.
Part 8: Classification Models & Evaluation
In this final modeling phase, I trained and evaluated three distinct classifiers to predict the price tier (0, 1, 2).
Metric Selection: The "False Positive" Risk
While Accuracy is a valid metric due to our perfectly balanced dataset (achieved in Part 7), I introduced a critical business constraint: Minimizing False Positives for the 'High' class.
Risk Scenario: Predicting a room is 'High' (Premium) when it is actually 'Low' (Budget).
Consequence: The hotel sets an overpriced rate Potential customer leaves Room remains empty (Inventory Spoilage).
Decision: I prioritized Precision for Class 2 (High), as an empty room is financially more damaging than a slightly underpriced one.
Model Comparison Results
I benchmarked a linear classifier against non-linear tree-based models. The results clearly favored the ensemble approach:
Model
Overall Accuracy
'High' Class Precision
Interpretation
Logistic Regression
60%
0.66
Underperformed; failed to capture complex pricing rules.
Random Forest Classifier is the chosen model.
It achieved the highest overall accuracy (86%) and, crucially, a Precision of 0.89 for premium bookings. This means when the model predicts a "High" price tag, it is correct 89% of the time, significantly reducing the risk of driving customers away with inflated prices.
Project Conclusion
This project highlights the importance of a holistic approach: clean data, thoughtful feature engineering (Clustering), and selecting the right model for the task. The combination of visual exploration and advanced predictive techniques led to a robust pricing engine capable of adapting to seasonality and customer types with high accuracy.
How to Use
Load the trained models using Python:
python
1import joblib
2import pandas as pd
34# 1. Load Regression Model (Predicts exact price)5reg_model = joblib.load('hotel_price_prediction_model.pkl')67# 2. Load Classification Model (Predicts Price Tier 0-2)8clf_model = joblib.load('hotel_price_classifier_model.pkl')