Machine Learning/캐글스터디(파이썬 머신러닝)

[2장-3] 타이타닉 생존자 예측 ML 구현

뉴욕킴 2023. 4. 3. 23:13

https://colab.research.google.com/drive/1pho8HoLe11nTAIvwRglZY83W2eTKs2IO?usp=sharing

 

Titanic_240206

Colaboratory notebook

colab.research.google.com

 

1) 사전작업

 

* 데이터 전처리

- NULL값, 불필요한 속성 제거, 인코딩 수행

 

*모델학습 및 검증,예측,평가

- 결정트리, 랜덤포레스트, 로지스틱회귀, K폴드 교차 검증, cross_val_score(), gridsearchCV()

 

2) 파일 불러오기

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

titanic_df = pd.read_csv('/train.csv')
titanic_df.head(3)

 

2-1) 속성 설명

  • Passengerid: 탑승자 데이터 일련번호
  • survived: 생존 여부, 0 = 사망, 1 = 생존
  • Pclass: 티켓의 선실 등급, 1 = 일등석, 2 = 이등석, 3 = 삼등석
  • sex: 탑승자 성별
  • name: 탑승자 이름
  • Age: 탑승자 나이
  • sibsp: 같이 탑승한 형제자매 또는 배우자 인원수
  • parch: 같이 탑승한 부모님 또는 어린이 인원수
  • ticket: 티켓 번호
  • fare: 요금
  • cabin: 선실 번호
  • embarked: 중간 정착 항구 C = Cherbourg, Q = Queenstown, S = Southampton

 

3) 데이터 정보 보기(info사용)

 

titanic_df.info()

 

3-1) describe로 사분위표 보기

titanic_df.describe()

 

# transpose(): #transpose는 행과 열을 바꿔서 볼 때 사용

titanic_df.describe().transpose()

 

 

4) 속성 정리(NULL값 처리)

- age를 평균 값으로 사용 → mean 사용

- cabin은 null값이 너무 많기 때문에 N으로 넣어버리기

- embarked도 중요한 속성이 아니기 때문에 N으로 바꿔버리기

 

# 결측값을 mean 평균값으로 채우기
#fillna(~로 채워라), age를 mean값으로 넣자, inplace=true 즉시 적용하는 것
titanic_df['Age'].fillna(titanic_df['Age'].mean(), inplace=True)
# null값을 평균값, 0 등으로 처리할때는 fillna(0, inplace=True)을 사용하여 대체
# 특정컬럼의 결측치값만 대체하고 싶을 때는 데이터프레임['특정 컬럼명'].fillna(0, inplace=True)를 사용
titanic_df['Cabin'].fillna('N', inplace=True)
titanic_df['Embarked'].fillna('N', inplace=True)
# null 값 개수 확인 
titanic_df.isnull().sum()

titanic_df.isnull().sum().sum()

 

5-1) object 컬럼 타입 확인

# object 컬럼 타입 추출
titanic_df.dtypes[titanic_df.dtypes =='object']

# index.tolist() : 인덱스를 리스트로 출력
titanic_df.dtypes[titanic_df.dtypes =='object'].index.tolist()

print('성별 값 분포: \n', titanic_df['Sex'].value_counts())

print('cabin 값 분포포: \n', titanic_df['Cabin'].value_counts())

print('Embarked 값 분포포: \n', titanic_df['Embarked'].value_counts())

# 맨 앞자리만 출력 
titanic_df['Cabin'].str[:1]

titanic_df['Cabin']=titanic_df['Cabin'].str[:1]
titanic_df['Cabin'].head()

5-2) 성별과 생존을 묶기(groupby 사용)

titanic_df.groupby(['Sex','Survived'])

 

- count 확인

titanic_df.groupby(['Sex','Survived']).count()

 

titanic_df.groupby(['Sex','Survived'])['Survived'].count()

# value_counts(). 각각의 값이 나온 횟수를 센다
titanic_df['Survived'].value_counts()

