1. 타이타닉 데이터 살펴보기
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
![image](https://user-images.githubusercontent.com/47748246/234761118-92a12c60-185d-4b0a-ae7c-1539cf6c0e3c.png)
- 컬럼
- Passengerid: 탑승자 데이터 일련번호
- survived: 생존여부, 0=사망, 1=생존
- pclass: 티켓의 선실 등급 (1=일등석, 2=이등석, 3=삼등석)
- sex: 탑승자 성별
- name: 탑승자 이름
- Age: 탑승자 나이
- sibsp: 같이 탑승한 형제자매 또는 배우자 인원수
- parch: 같이 탑승한 부모님 또는 어린이 인원수
- ticket: 티켓번호
- fare:요금
- cabin: 선실번호
- embarked:중간정착항구 C=Cherbourg, Q=Queenstown, S=Southampton
1) Null 처리
titanic_df.info()
---------------------------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890 ## 전체 로우 수
Data columns (total 12 columns): ## 전체 컬럼 수
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
- RangeIndex : DataFrame 인덱스의 범위 → 전체 로우 수
- Age, Cabin, Embarked 칼럼은 각각 714개, 204개, 889개의 Not Null 값을 가지고 있다.
⇒ 사이킷런 머신러닝 알고리즘은 Null 값을 허용하지 않으므로 Null 값을 어떻게 처리할지 결정해야 한다.
# 사이킷런 머신러닝 알고리즘은 NULL 값을 허용하지 않으므로 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)
# null 개수 확인
print('after null 개수 : ',titanic_df.isnull().sum().sum())
2) 값 분포 확인
titanic_df['Cabin'].value_counts()
-------------------------------------------------------------------------------
N 687 # N이 압도적으로 많다.
C23 C25 C27 4 # 여러 Cabin이 한거번에 표기됨
G6 4
B96 B98 4
C22 C26 3
...
E34 1
C7 1
C54 1
E36 1
C148 1
Name: Cabin, Length: 148, dtype: int64
titanic_df['Cabin'] = titanic_df['Cabin'].str[:1]
titanic_df['Cabin'].value_counts()
---------------------------------------------------------------------------------
N 687
C 59
B 47
D 33
E 32
A 15
F 13
G 4
T 1
Name: Cabin, dtype: int64
3) 성별과 선실 등급에 따른 생존자 수 확인
# 성별에 따른 생존자 수 비교
titanic_df.groupby(['Sex', 'Survived'])['Survived'].count()
------------------------------------------------------------------------------
Sex Survived
female 0 81
1 233
male 0 468
1 109
Name: Survived, dtype: int64
sns.barplot(x='Sex', y = 'Survived', data=titanic_df)
![image](https://user-images.githubusercontent.com/47748246/234761177-d33b288a-4ecd-4910-889b-1b3bf0e031eb.png)
sns.barplot(x='Pclass', y = 'Survived', hue='Sex' ,data=titanic_df)
![image](https://user-images.githubusercontent.com/47748246/234761206-5091d9db-2f13-4222-9ba8-3c71adde2681.png)
# Age에 따른 생존 확률 -> 값 종류가 많으므로 범위별로 분류해 카테고리 값을 할당
# 입력 age에 따라 구분 값을 반환하는 함수 설정. DataFrame의 apply lambda 식에 활용
def get_category(age):
cat = ''
if age <=-1: cat='Unkown'
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
# 막대 그래프의 크기 figure를 더 크게 설정
plt.figure(figsize=(10, 6))
# X축의 값을 순차적으로 표시하기 위한 설정
group_names=['Unkown', '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)
![image](https://user-images.githubusercontent.com/47748246/234761262-02176515-d8d7-4c70-86a3-7f32907d2485.png)
4) 문자열 타입 → 숫자형 피처로 변환
- LabelEncoder : 카테고리 값의 유형 수에 따라 0 ~(카테고리 유형 수 -1)까지의 숫자 값으로 변환
from sklearn import preprocessing
# 남아있는 문자열 카테고리 피처를 숫자형 카테고리 피처로 변환 => LabelEncoder
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()
2. 타이타닉 머신러닝 분석 수행
1) 데이터 전처리
# 데이터 전처리 함수
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
# 레이블 인코딩 수행
def format_features(df):
df['Cabin'] = df['Cabin'].str[:1]
features = ['Cabin', 'Sex', 'Embarked']
for feature in features:
le = preprocessing.LabelEncoder()
le = le.fit(df[feature])
df[feature] = le.transform(df[feature])
return df
def transform_features(df):
df = fillna(df)
df = drop_features(df)
df = format_features(df)
return df
from sklearn import preprocessing
titanic_df = pd.read_csv('./titanic/train.csv')
y_titanic_df = titanic_df['Survived']
X_titanic_df = titanic_df.drop('Survived', axis=1)
X_titanic_df = transform_features(X_titanic_df)
X_titanic_df.head(3)
2) 머신러닝 분석 수행
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
# 테스트 데이터 세트 추출
X_train, X_test, y_train, y_test = train_test_split(X_titanic_df, y_titanic_df, test_size=0.2, random_state=11)
# 머신러닝 알고리즘 3개 비교
# 결정트리, Random Forest, 로지스틱 회귀를 위한 사이킷런 Classifier 클래스 생성
dt_clf = DecisionTreeClassifier(random_state=11)
rf_clf = RandomForestClassifier(random_state=11)
lr_clf = LogisticRegression()
# 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('RandomForest 정확도 : {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('logistic Regression 정확도 : {0:.4f}'.format(accuracy_score(y_test, lr_pred)))
- DecisionTreeClassifier 정확도: 0.7877
- RandomForestClassifier 정확도:0.8547
- LogisticRegression 정확도: 0.8492
3) 교차 검증
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)
교차 검증 0 정확도: 0.7542
교차 검증 1 정확도: 0.7809
교차 검증 2 정확도: 0.7865
교차 검증 3 정확도: 0.7697
교차 검증 4 정확도: 0.8202
평균 정확도: 0.7823
- cross_val_score() 검증
- K 폴드의 평균 정확도와 다름
- StratifiedKFold를 이용해 폴드 세트를 분할하기 때문
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))")
교차 검증 0 정확도 : 0.7430
교차 검증 1 정확도 : 0.7753
교차 검증 2 정확도 : 0.7921
교차 검증 3 정확도 : 0.7865
교차 검증 4 정확도 : 0.8427
평균 정확도 : {0: .4f}.format(np.mean(scores))
- GridSearchCV
- cv : 5개의 폴드 세트 지정
- 하이퍼 파라미터 :
max_depth
, min_samples_split
, min_samples_leaf
를 변경하면서 성능을 측정
- 최적 하이퍼 파라미터로 학습된 Estimator를 이용해 train_test_split()으로 분리된 테스트 데이터 세트에 예측을 수행해 예측 정확도를 출력
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))
GridSearchCV 최적 하이퍼 파라미터 : {'max_depth': 3, 'min_samples_leaf': 5, 'min_samples_split': 2}
GridSearchCV 최고 정확도 : 0.7992
테스트 세트에서의 DecisionTreeClassifier 정확도 : 0.8715