728x90
1. Titanic Survivor Prediction ML Process
데이터 전처리(fit, transform) -> ML 모델 학습(fit)/예측(predict)/평가
Data Preprocessing
- Null 처리
- 불필요한 속성 제거
- Encoding 수행
Model 학습 및 검증/예측/평가
- 결정트리, 랜덤포레스트, 로지스틱 회귀 학습 비교
- K-Fold 교차 검증
- cross_val_score()와 GridSearchCV() 수행
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
titanic_df = pd.read_csv('./titanic_train.csv')
titanic_df.head(3)
* Passengerid: 탑승자 데이터 일련번호
* survived: 생존 여부, 0 = 사망, 1 = 생존
* Pclass: 티켓의 선실 등급, 1 = 일등석, 2 = 이등석, 3 = 삼등석
* sex: 탑승자 성별
* name: 탑승자 이름
* Age: 탑승자 나이
* sibsp: 같이 탑승한 형제자매 또는 배우자 인원수
* parch: 같이 탑승한 부모님 또는 어린이 인원수
* ticket: 티켓 번호
* fare: 요금
* cabin: 선실 번호
* embarked: 중간 정착 항구 C = Cherbourg, Q = Queenstown, S = Southampton
print("\n ### train 데이터 정보 ### \n")
print(titanic_df.info())
titanic_df.describe().T
Null Column들에 대한 처리
- DataFrame.isnull(): 모든 Column들에 대해 Null에 대한 T/F여부가 반환
- DataFrame.isnull().sum(): 각 Column들에 대해 T(1), F(0)들이 합쳐져서 숫자로 반환
- DataFrame.isnull().sum().sum(): 전체 DataFrame에서의 null값 개수
titanic_df["Age"].fillna(titanic_df["Age"].mean(), inplace=True)
titanic_df["Cabin"].fillna("N", inplace=True)
titanic_df["Embarked"].fillna("N", inplace=True)
print("Data Set Null 값 개수", titanic_df.isnull().sum().sum())
# Data Set Null 값 개수 0
주요 Column EDA
- object column type 추출
# object column type 추출
titanic_df.dtypes[titanic_df.dtypes == "object"].index.tolist()
# ['Name', 'Sex', 'Ticket', 'Cabin', 'Embarked']
- 주요 Column들의 개별 데이터값 분포
print("Sex 값 분포:\n", titanic_df["Sex"].value_counts())
print("\n Cabin 값 분포:\n", titanic_df["Cabin"].value_counts())
print("\n Embarked 값 분포:\n", titanic_df["Embarked"].value_counts())
- column data 전처리
- 선실 번호들을 일괄적으로 앞글자만 따서 처리
titanic_df['Cabin'].str[0]
titanic_df["Cabin"] = titanic_df["Cabin"].str[0]
titanic_df["Cabin"].value_counts()
# N 687
# C 59
# B 47
# D 33
# E 32
# A 15
# F 13
# G 4
# T 1
# Name: Cabin, dtype: int64
- Sex와 Survived 간의 관계 확인
titanic_df.groupby(["Sex", "Survived"])["Survived"].count()
# Sex Survived
# female 0 81
# 1 233
# male 0 468
# 1 109
# Name: Survived, dtype: int64
- barplot은 평균값을 구한다
sns.barplot(x="Sex", y="Survived", data=titanic_df)
- hue option을 사용해서 추정을 세분화함
sns.barplot(x="Pclass", y="Survived", hue="Sex", data=titanic_df)
- apply(lambda)를 사용하여 새로운 column Age_cat 생성
# 입력 age에 따라 구분값을 반환하는 함수 설정. DataFrame의 apply lambda식에 사용.
def get_category(age):
cat = ""
if age <= -1:
cat = "Unknown"
elif age <= 5:
cat = "Baby"
elif age <= 12:
cat = "Child"
elif age <= 18:
cat = "Teenager"
elif age <= 25:
cat = "Student"
elif age <= 35:
cat = "Young Adult"
elif age <= 60:
cat = "Adult"
else:
cat = "Elderly"
return cat
# 막대그래프의 크기 figure를 더 크게 설정
plt.figure(figsize=(10, 6))
# X축의 값을 순차적으로 표시하기 위한 설정
group_names = [
"Unknown",
"Baby",
"Child",
"Teenager",
"Student",
"Young Adult",
"Adult",
"Elderly",
]
# lambda 식에 위에서 생성한 get_category( ) 함수를 반환값으로 지정.
# get_category(X)는 입력값으로 'Age' 컬럼값을 받아서 해당하는 cat 반환
titanic_df["Age_cat"] = titanic_df["Age"].apply(lambda x: get_category(x))
sns.barplot(x="Age_cat", y="Survived", hue="Sex", data=titanic_df, order=group_names)
titanic_df.drop("Age_cat", axis=1, inplace=True)
- 3개의 Column에 대해 LabelEncoding 수행
from sklearn.preprocessing import LabelEncoder
def encode_features(dataDF):
features = ["Cabin", "Sex", "Embarked"]
le = LabelEncoder()
for feature in features:
le.fit(dataDF[feature])
dataDF[feature] = le.transform(dataDF[feature])
return dataDF
titanic_df = encode_features(titanic_df)
titanic_df.head()
2. Data Preprocessing
- 주요 Data Preprocessing
- Null 처리 함수
- ML Algorithm에 불필요한 Feature 제거
- Label Encoding 수행
- 앞에서 설정한 Data Preprocessing 함수 호출
from sklearn.preprocessing import LabelEncoder
# Null 처리 함수
def fillna(df):
df["Age"].fillna(df["Age"].mean(), inplace=True)
df["Cabin"].fillna("N", inplace=True)
df["Embarked"].fillna("N", inplace=True)
return df
# ML Algorithm에 불필요한 Feature 제거
def drop_features(df):
df.drop(["PassengerId", "Name", "Ticket"], axis=1, inplace=True)
return df
# Label Encoding 수행
def format_features(df):
df["Cabin"] = df["Cabin"].str[0]
features = ["Cabin", "Sex", "Embarked"]
for feature in features:
le = LabelEncoder()
le.fit(df[feature])
df[feature] = le.transform(df[feature])
return df
# 앞에서 설정한 DataPreprocessing 함수 호출
def transform_features(df):
df = fillna(df)
df = drop_features(df)
df = format_features(df)
return df
# 원본 데이터를 재로딩 하고, feature 데이터 셋과 Label 데이터 셋 추출
titanic_df = pd.read_csv("./titanic_train.csv")
y_titanic_df = titanic_df["Survived"] # Label 데이터 셋
X_titanic_df = titanic_df.drop(["Survived"], axis=1) # Feature 데이터 셋
X_titanic_df = transform_features(X_titanic_df) # 데이터 전처리 수행
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X_titanic_df, y_titanic_df, test_size=0.2, random_state=11
)
3. ML Model 학습,예측, 평가
ML Model 학습/예측/평가
- 결정트리, 랜덤포레스트, 로지스틱 회귀 학습 비교
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 결정트리, Random Forest, Logistic Regression을 위한 scikit-learn Classifier 클래스 생성
dt_clf = DecisionTreeClassifier(random_state=11)
rf_clf = RandomForestClassifier(random_state=11)
lr_clf = LogisticRegression(solver="liblinear")
# DecisionTreeClassifier 학습/예측/평가
dt_clf.fit(X_train, y_train)
dt_pred = dt_clf.predict(X_test)
print(f"DecisionTreeClassifier 정확도: {accuracy_score(dt_pred, y_test):.4f}")
# Random Forest 학습/예측/평가
rf_clf.fit(X_train, y_train)
rf_pred = rf_clf.predict(X_test)
print(f"DecisionTreeClassifier 정확도: {accuracy_score(rf_pred, y_test):.4f}")
# Logistic Regression 학습/예측/평가
lr_clf.fit(X_train, y_train)
lr_pred = lr_clf.predict(X_test)
print(f"DecisionTreeClassifier 정확도: {accuracy_score(lr_pred, y_test):.4f}")
# DecisionTreeClassifier 정확도: 0.7877
# DecisionTreeClassifier 정확도: 0.8547
# DecisionTreeClassifier 정확도: 0.8659
- K-Fold 교차 검증
from sklearn.model_selection import KFold
def exec_kfold(clf, folds=5):
# fold set를 5개인 KFold 객체를 생성, fold 수만큼 예측결과 저장을 위한 list 객체 생성
kfold = KFold(n_splits=folds)
scores = []
# KFold 교차 검증 수행
for iter_count, (train_index, test_index) in enumerate(kfold.split(X_titanic_df)):
# X_titanic_df 데이터에서 교차 검증별로 학습과 검증 데이터를 가리키는 index 생성
# .values()는 ndarray로 바꾸기 위해 사용: feature와 label은 모두 ndarray로, 반환한 Index를 Fancy Indexing을 통해 label과 feature에 적용
X_train, X_test = X_titanic_df.values[train_index], X_titanic_df.values[test_index]
y_train, y_test = y_titanic_df.values[train_index], y_titanic_df.values[test_index]
# Classifier 학습/예측/평가(정확도)계산
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
accuracy = accuracy_score(predictions, y_test)
scores.append(accuracy)
print(f'교차 검증 {iter_count} 정확도: {accuracy:.4f}')
# 5개 Fold에서의 평균 정확도 계산
mean_score = np.mean(scores)
print(f'평균 정확도: {mean_score:.4f}')
# exec_fkold 호출
exec_kfold(dt_clf, folds=5)
# exec_kfold(rf_clf, folds=5)
# exec_kfold(lr_clf, folds=5)
# 교차 검증 0 정확도: 0.7542
# 교차 검증 1 정확도: 0.7809
# 교차 검증 2 정확도: 0.7865
# 교차 검증 3 정확도: 0.7697
# 교차 검증 4 정확도: 0.8202
# 평균 정확도: 0.7823
- cross_val_score()와 GridSearchCV() 수행
- Stratified K-Fold 이용
from sklearn.model_selection import cross_val_score
scores = cross_val_score(dt_clf, X_titanic_df, y_titanic_df, cv=5)
for iter_count, accuracy in enumerate(scores):
print(f"교차 검증 {iter_count} 정확도: {accuracy:.4f}")
print(f"평균 검증 {iter_count} 정확도: {np.mean(scores):.4f}")
# 교차 검증 0 정확도: 0.7430
# 교차 검증 1 정확도: 0.7753
# 교차 검증 2 정확도: 0.7921
# 교차 검증 3 정확도: 0.7865
# 교차 검증 4 정확도: 0.8427
# 평균 검증 4 정확도: 0.7879
from sklearn.model_selection import GridSearchCV
parameters = {
"max_depth": [2, 3, 5, 10],
"min_samples_split": [2, 3, 5],
"min_samples_leaf": [1, 5, 8],
}
grid_dclf = GridSearchCV(dt_clf, param_grid=parameters, scoring="accuracy", cv=5)
grid_dclf.fit(X_train, y_train)
print("GridSearchCV 최적 하이퍼 파라미터:", grid_dclf.best_params_)
print(f"GridSearchCV 최고 정확도: {grid_dclf.best_score_:.4f}")
best_dclf = grid_dclf.best_estimator_
# GridSearchCV의 최적 하이퍼 파라미터로 학습된 Estimator로 예측 및 평가 수행
dpredictions = best_dclf.predict(X_test)
accuracy = accuracy_score(y_test, dpredictions)
print(f"테스트 세트에서의 DecisionTreeClassifier 정확도: {accuracy:.4f}")
# GridSearchCV 최적 하이퍼 파라미터: {'max_depth': 3, 'min_samples_leaf': 5, 'min_samples_split': 2}
# GridSearchCV 최고 정확도: 0.7992
# 테스트 세트에서의 DecisionTreeClassifier 정확도: 0.8715
728x90