스터디노트 (Machine Learning 2)

zoe·2023년 5월 16일
0

Machine learning workflow - 타이타닉 생존자 분석




Machine learning workflow - EDA

#install

#!pip install plotly_express
# 데이터 읽기

import pandas as pd

titanic_url = 'https://raw.githubusercontent.com/PinkWink/ML_tutorial/master/dataset/titanic.xls'

titanic = pd.read_excel(titanic_url)
titanic.head()
titanic['survived'].value_counts()
# 생존 상황
# 32.2%의 생존율

import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline

f, ax = plt.subplots(1, 2, figsize = (18, 8))

titanic['survived'].value_counts().plot.pie(explode = [0, 0.1],
                                            autopct = '%1.1f%%', ax = ax[0], shadow=True)
# autopct = '%1.1f%%' : 그래프 안에 면적을 비율로 입력
# explode = [0, 0.1] : 파이차트 조각 떨어지는 정도 설정

ax[0].set_title('Pie plot = Survived')
ax[0].set_ylabel('')
sns.countplot(x='survived', data=titanic, ax=ax[1])
ax[1].set_title('Count plot - Survived')

plt.show()
# 성별에 따른 생존 상황
# 남성의 생존 가능성이 더 낮다
# survived 0 : unsurvived, 1: survived

f, ax = plt.subplots(1, 2, figsize = (18, 8))

sns.countplot(x='sex', data=titanic, ax=ax[0])
ax[0].set_title('Count of Passengers of Sex')
ax[0].set_ylabel('')

sns.countplot(x='sex', data=titanic, hue='survived',  ax=ax[1])
ax[1].set_title('Sex : Survived and Unsurvived')

plt.show()
# 경제력 대비 생존률
# 1등실의 생존 가능성이 아주 높다
# 그런데 여성의 생존률도 높다
# 그럼, 1등실에는 여성이 많이 타고 있었나?

pd.crosstab(titanic['pclass'], titanic['survived'], margins=True)
# 선실 등급별 성별 상황
# 3등실에는 남성이 많았다 - 특히 20대 남성

grid = sns.FacetGrid(data=titanic, row='pclass', col='sex', height=4, aspect=2)
grid.map(plt.hist, 'age', alpha = .8, bins = 20)
grid.add_legend();
# 나이별 승객 현황도 확인
# 아이들과 20~30대가 많았다

import plotly.express as px

fig = px.histogram(titanic, x='age')
fig.show()
# 등실별 생존률을 연령별로 확인
# 선실 등급이 높으면 생존률이 높은 듯 하다

grid = sns.FacetGrid(titanic, col='survived', row='pclass', height=4, aspect=2)
grid.map(plt.hist, 'age', alpha = .5, bins = 20)
grid.add_legend();
# 나이를 5단계로 정리하기
# cut() : 구간 나누기
titanic['age_cut'] = pd.cut(titanic['age'], bins = [0, 7, 15, 30, 60, 100],
                            include_lowest=True, 
                            labels=['baby','teen','young', 'adult', 'old'])
titanic.head()
# 나이, 성별, 등급별 생존자 수를 한번에 파악할 수 있을까?

plt.figure(figsize=(12, 4))
plt.subplot(131) # 1행 3열 중 첫 번째
sns.barplot(x='pclass', y='survived', data=titanic)

plt.subplot(132) # 1행 3열 중 두 번째
sns.barplot(x='age_cut', y='survived', data=titanic)

plt.subplot(133) # 1행 3열 중 세 번째
sns.barplot(x='sex', y='survived', data=titanic)

plt.subplots_adjust(top=1, bottom=0.1, left=0.1, right=1, hspace=0.5, wspace=0.5)

# 남/여 나이별 생존 상황을 보다 더 들여다보자
# https://wikidocs.net/92112
# bins() : 히스토그램의 가로축 구간의 개수를 지정
# kde : 커널밀도추정
fig, axes  = plt.subplots(nrows=1, ncols=2, figsize=(14, 6))

women = titanic[titanic['sex']=='female']
men = titanic[titanic['sex']=='male']

ax = sns.histplot(women[women['survived']==1]['age'], bins=20, 
                 label = 'survived', ax = axes[0], kde = False)
ax = sns.histplot(women[women['survived']==0]['age'], bins=40, 
                 label = 'not_survived', ax = axes[0], kde = False)

ax.legend(); ax.set_title('Female')

ax = sns.histplot(men[men['survived']==1]['age'], bins=18, 
                 label = 'survived', ax = axes[1], kde = False)
