캐글에서 제공하는 타이타닉 탑승자 명단 데이터를 기반으로 생존자 예측을 해보겠습니다.
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
여기까지 데이터 확인 및 가공을 위한 전처리 작업이 끝났습니다.
다음에는 데이터를 직접 가공하는 것을 해볼게요.
'AI 머신러닝 딥러닝 > 파이썬 머신러닝 입문 공부일지' 카테고리의 다른 글
파이썬 머신러닝 입문 공부일지 18. 사이킷런으로 캐글 타이타닉 생존자 예측하기 (2) (0) | 2023.01.06 |
---|---|
파이썬 머신러닝 입문 공부일지 16. 데이터 전처리 (2) 피처 스케일링 (StandardScaler, MinMaxScaler) (0) | 2023.01.06 |
파이썬 머신러닝 입문 공부일지 15. 데이터 전처리 (1) 결손값 처리, 문자열 인코딩 (0) | 2023.01.06 |
파이썬 머신러닝 입문 공부일지 14. 교차 검증 (3) cross_val_score(), GridSearchCV (0) | 2023.01.05 |
파이썬 머신러닝 입문 공부일지 13. 교차 검증 (2) Stratified K 클래스 (0) | 2023.01.05 |