본문 바로가기

Programming/Machine Learning

타이타닉 생존자 예측 분석

train.csv
0.06MB
test.csv
0.03MB

 

목표

- 타이타닉 데이터를 학습해서 생존자/사망자를 예측해보자

- 머신러닝의 전체 과정을 진행해보자.

 

머신러닝 과정

- 문제정의

- 데이터 수집

- 데이터 전처리

- 탐색적 데이터 분석

- 모델 선택 및 학습

- 모델 평가

 

1. 문제 정의

- 생존자/사망자를 예측

- Kaggle 경진대회에서 높은 순위를 차지

- 머신러닝 과정 전체를 체험 해보는 예제

 

2. 데이터 수집

- Kaggle 사이트로부터 train, test 다운로드

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns # 시각화 라이브러리

 

Question1

- 타이타닉 train데이터와 test데이터를 변수 train,test에 저장하세요.(단 인덱스는 PassengerId를 사용 할 것.)

train = pd.read_csv('data/train.csv',index_col='PassengerId')
test = pd.read_csv('data/test.csv',index_col='PassengerId')

print(train.shape)
print(test.shape)

 

3.데이터 전처리 및 데이터 탐색

결측치 확인

train.info()

test.info()

 

Age 채우기

- 단순 기술통계치로 채우지 않고 다른 컬럼과의 상관관계를 이용해 결측치를 채워보자.

- Age와 다른 컬럼간의 상관관계를 알아보자.

train.corr()

 

 

- Pclass가 가장 높은 상관관계를 갖는다.

- 생존에 관련이 많을 것 같은 성별을 함께 그룹핑에 활용해보자.

pt1 = train.pivot_table(values='Age', 
                       index=['Pclass','Sex'],
                        aggfunc = 'mean')
pt1

pt1.loc[1,'female']

pt1.loc[3,'male']

def fill_age(row):
    # 만약 나이가 결측치라면 피봇데이블에서 값을 가져오고
    if np.isnan(row['Age']):
        return pt1.loc[row['Pclass'],row['Sex']]
    # 만약 나이가 결측치가 아니라면 원래 나이 값을 사용하자.
    else:
        return row['Age']
        
train['Age'] = train.apply(fill_age, axis=1).astype('int64')

train.info()

train.head(8)

test['Age'] = test.apply(fill_age, axis=1).astype('int64')

test.info()

 

Embarked 채우기

train['Embarked'].value_counts()

test['Embarked'].value_counts()

train['Embarked'] = train['Embarked'].fillna('S')

train.info()

 

Fare 채우기

train.corr()

pt2 = train.pivot_table(values='Fare', 
                       index=['Pclass','Sex'],
                        aggfunc = 'mean')
pt2

test[test['Fare'].isnull()]

test['Fare'] = test['Fare'].fillna(12.661633)

test.info()

 

Cabin 채우기

train['Cabin'].unique()

train['Deck']  = train['Cabin'].fillna('M')
test['Deck']  = test['Cabin'].fillna('M')

train['Deck'] = train['Deck'].str[0]
test['Deck'] = test['Deck'].str[0]

train.drop('Cabin', inplace=True, axis=1)

test.drop('Cabin', inplace=True, axis=1)

train.info()

test.info()

 

데이터 탐색

- train데이터를 이용해 탐색을 한다.

- test를 탐색하는 것은 모델 일반화에 도움이 되지 않음.

범주형 데이터

Deck 시각화

train_deck = train[['Deck','Survived','Name']].groupby(['Deck','Survived']).count()

train_deck

sns.countplot(data=train, x='Deck', hue='Survived')

 

- M에서 상대적으로 사람이 많이 죽었다.

- 생존여부 판단에 활용해도 괜찮겠다.

 

Pclass 시각화

sns.countplot(data=train, x='Pclass', hue='Survived')

- 3등급의 사람들이 많이 죽었다.

 

Deck과 Pclass 시각화

sns.countplot(data=train, x='Deck', hue='Pclass')

 

Question2

- Sex, Embarked 시각화 해보자.

sns.countplot(data=train, x='Sex', hue='Survived')

sns.countplot(data=train, x='Embarked', hue='Survived')

 

수치형 데이터

Age 시각화

plt.figure(figsize=(15,5))
sns.violinplot(data=train,
              x='Sex',
              y='Age',
              hue='Survived',
              split=True)

- 20~40대 사이가 많이 사망했고

- 어린아이 중에서는 남자아이가 여자아이에 비해 많이 살았다.

 

Fare 시각화

train['Fare'].describe()

plt.figure(figsize=(15,5))
sns.violinplot(data=train,
              x='Sex',
              y='Fare',
              hue='Survived',
              split=True)

- 요금이 싼사람은 상대적으로 많이 죽었다.

 

Parch,SibSp - 부모자식, 형제배우자

- 특성공학 : Parch와 SibSp를 더해서 가족의 숫자라는 새로운 컬럼 생성

- train에 진행한 작업은 test에도 해줘야한다.