ax = sns.histplot(men[men['survived']==0]['age'], bins=40, 
                 label = 'not_survived', ax = axes[1], kde = False)

ax.legend(); ax.set_title('Male')
# 탑승객의 이름에서 신분을 알 수 있다

for idx, dataset in titanic.iterrows():
    print(dataset['name'])
# 정규식을 이용해서 문장 사이의 신분에 대한 정보를 얻을 수 있다

import re

for idx, dataset in titanic.iterrows():
    tmp = dataset['name']
    print(idx)
    print(re.search('\,\s\w+(\s\w+)?\.', tmp).group()) # ,로 시작하는 단어(하나이든 두개이든..)
# 살짝 응용하면 사회적 신분만 얻을 수 있다

import re

title = []
for idx, dataset in titanic.iterrows():
    title.append(re.search('\,\s\w+(\s\w+)?\.', dataset['name']).group()[2:-1])
    
titanic['title'] = title
titanic.head()
# 성별별로 본 귀족

pd.crosstab(titanic['title'], titanic['sex'])
# 사회적 신분을 조금 더 정리하자

titanic['title'] = titanic['title'].replace('Mlle', 'Miss')
titanic['title'] = titanic['title'].replace('Ms', 'Miss')
titanic['title'] = titanic['title'].replace('Mme', 'Mrs')

Rare_f = ['Dona', 'Lady', 'the Countess']
Rare_m = ['Capt', 'Col', 'Don', 'Major', 'Rev', 'Sir', 'Jonkheer', 'Master']

for each in Rare_f:
    titanic['title'] = titanic['title'].replace(each, 'Rare_f')

for each in Rare_m:
    titanic['title'] = titanic['title'].replace(each, 'Rare_m')

titanic['title'].unique()
# 이 결과는 또 어떻게 해석할 수 있을까
# 한편 2등 항해사 라이톨러는 선장에게 여성과 어린이를 먼저 태울 것을 건의했고 선장은 이를 승인했다
# https://namu.wiki/w/%ED%83%80%EC%9D%B4%ED%83%80%EB%8B%89%ED%98%B8%20%EC%B9%A8%EB%AA%B0%20%EC%82%AC%EA%B3%A0

titanic[['title', 'survived']].groupby(['title'], as_index=False).mean()



머신러닝을 이용한 생존자 예측

# 간단히 구조확인

titanic.info()
# 머신러닝을 위해 몇 컬럼을 숫자로 변경해야겠다

titanic['sex'].unique()
# Label Encode를 사용

from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(titanic['sex'])
titanic['gender'] = le.transform(titanic['sex'])
titanic.head()
# 결측치는 어쩔 수 없이 포기하자

titanic.info()
titanic = titanic[titanic['age'].notnull()]
titanic = titanic[titanic['fare'].notnull()]
titanic.info()
# 상관관계

correlation_matrix = titanic.corr().round(1)
sns.heatmap(data=correlation_matrix, annot=True, cmap='bwr')
# 먼저 특성을 선택하고, 데이터를 나누자
# 특성은 pclass, age, sibsp, parch, fare, gender로 선정

from sklearn.model_selection import train_test_split

X = titanic[['pclass', 'age', 'sibsp', 'parch', 'fare', 'gender']]
Y = titanic['survived']

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=13)
# 일단 DecisionTree

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

dt = DecisionTreeClassifier(max_depth=4, random_state=13)
dt.fit(X_train, Y_train)

pred = dt.predict(X_test)
print(accuracy_score(Y_test, pred)) # Y_test, pred 데이터로 맞춰 정확도 확인




특정 인물을 특정

# 특정 인물 디카프리오를 특정
# 디카프리오의 생존률

import numpy as np

dicaprio = np.array([[3, 18, 0, 0, 5, 1]])
print('Decaprio : ', dt.predict_proba(dicaprio)[0, 1]) # 할 때마다 다른 것이 맞음
# 윈슬릿의 생존률

winslet = np.array([[1, 16, 1, 1, 100, 0]])
print('Winslet : ', dt.predict_proba(winslet)[0, 1])



몇 가지 참고 사항

  • 마크다운 : jupyter를 아름답고 실용적으로 꾸며주는 도구
    - 샵, 별표, 제목과 기울임, 굵게, 가로 구분선, 인용문, 수식

💻 출처 : 제로베이스 데이터 취업 스쿨

profile
#데이터분석 #퍼포먼스마케팅 #데이터 #디지털마케팅

0개의 댓글