AI 머신러닝 딥러닝/파이썬 머신러닝 입문 공부일지

파이썬 머신러닝 입문 공부일지 17. 사이킷런으로 캐글 타이타닉 생존자 예측하기 (1)

Tomitom 2023. 1. 6. 14:47
반응형

캐글에서 제공하는 타이타닉 탑승자 명단 데이터를 기반으로 생존자 예측을 해보겠습니다. 

 

Titanic 생존자 예측 머신러닝 실습

  • 실습 목적 : 사이킷런 사용 및 데이터 전처리와 학습과정에 대한 연습
  • 실습 내용 : 타이타닉 호 침몰 사건 당시의 사망자와 생존자를 구분하는 요인 분석을 통해 승객의 생존 여부를 예측한다.

 

전처리 과정 시작

1. https://www.kaggle.com/c/titanic/data 에서 타이타닉 탑승자 데이터 명단 다운로드 후 해당 데이터에 대한 개략적인 설명 확인합니다.

  • PassengerId : 각 승객의 고유 번호
  • Survived : 생존 여부(종속 변수) 0 = 사망 1 = 생존
  • Pclass : 객실 등급 - 승객의 사회적, 경제적 지위 1st = Upper 2nd = Middle 3rd = Lower
  • Name : 이름
  • Sex : 성별
  • Age : 나이
  • SibSp : 동반한 Sibling(형제자매)와 Spouse(배우자)의 수
  • Parch : 동반한 Parent(부모) Child(자식)의 수
  • Ticket : 티켓의 고유넘버
  • Fare : 티켓의 요금
  • Cabin : 객실 번호
  • Embarked : 승선한 항 C = Cherbourg Q = Queenstown S = Southampton

 

2. 라이브러리 임포트 후 판다스의 read_csv() 를 사용해 DataFrame 로딩합니다.

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

  • 각각의 함수를 사용해서 간편하게 그래프를 만들고 변화를 줄 수 있습니다. 

import seaborn as sns

  • matplotlib가 제공하지 않는 기능들을 보완해주는 역할로, 서로 기능을 고유합니다.

%matplotlib inline

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

 

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)

 

 

만약 해당 import 중에서 설치가 되어 있지 않은 모듈이 있다면 별도로 설치를 해야 합니다. 

 

< jupyter 사용 시 import 되지 않은 모듈 설치하는 법 > 

아나콘다 프롬프트 열기 ->  conda env list  명령어 입력하여 가상환경 모듈을 확인

-> conda activate 사용하는_가상환경_이름 명령어 입력하여 가상환경 모듈을 바꿈

-> 가상환경을 바꾼 뒤에 pip install seaborn 명령어로 설치해줍니다. 

 

 

코드 실행 결과는 다음과 같습니다. 

 

 

3. info() 메서드를 통해 총 데이터 건수와 데이터 타입, Null 건수를 확인합니다.

print('\n ###학습 데이터 정보###')
print(titanic_df.info())

 

 

  • RangeIndex: DataFrame index 의 범위인 전체 row 수를 확인
  • Data columns : 전체 columns 수를 확인
  • Dtype : 각 컬럼별 데이터 확인
  • Non-Null Count 몇 개의 데이터가 Null 값이 아닌지를 확인

 

4. Null 값 처리

사이킷런은 Null 값을 허용하지 않으므로 DataFrame 의 fillna() 함수를 사용해서 Null 값을 변경합니다.

상기 코드인 info() 에서 Null 값이 확인된 Columns 에 대해 Null 값을 처리해줍니다.

Age의 경우 평균 나이, 그 외의 칼럼은 'N'값으로 변경 그 뒤 모든 칼럼에 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('데이터 세트 Null 값 개수 : ', titanic_df.isnull().sum().sum())

 

  • mean() : 평균값을 구하는 함수
  • inplace=True rename, drop, fillna 등의 메소드를 사용해서 변경될 데이터 프레임을 저장 할 때 사용된다. inplace = False (저장 안 함) inplace = True (저장함)
  • isnull() 함수는 결측값을 확인할 때 쓰는 함수로 데이터의 값이 null 이면 True를 반환한다.
  • isnull().sum().sum() 을 통해 총 Null 의 갯수를 확인

 

 

5. 피처들의 값 분류

info() 에서 object 로 확인된 문자열 중 Name, Sex, Ticket, Cabin, Embarked 중에서 유의미한 정보인 Sex, Cabin, Embarked 에 대하여 피처 값을 분류를 합니다. 

 

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())

 

value_counts() 는 해당 정렬의 분포값으로, 기본적으로 지정된 columns 의 value에 대하여 각 고윳값에 대한 갯수를 반환합니다. 즉, 값이 몇 개가 존재하는지 카운팅합니다.

 

 

6. 중복 속성값 정리

Columns 중 Cabin 의 선실 C의 값이 중복되므로 해당 값을 알파벳 C로 통일합니다. 

titanic_df['Cabin'].str 여기에 들어있는 스트링 값들에 대한 어떤 수행을 하겠다는 것으로 [:1] 0번째 요소까지 슬라이싱합니다.  [0] 과 같은 의미입니다.

해당 데이터프레임을 상위 3개만 확인해서 C의 값이 정상적으로 슬라이싱 되었는지 확인합니다.

 

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

 

 

데이터 탐색

1. 알고리즘 예측 시행 전 각 Columns 별 생존 확률을 확인하여 데이터 탐색합니다.

  • 성별에 따른 생존 숫자 확인