train['Family_Size'] = train['Parch'] + train['SibSp'] + 1
test['Family_Size'] = test['Parch'] + test['SibSp'] + 1

sns.countplot(data=train, x='Family_Size', hue='Survived')

- 1명일때는 죽은 비율이 높고, 2~4일때는 산 비율이 높고, 5명이상이면 죽은 비율이 높다.

- binning(사소한 관찰오류의 영향을 줄여 줄 수 있다.)

 

Question3

- 가족사이즈가 1이면 Alone, 2~4면 Small, 5이상이면 Large

- train, test 전부 적용

bins = [0,1,4,11]
labels = ['Alone','Small','Large']
train['Family_Group'] = pd.cut(train['Family_Size'], bins=bins, labels=labels)
test['Family_Group'] = pd.cut(test['Family_Size'], bins=bins, labels=labels)

sns.countplot(data=train, x='Family_Group', hue='Survived')

 

Text 데이터 다루기

Name 시각화

- 중간 호칭만 추출하자.

train['Name']

def split_title(row):
    return row.split(',')[1].split('.')[0].strip()
    
train['Title'] = train['Name'].apply(split_title)
test['Title'] = test['Name'].apply(split_title)

plt.figure(figsize=(15,5))
sns.countplot(data=train, x='Title', hue='Survived')

plt.figure(figsize=(15,5))
plt.ylim(0,20)
sns.countplot(data=train, x='Title', hue='Survived')

- Master : 결혼하지 않은 남성. 주로 청소년 이하

- Rev : 목사님 (6명 모두 죽음)

- Mr,Mrs,Miss,Master,Rev,Other(나머지)

train['Title'].unique()

title = ['Mr', 'Mrs', 'Miss', 'Master', 'Rev', 'Don',  'Dr', 'Mme', 'Ms',
       'Major', 'Lady', 'Sir', 'Mlle', 'Col', 'Capt', 'the Countess',
       'Jonkheer']
       
len(title)

covert_title = ['Mr', 'Mrs', 'Miss', 'Master', 'Rev'] + ['Other'] * 12
covert_title

title_dict = dict(zip(title,covert_title))

train['Title'] = train['Title'].map(title_dict)

test['Title'].unique()

title_dict['Dona'] = 'Other'
title_dict

test['Title'] = test['Title'].map(title_dict)

 

티켓

- 버리자

train.drop('Ticket',axis=1,inplace=True)
test.drop('Ticket',axis=1,inplace=True)

train.drop('Name',axis=1,inplace=True)
test.drop('Name',axis=1,inplace=True)

train.info()

 

특성선택

- 범주형 데이터 인코딩

- 전체 데이터를 이용해서 학습

- 추후 상관계수, Decision tree 중요도를 활용해서 특성 고르기

y_train = train['Survived']
X_train = train.drop('Survived',axis=1)
X_test = test

X_train.columns

cat_feature = ['Sex','Embarked','Deck','Family_Group','Title']

for cat_name in cat_feature:
    dummy = pd.get_dummies(train[cat_name], prefix=cat_name)
    X_train = pd.concat([X_train,dummy], axis=1)
    X_train.drop(cat_name,axis=1,inplace=True)
    
    for cat_name in cat_feature:
    dummy = pd.get_dummies(test[cat_name], prefix=cat_name)
    X_test = pd.concat([X_test,dummy], axis=1)
    X_test.drop(cat_name,axis=1,inplace=True)
    
X_train.shape

X_test.shape

set(X_train.columns) - set(X_test.columns)

X_test['Deck_T'] = 0

X_train.shape

X_test.shape

 

4. 모델 선택 및 학습

from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier

from sklearn.model_selection import cross_val_score

 

Tree 모델

tree_model = DecisionTreeClassifier(max_depth=5)

result = cross_val_score(tree_model,
                        X_train,
                        y_train,
                        cv = 5)
result

result.mean()

 

KNN 모델

knn_model = KNeighborsClassifier(n_neighbors=3)

result = cross_val_score(knn_model,
                        X_train,
                        y_train,
                        cv=5)
result

result.mean()

 

KNN Scaler 적용

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

scaler.fit(X_train)

transform_X_train = scaler.transform(X_train)
transform_X_train

transform_X_test = scaler.transform(X_test)
transform_X_test

result = cross_val_score(knn_model,
                        transform_X_train,
                        y_train,
                        cv=5)
result

result.mean()

 

5. 모델평가

result = pd.read_csv('data/gender_submission.csv')
result

tree_model.fit(X_train,y_train)
pre = tree_model.predict(X_test)
pre

result['Survived'] = pre

result.to_csv('HHD_submission_01.csv', index=False)

'Programming > Machine Learning' 카테고리의 다른 글

보스턴주택 값 예측  (0) 2020.02.17
Linear Model - Regression  (0) 2020.02.17
버섯데이터 분류  (0) 2020.02.17
iris 품종분류  (0) 2020.02.17
BMI 학습하기  (0) 2020.02.16