Sukhjeet Singh
Machine Learning
12 Nov 2025
15 min read

Hotel Booking Cancellation Prediction — EDA & Machine Learning

Applying exploratory data analysis and four classification models to predict whether a hotel reservation will be cancelled and what that means for revenue management in the hospitality industry.

View Repository

Introduction

A guest books a hotel room three weeks in advance, then cancels the day before arrival. For the hotel, that's a room sitting empty, staff scheduled unnecessarily, and revenue that never materialised. Multiply that across hundreds of reservations a month and the financial impact becomes significant.

Last-minute cancellations are one of the hospitality industry's most persistent operational challenges. But what if a hotel could predict at the time of booking — whether a reservation was likely to be cancelled? It could adjust overbooking policies, offer targeted incentives to at-risk bookings, or allocate staff and inventory more efficiently.

This project tackles exactly that problem. Using a real-world hotel reservations dataset of 36,275 bookings, I applied exploratory data analysis (EDA) and four machine learning classification models to predict cancellation outcomes — and evaluated which approach performed best.


The Dataset

The dataset was sourced from Kaggle's "Hotel Reservations Dataset" a structured, business-relevant collection of booking records containing 36,275 entries and 19 attributes. The target variable is booking_status, a binary label indicating whether a reservation was Cancelled or Not_Cancelled.

AttributeDescription
no_of_adultsNumber of adults in the booking
no_of_weekend_nightsNumber of weekend nights reserved
no_of_week_nightsNumber of weeknights reserved
type_of_meal_planMeal plan selected by the guest
room_type_reservedCategory of room booked
booking_channelChannel through which the booking was made
no_of_special_requestsNumber of special requests submitted
lead_timeDays between booking and arrival
booking_statusTarget: Cancelled / Not_Cancelled

Key features like lead_time (how far in advance the booking was made) and no_of_special_requests are intuitively linked to cancellation behaviour guests who book far ahead or make no special requests may be less committed to their booking.


Project Workflow

The project follows a structured, end-to-end data science pipeline across six stages:

01

Dataset Acquisition

The Hotel Reservations Dataset was sourced from Kaggle. It required no scraping or API access — a clean CSV download ready for analysis.

02

Exploratory Data Analysis (EDA)

Univariate and bivariate analysis using Matplotlib and Seaborn to understand distributions, correlations, and patterns in booking behaviour. Key visualisations included cancellation rate breakdowns by room type, meal plan, and lead time.

03

Data Cleaning & Preprocessing

Handling missing values, encoding categorical variables, and scaling numerical features. Categorical columns like room type and meal plan were label-encoded for model compatibility.

04

Feature Selection

Identifying the most predictive features to reduce noise and improve model generalisation. Correlation analysis and feature importance scores from tree-based models guided the selection.

05

Model Training & Evaluation

Four classification models were trained on an 80/20 train-test split and evaluated across multiple metrics.

06

Interpretation of Results

Comparing model performance and drawing business insights from the predictions — which features drive cancellations, and what actions hotels could take.


Exploratory Data Analysis

Before training any model, EDA was used to understand the shape of the data and surface the signals most likely to predict cancellation.

Class Distribution

The dataset has a moderate class imbalance, higher proportion of non-cancelled bookings than cancelled ones. Understanding this upfront is important because it affects how accuracy metrics should be interpreted: a model that predicts "not cancelled" for every booking would score high on raw accuracy but be operationally useless.

Lead Time vs Cancellation

One of the clearest patterns to emerge from EDA is the relationship between lead_time and cancellation rate. Bookings made further in advance tend to have higher cancellation rates guests who book months ahead are more likely to change their plans. This makes lead_time one of the strongest individual predictors in the dataset.

Special Requests as a Commitment Signal

Guests who submit special requests (e.g., room preferences, dietary requirements) show lower cancellation rates. A special request is a signal of commitment — the guest has put thought into their stay. Bookings with zero special requests are meaningfully more likely to be cancelled, making no_of_special_requests a valuable feature from a business logic perspective as well as statistically.

Tools Used for EDA

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# Load dataset
df = pd.read_csv('hotel_reservations.csv')

# Class distribution
df['booking_status'].value_counts(normalize=True).plot(kind='bar')
plt.title('Cancellation Rate Distribution')
plt.show()

# Lead time vs cancellation
sns.boxplot(x='booking_status', y='lead_time', data=df)
plt.title('Lead Time by Booking Status')
plt.show()

# Special requests vs cancellation
sns.countplot(x='no_of_special_requests', hue='booking_status', data=df)
plt.title('Special Requests vs Booking Status')
plt.show()

Data Cleaning & Preprocessing

The dataset was relatively clean, but several preprocessing steps were required before it could be fed into machine learning models:

  • Encoding categorical variables — columns like type_of_meal_plan, room_type_reserved, and booking_channel were label-encoded into numeric values.
  • Target encoding — the booking_status column was mapped to binary values: Canceled = 1, Not_Canceled = 0.
  • Feature scaling numerical features were standardised using StandardScaler to ensure distance-based models like KNN are not biased by the scale of individual features.
  • Train-test split the dataset was split 80/20 into training and test sets using a fixed random state to ensure reproducibility.
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split

le = LabelEncoder()
for col in ['type_of_meal_plan', 'room_type_reserved', 'booking_channel']:
    df[col] = le.fit_transform(df[col])

df['booking_status'] = df['booking_status'].map({'Canceled': 1, 'Not_Canceled': 0})

X = df.drop('booking_status', axis=1)
y = df['booking_status']

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.2, random_state=42
)

Machine Learning Models

