캐글의 [Titanic Dataset] 을 활용하여 타이타닉 생존자를 예측하는 모델을 만들어봤다.

 

https://www.kaggle.com/datasets/yasserh/titanic-dataset

 

Titanic Dataset

Titanic Survival Prediction Dataset

www.kaggle.com

 

데이터 로드 및 확인

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings('ignore', category=UserWarning)

df = pd.read_csv("./data/titanic_dataset.csv")
df

 

df.info()

 

df.describe()

 

# Name 데이터 확인 - 불필요한 컬럼이라 판단되면 삭제
df["Name"]

 

# Ticket 데이터 확인 - 불필요한 데이터라 판단되면 삭제
df["Ticket"].value_counts()

 

# Cabin 데이터 확인 - 불필요한 컬럼이라 판단되면 삭제
df["Cabin"].value_counts()

 

# Embarked 데이터 확인 - 불필요한 데이터라 판단되면 삭제
df["Embarked"].value_counts()

 

# SibSp 데이터 확인 - 불필요한 데이터라 확인되면 삭제
df["SibSp"].value_counts()

 

# Parch 데이터 확인 - 불필요한 데이터라 판단되면 삭제
df["Parch"].value_counts()

 

 

데이터 시각화

cat_cols = ["Pclass", "Sex", "SibSp", "Parch", "Embarked", "Survived"]
num_cols = ["Age", "Fare"]

 

# 범주형 데이터 시각화
figs, axes = plt.subplots(2, 3, figsize=(12, 8))
axes_flat = axes.flatten()

for i, col in enumerate(cat_cols):
    ax = axes_flat[i]

    data_count = df[col].value_counts().sort_index()
    ax.bar(data_count.index.astype(str), data_count.values, color="C"+str(i), alpha=0.7, edgecolor="black")
    ax.set_title(f"Bar Chart: {col}")
    ax.set_xlabel("Categories")
    ax.set_ylabel("Count")
    ax.tick_params(axis="x", rotation=45) # x축 글자가 겹치므로 45도 회전

plt.tight_layout()
plt.show()

 

# 수치형 데이터 시각화
fig, axes = plt.subplots(1, 2, figsize=(13, 5))

for i, col_name in enumerate(num_cols):
    ax = axes[i]

    # 히스토그램 그리기
    ax.hist(df[col_name], bins=10, color="C"+str(i), alpha=0.7, edgecolor="black")

    # 개별 차트 제목 및 라벨 설정
    ax.set_title(f"Histogram: {col_name}")
    ax.set_xlabel("Values")
    ax.set_ylabel("Frequency")

    # 격자선 추가
    ax.grid(axis="y", alpha=0.5)

plt.tight_layout()
plt.show()

 

 

전처리 전략

1. PassengerId, Name, Ticket 컬럼은 삭제
2. Cabin 컬럼은 null 데이터가 많아서 삭제 하기로 결정
3. Age 컬럼은 null 데이터를 특정값으로 대체하기 어려워서 null 값 삭제
4. Embarked 컬럼은 null 데이터를 특정값으로 대체하기 어려워서 null 값 삭제
5. 범주형 컬럼(Pclass, Sex, SibSp, Parch, Embarked) 은 모두 원핫 인코딩
6. Age 는 StandardScaler로 스케일링
7. Fare 는 RobustScaler로 스케일링

df_prep = df.copy()
df_prep = df_prep.drop(labels=["PassengerId", "Name", "Ticket", "Cabin"], axis=1)
df_prep = df_prep.dropna()
df_prep = df_prep.reset_index(drop=True)
df_prep.info()

 

from sklearn.preprocessing import OneHotEncoder

# Company, TypeName, OpSys 는 원핫인코딩
encoder = OneHotEncoder(sparse_output=False)
encoded_data = encoder.fit_transform(df_prep[["Pclass", "Sex", "SibSp", "Parch", "Embarked"]])

# 인코딩 된 데이터를 데이터프레임으로 변환
encoded_df = pd.DataFrame(
    encoded_data, columns=encoder.get_feature_names_out(["Pclass", "Sex", "SibSp", "Parch", "Embarked"])
)

# 기존 데이터셋에서 인코딩한 컬럼을 제거하고 인코딩된 데이터를 붙이기
df_encoded = df_prep.drop(columns=["Pclass", "Sex", "SibSp", "Parch", "Embarked"])
df_encoded = pd.concat([df_encoded, encoded_df], axis=1)

 

from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, RobustScaler

robust_col = ["Fare"]
standard_col = ["Age"]

X = df_encoded.drop(labels=["Survived"], axis=1)
y = df_encoded["Survived"]

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

# 전처리 파이프라인 구성
preprocessor = ColumnTransformer(
    transformers = [
        ("robust", RobustScaler(), robust_col),
        ("std", StandardScaler(), standard_col)
    ],
    remainder="passthrough"
)

 

 

