Aakash Singh Dahiya

Machine Learning / Python · Learning project

Titanic Survival Prediction — Logistic Regression

A Python logistic regression model on the Kaggle Titanic dataset — exploring which passenger features predicted survival, and achieving 77% test accuracy on a held-out test set.

Status
Published
Published
January 2023
Reading time
4 min read
Project type
Python & ML
Complexity
Low
ai-automationpythonmachine-learning

77% on held-out test set

Model accuracy

Kaggle Titanic — passenger survival classification

Dataset

Python end to end — data loading to confusion matrix

Stack

Business Question

Can passenger characteristics — class, age, gender, fare, embarkation port — predict survival on the Titanic? This is a standard binary classification problem that served as the first full end-to-end ML pipeline I built in Python.

Data Sources

The Kaggle Titanic dataset: 891 training records with features including passenger class, name, sex, age, number of siblings/spouses aboard, number of parents/children aboard, ticket number, fare, cabin number and port of embarkation — and a binary survival target.

Approach

A complete Python workflow: data loading, exploratory visualization, null handling, feature selection, train/test split (scikit-learn), logistic regression model fit, predictions and evaluation via confusion matrix and accuracy score.

Key Steps

  1. Data exploration — countplots (survival by sex, by class), histograms (age distribution, fare distribution) using seaborn and matplotlib to understand the data before modelling
  2. Data cleaning — isnull() checks, dropping columns with high null rates (cabin), imputing where appropriate
  3. Feature engineering — defining X (independent variables: passenger class, sex, age, fare, siblings, parents) and y (survival)
  4. Modelling — train/test split, LogisticRegression() fit, predictions on the test set
  5. Evaluation — confusion matrix showing 102 + 63 correct predictions and 24 + 25 incorrect; accuracy score of 77%

The notebook below recreates the actual pipeline — cell by cell, code through to the confusion matrix.

titanic_logistic_regression.ipynbPython 3
In [1]:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, accuracy_score
 
train = pd.read_csv('train.csv')
train.shape
Out[1]:
(891, 12)
In [2]:
# check for missing values before doing anything else
train.isnull().sum().sort_values(ascending=False).head()
Out[2]:
Cabin          687
Age            177
Embarked         2
Fare             0
Ticket           0
dtype: int64
In [3]:
sns.countplot(data=train, x='Sex', hue='Survived')
plt.title('Survival Count by Sex')
plt.show()
Out[3]:
Bar chart of Titanic survival counts split by sex
In [4]:
sns.countplot(data=train, x='Pclass', hue='Survived')
plt.title('Survival Count by Passenger Class')
plt.show()
Out[4]:
Bar chart of Titanic survival counts split by passenger class
In [5]:
train.drop('Cabin', axis=1, inplace=True)
train['Age'].fillna(train['Age'].median(), inplace=True)
train.dropna(inplace=True)
 
sex = pd.get_dummies(train['Sex'], drop_first=True)
embark = pd.get_dummies(train['Embarked'], drop_first=True)
train = pd.concat([train, sex, embark], axis=1)
 
X = train[['Pclass', 'Age', 'SibSp', 'Parch', 'Fare', 'male', 'Q', 'S']]
y = train['Survived']
 
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.24, random_state=42
)
 
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)
Out[5]:
LogisticRegression(max_iter=1000)
In [6]:
predictions = model.predict(X_test)
 
cm = confusion_matrix(y_test, predictions)
print(cm)
print('Accuracy:', round(accuracy_score(y_test, predictions), 3))
Out[6]:
[[102  25]
 [ 24  63]]
Accuracy: 0.771
In [7]:
import seaborn as sns
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['Pred: 0','Pred: 1'],
yticklabels=['Actual: 0','Actual: 1'])
plt.title('Confusion Matrix Logistic Regression')
plt.show()
Out[7]:
Confusion matrix heatmap for the logistic regression model, 77.1% accuracy

Key Finding

Fare contributed more to predicted survival than other variables based on the model coefficients — a result that reflects the class structure on the ship. Gender and class were also significant predictors, consistent with the historical "women and children first" evacuation pattern.

Technologies I Personally Used

Python

pandasnumpyscikit-learnseabornmatplotlib

Modelling

Logistic RegressionTrain/Test SplitConfusion Matrix

Lessons Learned

  • The confusion matrix is more informative than accuracy alone — 77% accuracy looks reasonable but the matrix shows where the model fails (false negatives vs false positives) and which error type matters more in context
  • Feature selection before modelling matters: including passenger name and ticket number adds noise without predictive value
  • This was a first Python ML project, built collaboratively with a teammate; the process of explaining each step (in the LinkedIn post we published) reinforced the concepts more than just running the code did

Reflection

What I learned: the whole pipeline from import pandas to a confusion matrix — and that the interesting part isn't fitting the model, it's understanding why the model makes the predictions it does.

What I would improve today: feature engineering (extracting titles from names, family size from siblings+parents), hyperparameter tuning, and comparing logistic regression against a decision tree and random forest for the same dataset.

Published: January 2023, with teammate Amarjeet Singh, with guidance from senior Abhimanyu Kr.

Related work