titanic_df.groupby(['Sex','Survived'])['Survived'].count()

 

df.groupby() 기능을 통해 데이터를 그룹별로 분할하여 독립된 그룹에 대하여 별도의 데이터 처리를 하거나 그룹별 통계량을 확인할 수 있습니다. split 단계에서 Columns 의 독립된 그룹인 Sex, Survived 를 나누고 각각을 카운팅합니다. 

 

 

 

 

1-2. 시본Seaborn 패키지로 시각화

데이터 분석을 위한 시각화로 seaborn 패키지를 이용하여 그래프를 통해 확인합니다. 

 

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

 

barplot() 함수 : 가로 막대 차트

 

 

2. hue 파라미터 추가

  • 객실 등급에 따른 생존확률 확인합니다. 

객실 등급과 성별에 따른 생존확률을 확인하기 위해 Pclass와 hue 파라미터를 추가 각 선실 클래스 별로 어떤 성별이 얼마나 생존하였는지 Sex 의 분류와 Pclass 에 따라 Survived가 얼마나 분포 되어 있는지 확인이 가능합니다. 

 

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

3. 범위 별로 카테고리 분류

  • 나이에 따른 생존확률 확인합니다. 

각 연령대에 따른 생존확률을 확인하기 위해 범위 별로 카테고리 값을 할당합니다. 

 

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

plt.figure(figsize=(10,6))

group_names = ['Unknown', 'Baby', 'Child', 'Teenager', 'Student', 'Young Adult', 'Adult', 'Elderly']

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)

 

  • def 함수 기능으로 get_category 에서 age 값을 받아 if 조건문으로 각 범위별로 카테고리를 할당
  • plt.figure() 기능으로 막대그래프의 크기 사이즈를 크게 설정한다.
  • group names 을 지정해 순차적으로 x축의 값을 연령의 오름차순으로 설정
  • lambda 식으로 get_category() 함수를 반환값으로 지정한다.

apply() 함수를 적용 : 데이터 프레임의 컬럼 중 Age 의 값을 받아 get_category(x)를 적용하고 새로운 Age_cat 데이터 프레임 값으로 반환 받습니다. (기존의 데이터프레임은 바뀌지 않습니다. 기존의 프레임에 적용하고 싶다면 다시 객체를 해당 컬럼에 할당시켜야 합니다.)

  • barplot 으로 각 카테고리 그룹 이름순으로 정렬합니다.
  • drop() 함수는 axis 값에 따라 특정 칼럼 또는 특정 행을 삭제합니다. axis 0 은 row 방향 축, axis 1 은 calumns 방향 축
  • 기존 칼럼을 가공해 새로운 칼럼을 만들고 삭제하는 경우 axis=1 로 설정하고 드롭합니다. 

 

4. 문자열 카테고리 피처 -> 숫자형 카테고리 피처로 인코딩

 

from sklearn import preprocessing

def encode_features(dataDF):
    features = ['Cabin', 'Sex', 'Embarked']
    for feature in features:
        le = preprocessing.LabelEncoder()
        le = le.fit(dataDF[feature])
        dataDF[feature] = le.transform(dataDF[feature])
        
    return dataDF

titanic_df = encode_features(titanic_df)
titanic_df.head()
  • def encode_features 함수 생성

데이터 프레임을 변수로 받고 sklearn.preprocessing 안에 있는 LabelEncoder 클래스를 이용해 레이블 인코딩(단순히 숫자로 변환하는 것)을 적용합니다.

LabelEncoder 객체는 카테고리 값의 유형 수에 따라 0 ~ (카테고리 유형수 -1)까지의 숫자값으로 변환합니다.

 

  • 'Cabin', 'Sex', 'Embarked' 을 각각 반복문으로 인코딩

라벨 인코딩을 한 le 변수를 fit() 메소드에 학습용 피처 데이터 속성과 결정값 데이터 세트를 입력해 호출하여 학습을 시작합니다. transform() 메소드는 입력된 객체와 동일하게 인덱스된 객체를 반환하며, 다중연산을 가능하게 합니다.

 

5. 가공한 피처 내역 정리 및 재사용 가능한 함수로 생성

최종적으로 데이터를 전처리 하는 함수 transform_features() 생성하기 위한 메소드들

  • Null 처리
  • 불필요한 피처 제거(drop으로 생존확률 값에 무의미한 데이터인 PassengerId, Name, Ticket 피처를 제거)
  • 인코딩 수행하는 내부 함수로 구성
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)
    df['Fare'].fillna(0, inplace=True)
    return df

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

# 레이블 인코딩 수행. (중복되는 단어를 스펠링 하나로 합치고, fit 과 transform으로 변환)
def format_features(df):
    df['Cabin'] = df['Cabin'].str[:1]
    features = ['Cabin', 'Sex', 'Embarked']
    for feature in features:
        le = LabelEncoder()
        le = le.fit(df[feature])
        df[feature] = le.transform(df[feature])
    return df

# 앞에서 설정한 데이터 전처리 함수 호출
def transform_features(df):
    df = fillna(df)     # Null 처리 
    df = drop_features(df)    # 불필요한 피처 처리
    df = format_features(df)     # 레이블 인코딩, 변환
    return df

 

여기까지 데이터 확인 및 가공을 위한 전처리 작업이 끝났습니다. 

다음에는 데이터를 직접 가공하는 것을 해볼게요. 

반응형