모델 학습 및 평가 - XGBoost

from xgboost import XGBClassifier
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import GridSearchCV

# XGBoost 전용 파이프라인 구성
pipeline_xgb = ImbPipeline(
    [
        ("preprocessor", preprocessor),
        ("classifier", XGBClassifier(random_state=42, eval_metric="logloss"))
    ]
)

# XGBoost 하이퍼파라미터 그리드 설정
param_grid_xgb = {
    "classifier__n_estimators": [50, 100, 150, 200],
    "classifier__max_depth": [3, 5, 7, 9],
    "classifier__learning_rate": [0.01, 0.05, 0.1, 0.2]
}

# GridSearchCV 설정
grid_search_xgb = GridSearchCV(
    estimator=pipeline_xgb,
    param_grid=param_grid_xgb,
    cv=5,
    scoring="accuracy",
    n_jobs=1,
    verbose=2
)

# 원본 데이터로 학습 시작
print("===== XGBoost GridSearchCV 학습 시작 =====")
grid_search_xgb.fit(X_train, y_train)
print("최적의 파라미터: ", grid_search_xgb.best_params_)

# 최적 모델 추출 및 예측
best_xgb_model = grid_search_xgb.best_estimator_

 

from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score

y_pred_xgb = best_xgb_model.predict(X_test)

# 성능 지표
print(classification_report(y_test, y_pred_xgb, target_names=["Not[0]", "Survived(1)"]))

print(f"Accuracy Score: {accuracy_score(y_test, y_pred_xgb)}")

 

 

모델 학습 및 평가 - RandomForestClassifier

from sklearn.ensemble import RandomForestClassifier
from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import GridSearchCV

# RandomForestClassifier 전용 파이프라인 구성
pipeline_rf = ImbPipeline(
    [
        ("preprocessor", preprocessor),
        ("classifier", RandomForestClassifier(random_state=42))
    ]
)

# RandomForestClassifier 하이퍼파라미터 그리드 설정
param_grid_rf = {
    "classifier__n_estimators": [50, 100, 200, 300],
    "classifier__max_depth": [10, 20, None],
    "classifier__min_samples_split": [2, 5, 7, 10],
    "classifier__min_samples_leaf": [1, 2, 4, 8]
    }

# GridSearchCV 설정
grid_search_rf = GridSearchCV(
    estimator=pipeline_rf,
    param_grid=param_grid_rf,
    cv=5,
    scoring="recall",
    n_jobs=1,
    verbose=2
)

# 원본 데이터로 학습 시작
print("===== RandomForestClassifier GridSearchCV 학습 시작 =====")
grid_search_rf.fit(X_train, y_train)
print("최적의 파라미터: ", grid_search_rf.best_params_)

# 최적 모델 추출 및 예측
best_rf_model = grid_search_rf.best_estimator_

 

from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score

# 테스트 데이터로 예측 수행
y_pred_rf = best_rf_model.predict(X_test)


# 성능 지표
print(classification_report(y_test, y_pred_rf, target_names=["Not[0]", "Survived(1)"]))

print(f"Accuracy Score: {accuracy_score(y_test, y_pred_rf)}")

 

 

모델 학습 및 평가 - LGBMClassifier

from lightgbm import LGBMClassifier

# LightGBM 전용 파이프라인 구성
pipeline_lgbm = ImbPipeline([
    ('preprocessor', preprocessor),
    ('classifier', LGBMClassifier(random_state=42, verbose=-1)) # 로그 출력 최소화
])

# LightGBM 하이퍼파라미터 그리드 설정
param_grid_lgbm = {
    'classifier__n_estimators': [100, 200, 300],
    'classifier__max_depth': [3, 5, 7, -1], # -1은 제한 없음
    'classifier__num_leaves': [15, 31, 63],
    'classifier__learning_rate': [0.01, 0.05, 0.1]
}

# GridSearchCV 설정
grid_search_lgbm = GridSearchCV(
    estimator=pipeline_lgbm,
    param_grid=param_grid_lgbm,
    cv=5,
    scoring="recall",
    n_jobs=1,
    verbose=2
)

# 원본 데이터로 학습 시작
print("===== LightGBM GridSearchCV 시작 =====")
grid_search_lgbm.fit(X_train, y_train)
print("최적의 파라미터: ", grid_search_lgbm.best_params_)

# 최적 모델 추출 및 예측
best_lgbm_model = grid_search_lgbm.best_estimator_

 

from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score

# 테스트 데이터로 예측 수행
y_pred_lgbm = best_lgbm_model.predict(X_test)

# 성능 지표
print(classification_report(y_test, y_pred_lgbm, target_names=["Not[0]", "Survived(1)"]))

print(f"Accuracy Score: {accuracy_score(y_test, y_pred_lgbm)}")