sns.barplot(x='Pclass',y='Survived', hue='Sex', data=titanic_df)

 

- 3등급의 사람들은 여자, 남자 모두 생존률이 낮다

 

6-1) 나이대 별로 생존률 예측

6-2) label encoding 진행

- cabin, sex, embarked 세개 돌려서 숫자로 바꾸기 

# 불필요한 feature 삭제
# LabelEncoder: 문자를 수치화 

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

# 머신러닝 알고리즘에 불필요한 피처 제거
def drop_features(df):
    df.drop(['Passengerld', 'Name', 'Ticket'], axis=1, inplace=True)
    return df

# 레이블 인코딩 수행. 
def format_features(df):
    df['Cabin']=df['Cabin'].str[:1]
    features =['Cabin','Sex','Embarked']
    for feature in feature:
        le =LabelEncoder()
        le=le.fit(df[feature])
        df[feature]=le.transform(df[feature])
    return df

# 앞에서 설정한 Data Preprocessing 함수 호출

def transform_features(df):
    df=fillna(df)
    df=drop_features(df)
    df=format_features(df)
    return df
titanic_df.head()

# 원본 데이터를 재로딩 하고, feature데이터 셋과 Label 데이터 셋 추출. 
titanic_df = pd.read_csv('./titanic_train.csv')
y_titanic_df = titanic_df['Survived']
X_titanic_df= titanic_df.drop('Survived',axis=1, inplace=False)

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)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 결정트리, Random Forest, 로지스틱 회귀를 위한 사이킷런 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('DecisionTreeClassifier 정확도: {0:.4f}'.format(accuracy_score(y_test, dt_pred)))

# RandomForestClassifier 학습/예측/평가
rf_clf.fit(X_train , y_train)
rf_pred = rf_clf.predict(X_test)
print('RandomForestClassifier 정확도:{0:.4f}'.format(accuracy_score(y_test, rf_pred)))

# LogisticRegression 학습/예측/평가
lr_clf.fit(X_train , y_train)
lr_pred = lr_clf.predict(X_test)
print('LogisticRegression 정확도: {0:.4f}'.format(accuracy_score(y_test, lr_pred)))

X_titanic_df.values[[0, 1, 2, 3, 4, 5]]

from sklearn.model_selection import KFold

def exec_kfold(clf, folds=5):
    # 폴드 세트를 5개인 KFold객체를 생성, 폴드 수만큼 예측결과 저장을 위한  리스트 객체 생성.
    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 생성
        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(y_test, predictions)
        scores.append(accuracy)
        print("교차 검증 {0} 정확도: {1:.4f}".format(iter_count, accuracy))     
    
    # 5개 fold에서의 평균 정확도 계산. 
    mean_score = np.mean(scores)
    print("평균 정확도: {0:.4f}".format(mean_score)) 
# exec_kfold 호출
exec_kfold(dt_clf , folds=5)

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("교차 검증 {0} 정확도: {1:.4f}".format(iter_count, accuracy))

print("평균 정확도: {0:.4f}".format(np.mean(scores)))

from sklearn.model_selection import GridSearchCV

 

GridSearchCV란 머신러닝에서 모델의 성능향상을 위해 쓰이는 기법
- 사용자가 직접 모델의 하이퍼 파라미터의 값을 리스트로 입력하면 값에 대한 경우의 수마다 예측 성능을 측정 평가하여 비교하면서 최적의 하이퍼 파라미터 값을 찾는 과정을 진행

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('GridSearchCV 최고 정확도: {0:.4f}'.format(grid_dclf.best_score_))
best_dclf = grid_dclf.best_estimator_

# GridSearchCV의 최적 하이퍼 파라미터로 학습된 Estimator로 예측 및 평가 수행. 
dpredictions = best_dclf.predict(X_test)
accuracy = accuracy_score(y_test , dpredictions)
print('테스트 세트에서의 DecisionTreeClassifier 정확도 : {0:.4f}'.format(accuracy))