ML in Industry · Travel & Hospitality
How Travel Companies Use Machine Learning for Business Growth
Quick summary — ML in travel
Travel is one of the most ML-heavy industries, after ads and finance. Airlines, OTAs (MakeMyTrip, Booking, Expedia), hotels and ride-hailing services use ML for pricing, forecasting, ranking, personalisation and fraud. Every one of those is a data science role inside the company.
In this guide you will learn:
- Dynamic pricing — how fares are set per user, per search.
- Demand forecasting — predicting seats, rooms and surges.
- Personalisation — recommendations and ranking.
- Fraud detection — the hidden ML layer.
- Skills you need — the data science stack for a travel role.
SECTION 01Dynamic pricing — how fares are set in real time
Every flight and hotel price you see is calculated by a model in milliseconds. Here's the shape of it:
| Input feature | Example | Why it matters | Signal strength |
|---|---|---|---|
| Days to departure | 3 days before | Last-minute = higher willingness to pay | Very strong |
| Remaining seats | 12 of 180 | Scarcity drives price up | Very strong |
| Search history | 5th search this session | Repeated intent signals high interest | Strong |
| Competitor prices | ₹4,500 on a rival | Relative pricing matters | Strong |
| Day of week | Friday evening | Weekend demand peaks | Medium |
| Weather at destination | Monsoon | Suppresses leisure demand | Medium |
| User segment | Business traveller | Less price-sensitive | Medium |
| Time of search | 2 AM | Lower urgency historically | Weak |
# A simplified dynamic pricing model
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split
# Load historical search + booking data
df = pd.read_parquet("flights.parquet")
# Target: did the user book at this price?
# (Or: what price maximizes expected revenue?)
df["booked"] = (df["booking_id"].notna()).astype(int)
FEATURES = [
"days_to_departure",
"seats_remaining",
"searches_this_session",
"competitor_price",
"is_weekend",
"user_segment_code",
"route_popularity",
]
X = df[FEATURES]
y = df["booked"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, shuffle=False # time-based split
)
model = GradientBoostingRegressor(
n_estimators=300,
learning_rate=0.05,
max_depth=4,
)
model.fit(X_train, y_train)
# Score each candidate price
def recommend_price(features, candidates):
best = None
best_score = -1
for price in candidates:
f = features.copy()
f["price"] = price
# Expected revenue = P(book | price) * price
score = model.predict([f])[0] * price
if score > best_score:
best_score = score
best = price
return best
# Real models are far more complex — this is the idea.
# You're not predicting a price. You're predicting
# P(book) and maximizing expected revenue.
Features that actually move the needle:
1. URGENCY SIGNALS
- days_to_departure
- hours_since_first_search
- number_of_searches_in_session
- days_since_last_search_on_this_route
2. SCARCITY SIGNALS
- seats_remaining_on_this_flight
- seats_remaining_on_similar_flights
- booking_velocity_last_24h
3. COMPETITIVE SIGNALS
- competitor_price_same_route
- price_delta_vs_cheapest
4. CONTEXTUAL SIGNALS
- day_of_week_departure
- day_of_week_booking
- holidays_within_7_days
- weather_at_destination
- events_at_destination
5. USER SIGNALS
- segment (business / leisure / group)
- past_booking_frequency
- past_avg_spend
- loyalty_tier
Features to be careful about:
✗ gender / age (often legally problematic)
✗ device_type (proxy for income — often banned)
✗ postcode (proxy for ethnicity)
✗ browser history (privacy)
Rule: the best features are behavioural
and contextual — not demographic.
SECTION 02Demand forecasting — predicting seats, rooms and surges
Before pricing, travel companies have to predict how much demand there will be. Here's what that looks like:
| Forecast | Time horizon | Used for | Model type |
|---|---|---|---|
| Flight load | 0-90 days | Inventory, pricing, overbooking | Gradient boosting + time-series |
| Hotel occupancy | 1-30 days | Room rates, staffing | Time-series (Prophet, ARIMA) |
| Search demand | 1-14 days | Ad bidding, server capacity | Gradient boosting |
| Ride-hailing surge | 0-60 minutes | Price multipliers | Real-time gradient boosting |
| Churn prediction | 0-90 days | Retention campaigns | Classification |
# demand_forecast.py
import pandas as pd
from prophet import Prophet
from sklearn.metrics import mean_absolute_percentage_error
# Load daily bookings for one route
df = pd.read_csv("route_bookings.csv", parse_dates=["date"])
df = df.rename(columns={"date": "ds", "bookings": "y"})
# Seasonal forecast — holidays, weekends, festivals
model = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
daily_seasonality=False,
changepoint_prior_scale=0.05, # allow some trend change
)
model.add_country_holidays(country_name="IN")
model.fit(df)
# Forecast next 90 days
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)
# MAPE on last 30 days (backtest)
train = df[:-30]
test = df[-30:]
model_train = Prophet(
yearly_seasonality=True,
weekly_seasonality=True,
).fit(train)
pred = model_train.predict(test[["ds"]])
mape = mean_absolute_percentage_error(test["y"], pred["yhat"])
print(f"MAPE: {mape:.2%}")
# Real systems add:
# - per-route models (or a global model with route embeddings)
# - weather and event features
# - booking-curve features (how fast it's selling)
# - competitor load as a proxy for demand
# The output is not a number — it's a curve
# the business can plan against.
Backtest properly — time series has traps:
BAD (random split):
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
✗ Leaks future into training
✗ Overstates accuracy
✗ Fails in production
GOOD (time-based split):
train = df[df["ds"] < cutoff]
test = df[df["ds"] >= cutoff]
✓ Respects time
✓ Matches production
BEST (walk-forward validation):
for each week in the last 12 weeks:
train on data up to that week
predict the week
record error
average errors
Why walk-forward matters:
- Seasonality changes
- Demand shifts
- Competitor behaviour changes
- A model that "worked" 2 years ago may
fail today
The single most common mistake in travel
forecasting:
reporting MAPE from a random split,
then failing in production.
Interviewers ask about this directly.
SECTION 03Personalisation, ranking and fraud detection
These three quietly drive most of the growth in travel apps. Here's how each one works:
| Problem | ML approach | Impact | Tools |
|---|---|---|---|
| Which hotels to show first? | Learning to rank (LambdaMART) | +5-15% booking rate | XGBoost ranker, LightGBM |
| What to recommend? | Collaborative + content-based | +10-20% CTR | Two-tower model, matrix factorisation |
| Should we offer this user a coupon? | Uplift modelling | Better ROI on discounts | Causal ML (CausalML, EconML) |
| Is this booking fraud? | Anomaly detection + classification | Prevents chargebacks and refund abuse | Isolation Forest, XGBoost |
| Will this user churn? | Classification | Retention campaigns before they leave | Gradient boosting + SHAP |
# A ranking model for hotel search
import lightgbm as lgb
import pandas as pd
# Each row = one hotel shown in one search
# Each search has multiple hotels (a "group")
df = pd.read_parquet("search_impressions.parquet")
df = df.sort_values(["search_id", "position"])
features = [
"price",
"star_rating",
"review_score",
"distance_to_centre",
"user_affinity_to_city",
"past_click_rate_for_similar",
]
# Groups = how many hotels were shown per search
group_sizes = df.groupby("search_id").size().values
labels = df["clicked"].values # or "booked" for booking ranker
ranker = lgb.LGBMRanker(
objective="lambdarank",
n_estimators=300,
learning_rate=0.05,
)
ranker.fit(
df[features],
labels,
group=group_sizes,
)
# The model learns to order hotels within
# each search — not to score them in isolation.
# Why this matters in travel:
# A user sees 20 hotels. The first 3 get 80%
# of clicks. Ranking moves revenue far more
# than model accuracy.
# Fraud detection for travel bookings
import pandas as pd
from sklearn.ensemble import IsolationForest
from sklearn.model_selection import train_test_split
# Load labelled booking data (fraud = 1)
df = pd.read_parquet("bookings.parquet")
FEATURES = [
"amount",
"is_first_booking",
"booking_hour",
"card_country",
"ip_country",
"same_ip_multiple_bookings",
"minutes_since_account_created",
"device_risk_score",
]
X = df[FEATURES]
y = df["is_fraud"]
# Class imbalance: fraud ~ 0.1-0.5% of bookings
# Accuracy is useless. Use precision@k, recall@k.
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import average_precision_score
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y
)
model = GradientBoostingClassifier(n_estimators=300)
model.fit(X_train, y_train)
scores = model.predict_proba(X_test)[:, 1]
ap = average_precision_score(y_test, scores)
print(f"Average precision: {ap:.3f}")
# Also worth running:
# - Isolation Forest for unsupervised anomalies
# - Rule engine for known fraud patterns
# - Human review for borderline cases
The realistic production setup:
1. ML ranks suspiciousness
2. Rules catch obvious cases
3. Humans review the ambiguous middle
Fully automated fraud detection is
rare in travel. False positives kill
real customers.
SECTION 04ML project templates for travel data
Three portfolio projects that would read as credible to any travel company:
Portfolio project 1 — price optimisation
BUSINESS QUESTION
"For a set of 50 hotel properties, what
price maximizes expected revenue per
available room over the next 30 days?"
DATA
- Historical bookings with price paid
- Search impressions (with price shown)
- Calendar of local events and holidays
- (You'll simulate some of this from
public data or Kaggle)
METHOD
1. Fit P(book | features, price) using
gradient boosting
2. For each property-date, evaluate a
grid of candidate prices
3. Pick the price that maximizes
expected revenue = P(book) × price
DELIVERABLE
- A notebook that explains the model
- A CSV of recommended prices per property
- An analysis of expected uplift vs.
current prices
- A README with trade-offs
INTERVIEW VALUE
This is the closest project to what
pricing teams actually do. It shows you
understand the business objective, not
just the ML.
Portfolio project 2 — demand forecast
BUSINESS QUESTION
"Forecast daily bookings for 10 flight
routes for the next 90 days, so ops
can plan capacity and pricing."
DATA
- Public flight booking data (e.g. Kaggle)
- Holiday calendars
- Weather (public APIs)
METHOD
1. Per-route or global model with route
embeddings
2. Prophet or gradient boosting
3. Walk-forward validation
4. Report MAPE and bias by horizon
DELIVERABLE
- 90-day forecast per route
- Backtest chart showing actual vs
predicted
- Segment errors (weekdays vs weekends,
holiday vs non-holiday)
- README explaining trade-offs
INTERVIEW VALUE
Time-series done right is rare in
portfolios. Walk-forward validation alone
will distinguish you from 90% of
candidates.
Portfolio project 3 — ranking model
BUSINESS QUESTION
"Given 100 hotel search results per
query, which 10 should we show first?"
DATA
- Search impressions with position
- Click logs
- Booking logs (harder to get publicly)
- Build a synthetic dataset if needed
METHOD
1. Construct the ranking problem:
- group = one search
- labels = clicked (or booked)
2. Train a LambdaMART or LightGBM ranker
3. Evaluate with NDCG@10
4. Compare against a baseline (e.g.
price sort, review-score sort)
DELIVERABLE
- Trained ranker
- NDCG@10 vs baselines
- Feature importance chart
- README explaining why ranking
beats scoring-in-isolation
INTERVIEW VALUE
Ranking is the single most underrated
skill in ML portfolios. Very few
candidates can explain the difference
between a scoring model and a ranker.
SECTION 05Skills needed to work in travel ML
Here's the actual skill set travel companies hire for:
- Python + Pandas — daily. No travel ML team writes in anything else for data work.
- SQL — you'll query booking tables, logs and pricing history every day. Non-negotiable.
- Classical ML — gradient boosting (XGBoost, LightGBM) solves 70% of travel problems. Deep learning is used for ranking and personalisation, but is not the default.
- Time series — every travel role involves forecasting demand, pricing or capacity. Learn walk-forward validation properly.
- Business framing — every model is judged on revenue, margin, conversion or churn. Show that in your projects.
- Causal inference (bonus) — understanding whether a discount actually worked is worth more than a slightly better model.
SECTION 06Interview Q&A — ML in travel
Q1Do travel companies use deep learning?
Yes, for ranking and personalisation at large scale (Bookings, Expedia, MakeMyTrip). But most pricing, demand and fraud models are still gradient boosting — interpretability and speed matter more than raw accuracy.
Q2What's the most valuable skill in travel ML?
Business framing. Every model has to move a number the business cares about — revenue per room, booking rate, chargeback rate. Candidates who can connect models to revenue move faster.
Q3Is time-series experience required?
Yes for forecasting roles. Most travel data is a time series, and the way you validate matters more than the algorithm. Learn walk-forward validation before you learn Prophet.
Q4How do you handle seasonality?
Seasonal features (month, festival flags, school holidays) and seasonal decomposition. For demand, Prophet's built-in seasonality works well; for pricing, you usually build seasonal features into the model.
Q5Which project should I build first?
A price-optimisation notebook. It combines regression, business reasoning and revenue thinking — the three things travel ML interviews probe.
SECTION 07Test yourself — ML in travel quiz
Five questions. No sign-up.
0 / 5Pick an answer to see why it is right or wrong.
SECTION 08Frequently asked questions
Which travel companies have strong ML teams?
Booking.com, Expedia, Airbnb and MakeMyTrip (in India) are the biggest. Airlines (IndiGo, Emirates) and ride-hailing (Uber, Ola, Rapido) also have large ML teams. Startups in travel planning use ML heavily too.
Is travel ML hard to get into?
Similar to other ML roles — competitive, but not unusually so. What separates candidates is the ability to connect a model to business impact. A pricing notebook that shows expected revenue uplift lands better than a generic classification model.
Do I need travel industry experience?
No. Domain knowledge helps, but travel companies hire data scientists from other industries all the time. What they care about is your ML depth and your ability to reason about revenue/conversion problems.
What's the most common ML problem in travel?
Demand forecasting. Every team needs it — pricing, ops, marketing, staffing. If you can forecast well and communicate uncertainty, you're useful in almost every travel role.
How much of the work is model building vs other tasks?
Realistically 20-30% modeling, 70-80% data pipelines, business conversations, evaluation and deployment. The "model" is often the smallest part of the job — the rest is what makes it useful.
SECTION 09Related reads
Classroom & online · Noida
Build the travel-ML portfolio
Our Data Science Training Course includes pricing, forecasting and ranking projects — the three most in-demand skills in travel ML.
₹42,500 · full programme- Pricing, forecasting & ranking projects
- Real datasets, not Titanic
- Mock interviews & portfolio review
- Weekday & weekend batches