Four classification models were trained and evaluated, chosen to represent a range of approaches from simple linear classifiers to ensemble methods.

1. Logistic Regression

The baseline model. Logistic regression fits a linear decision boundary and outputs a probability score for each class. It's interpretable the coefficients directly indicate how each feature pushes the prediction toward cancellation or not. While it may underfit complex non-linear patterns, it provides a solid performance benchmark and is fast to train.

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression(random_state=42, max_iter=1000)
lr.fit(X_train, y_train)
lr_pred = lr.predict(X_test)

2. Decision Tree

A decision tree splits the data on the most informative features at each node, building a tree of if-then rules. It's highly interpretable you can visualise the exact path from booking features to a cancellation prediction. However, decision trees are prone to overfitting without careful depth limiting, which was applied here.

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(max_depth=10, random_state=42)
dt.fit(X_train, y_train)
dt_pred = dt.predict(X_test)

3. Random Forest

An ensemble of decision trees, each trained on a random subset of features and data. Random Forest reduces the overfitting tendency of individual trees by averaging predictions across many trees. It also provides feature importance scores a useful byproduct for understanding which booking attributes drive cancellations most.

from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
rf_pred = rf.predict(X_test)

# Feature importance
importances = pd.Series(rf.feature_importances_, index=X.columns)
importances.sort_values(ascending=False).head(10).plot(kind='bar')
plt.title('Top 10 Feature Importances — Random Forest')
plt.show()

4. K-Nearest Neighbors (KNN)

KNN classifies a booking by finding the k most similar bookings in the training set and taking a majority vote of their outcomes. It's a non-parametric model no explicit training phase but sensitive to feature scale (hence the StandardScaler applied earlier) and can be slower to predict on large datasets. It provides a useful contrast to the tree-based approaches.

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
knn_pred = knn.predict(X_test)

Evaluation & Results

Each model was evaluated using accuracy, precision, recall, F1-score, and a confusion matrix. In a cancellation prediction context, recall matters as much as accuracy missing a true cancellation (a false negative) is a costly error for a hotel that could have acted to retain that booking.

from sklearn.metrics import classification_report, confusion_matrix, accuracy_score

models = {
    'Logistic Regression': lr_pred,
    'Decision Tree':       dt_pred,
    'Random Forest':       rf_pred,
    'KNN':                 knn_pred,
}

for name, pred in models.items():
    print(f"--- {name} ---")
    print(f"Accuracy: {accuracy_score(y_test, pred):.4f}")
    print(classification_report(y_test, pred))
    print(confusion_matrix(y_test, pred))
    print()

Summary of Model Performance

ModelAccuracyPrecisionRecallF1-Score
Logistic Regression~79%~78%~79%~78%
Decision Tree~85%~85%~85%~85%
Random Forest~89%~89%~89%~89%
KNN~83%~83%~83%~83%

Note: Performance figures are indicative based on the dataset and standard hyperparameters. Exact values are available in the notebook.

Key Finding: Random Forest Wins

Random Forest was the strongest performer across all metrics. Its ability to aggregate many decision trees — each capturing different feature interactions made it well-suited to this tabular dataset where the relationship between features and cancellation is non-linear. The feature importance output also revealed that lead_time, no_of_special_requests, and the number of nights booked were consistently among the top predictors — aligning well with the patterns uncovered during EDA.


Business Insights

Beyond the model metrics, the analysis surfaces actionable insights for hotel operations:

  • Target long lead-time bookings for retention. Reservations made many weeks in advance are statistically more likely to be cancelled. Hotels could send tailored reminders or offer small incentives (early check-in, room upgrades) to bookings with high lead times and no special requests.
  • Use special requests as a health signal. Zero special requests at the time of booking is a mild cancellation risk indicator. Prompting guests to personalise their stay (meal preferences, room type) shortly after booking could both reduce cancellations and improve the guest experience.
  • Overbooking policy calibration. A model scoring above 85% accuracy enables more principled overbooking decisions — rather than applying a flat overbooking rate, hotels can use predicted cancellation probability per booking to optimise occupancy dynamically.
  • Revenue management integration. Predicted cancellation probability could be a direct input into dynamic pricing models — higher-risk bookings might be offered at a discount to improve commitment, while lower-risk bookings command full rate.

Potential Improvements

There are several directions this project could be extended for a production or research context:

  • Gradient boosting models — XGBoost or LightGBM would likely outperform Random Forest on this dataset, as they are optimised for tabular data and offer stronger regularisation.
  • Hyperparameter tuning — GridSearchCV or RandomizedSearchCV on the Random Forest (number of trees, max depth, min samples split) could squeeze additional performance.
  • Class imbalance handling — techniques like SMOTE (Synthetic Minority Oversampling) or class-weight adjustments could improve recall on the minority (cancelled) class.
  • Temporal validation — splitting the dataset by date rather than randomly would give a more realistic evaluation of how the model generalises to future bookings.
  • SHAP values — using SHAP (SHapley Additive exPlanations) on the Random Forest would provide per-prediction interpretability, making the model more trustworthy in an operational setting.

Conclusion

This project demonstrates that machine learning can be meaningfully applied to a real operational problem in the hospitality industry. Using a structured dataset of 36,275 hotel bookings, four classification models were trained and evaluated with Random Forest emerging as the best performer at approximately 89% accuracy.

Beyond the technical results, the project highlights how EDA and model interpretability tools can surface genuine business insights: that lead time and guest engagement (via special requests) are strong signals of cancellation risk, and that this information can directly inform hotel revenue and operations strategy.

The full implementation including the EDA notebooks, preprocessing pipeline, and model training code is available in the GitHub repository below.