머신러닝 (Machine Learning)/분석 연습

타이타닉 (분석연습)

DS지니 2021. 2. 11. 20:21
728x90
반응형

* 이번 타이타닉 데이터 분석은 오직 train/test data로만 나눴고, test 결과는 다소 test set에 과적합 되었습니다.

또한 평가지표는 정확도(Accuracy)만 측정되어 정확한 평가가 이루어지지 않았음을 미리 알려드립니다.

 

1. 분석 배경 

 

1) 데이터 살피기

df = pd.read_csv('train (1).csv')
df.head(3)

  • PassengerId : 탑승자 데이터 일련번호
  • Survived : 생존여부 (0=사망 1=생존)
  • Pclass : 티켓의 선실 등급 (1=일등석 2=이등석 3=삼등석)
  • Name : 탑승자 이름
  • Sex : 탑승자 성별
  • Age : 탑승자 나이
  • SibSp : 같이 탑승한 형제자매 또는 배우자 인원수
  • Parch : 같이 탑승한 부모님 또는 어린이 인원수
  • Ticket : 티켓 번호
  • Fare : 요금
  • Cabin : 선실번호
  • Embarked : 중간 정착 항구(C=Cherbourg Q=Queenstown S=Southampton)

▶결과

( Target : Survived ) 숫자형 카테고리형
필요한 feature Pclass, Age, SibSp, Parch, Fare Sex, Cabin, Embarked
필요없는 feature PassengerId  Name , Ticket
# 필요없는 feature 제거
df.drop(['PassengerId','Name','Ticket'],axis=1,inplace=True)
df

 

2) 데이터 결측치와 타입 확인 후 처리

df.info()

▶결과

* 결측치 있는 Feature : Age , Cabin, Embarked
# 결측값 정리
df['Age'].fillna(df['Age'].mean(),inplace=True)
df['Cabin'].fillna('N', inplace=True)
df['Embarked'].fillna('N', inplace=True)
print('총 결측치 수:',df.isnull().sum().sum())

# 문자열 피처
print('Sex 값 분포 :\n',df['Sex'].value_counts())
print('\nCabin 값 분포 :\n', df['Cabin'].value_counts())
print('\nEmbarked 값 분포 :\n', df['Embarked'].value_counts())

# Cabin 앞글자는 선실 등급으로 보임
df['Cabin'] = df['Cabin'].str[:1]
df['Cabin'].head()

2. 분석 목표

 

필요한 feature들로 생존율 예측하기

 

3. 데이터 시각화/ 모델링(스토리텔링)

 

1) 관련있는 feautres 확인

  1. 여성과 아이들, 노약자가 제일 먼저 구조 대상일 것이다.
  2. 그리고 아마 그 다음이 부자와 유명인 이었을 것이다.
  3. 삼등실에 탄 많은 가난한 사람들의 사망률이 높을 것이다.

성별과 나이, 객실등급이 생존 확률에 어떤 영향을 미쳤는지 비교해 보겠습니다.

 

df.groupby(['Sex','Survived'])['Survived'].count()

# 성별에 따른 생존율
sns.barplot(x='Sex',y='Survived',data=df)

성별에 따른 생존율

▶결과

전체적으로 남성의 수(577명)가 여성의 수(314명)보다 많지만, 생존률은 남성(약 19%)보다 여성(약 75%)이 훨씬 크다.
결론 : 성별은 생존율에 영향을 끼친다.

 

# 객실 등급과 성별에 따른 생존율
sns.barplot(x='Pclass', y='Survived', hue='Sex',data=df)

객실등급, 성별에 따른 생존율

▶결과

여성의 경우 1,2 등실에 따른 생존율 차이가 많이 없으나, 3등실의 경우 생존율이 상대적으로 많이 떨어진다.
남성의 경우 일등실의 생존 확률이 2,3 등실보다 2배 이상 높습니다.
결론 : 객실 등급은 생존율에 영향을 끼친다.

 

# 나이에 따른 생존확률
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))

# X축을 순차적으로 표시하기 위한 설정
group_names = ['Unknown','Baby','Child','Teenager','Student','Young Adult','Adult','Elderly']

#lambda 식에 위에서 생성한 get_category() 함수를 반환값으로 지정
# get_category(X)는 입력값으로 'Age' 칼럼 값을 받아서 해당하는 cat 반환

df['Age_cat'] = df['Age'].apply(lambda x: get_category(x))
sns.barplot(x='Age_cat',y='Survived',hue='Sex',data=df, order=group_names)
df.drop('Age_cat', axis=1, inplace=True)

* seaborn은 barplot() 함수를 사용할 때 각 막대에 기본적으로 오차막대(error bar)가 함께 나타나도록 되어 있다.

그리고 이 오차막대를 그리는 범위는 기본적으로 ‘부트 스트랩 신뢰구간(Bootstrap confidence interval)’이라는 것을 사용한다.  “이 데이터를 기반으로 유사한 상황의 95 %가 이 범위 내에서 결과를 얻을 것”을 의미한다.

나이, 성별에 따른 생존율

▶결과

여성의 경우 Elderly의 생존율은 거의 98~9%로 매우 높다. 여자 Baby는 생존율이 높지만 여자 Child는 생존율이 낮다.
남성의 경우 baby, Child 순으로 생존율이 높으며, Teenager가 생존율이 가장 낮다.
결론 : 이때까지 분석한 결과 Sex, Age, PClass 등이 중요하게 생존과 관련있는 feature임을 알 수 있다.

 

2) 문자열 카테고리 Label encoding

 

문자열 카테고리 숫자형으로 바꾸기

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

df = encode_features(df)
df.head()

 

3) 머신러닝 알고리즘을 이용해 생존자 예측하기

 1. Decision Tree/Random Forest/Logistic Regression 최적화X

 2. Decision Tree/Random Forest/Logistic Regression & KFoldCV

 3. Decision Tree/Random Forest/Logistic Regression & cross_val_score()

 4. Decision Tree/Random Forest/Logistic Regression & GridSearchCV

 

1. 최적화 X (before)

 

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 사이킷런 Classifir 클래스 생성
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('DecisionTree 정확도 : {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)))

2. DecisionTree / RandomForest / Logistic Regression  &  KFold CV

# DecisionTree & KFold

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(feature)):
    # X_titanic_df 데이터에서 교차 검증별로 학습과 검증 데이터를 가리키는 index 생성
    X_train, X_test = feature.values[train_index], feature.values[test_index]
    y_train, y_test = target.values[train_index], target.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)

DecisionTree & KFold CV

 

# RandomForest & KFold

# exec_kfold 호출
exec_kfold(rf_clf, folds=5)

RandomForest & KFold CV

 

# Logistic Regression & KFold

# exec_kfold 호출
exec_kfold(lr_clf, folds=5)

Logistic Regression & KFold CV

 

 

DecisionTree / RandomForest / Logistic Regression  &  cross_val_score()

# Decision Tree & cross_val_score()

from sklearn.model_selection import cross_val_score

scores = cross_val_score(dt_clf, feature, target, cv=5)
for iter_count, accuracy in enumerate(scores):
  print("교차검증 {0} 정확도 : {1:.4f}".format(iter_count, accuracy))

print("평균 정확도: {0:.4f}".format(np.mean(scores)))

DecisionTree & Cross_val_Score()

 

# RandomForest Tree & cross_val_score()

from sklearn.model_selection import cross_val_score

scores = cross_val_score(rf_clf, feature, target, cv=5)
for iter_count, accuracy in enumerate(scores):
  print("교차검증 {0} 정확도 : {1:.4f}".format(iter_count, accuracy))

print("평균 정확도: {0:.4f}".format(np.mean(scores)))

RandomForest & Cross_val_Score()

 

# Logistic Regression & cross_val_score()

from sklearn.model_selection import cross_val_score

scores = cross_val_score(lr_clf, feature, target, cv=5)
for iter_count, accuracy in enumerate(scores):
  print("교차검증 {0} 정확도 : {1:.4f}".format(iter_count, accuracy))

print("평균 정확도: {0:.4f}".format(np.mean(scores)))

Logistc Regression & Cross_val_socre()

 

 

DecisionTree & GridSearchCV

# DecisionTree & GridSearchCV
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('test set 정확도 :{0:.4f}'.format(accuracy))

DecisionTree & Cross_val_Score()

 

RandomForest & GridSearchCV

# RandomForest & GridSearchCV
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_rclf = GridSearchCV(rf_clf, n_jobs=-1, param_grid=parameters, scoring='accuracy', cv=5)
grid_rclf.fit(X_train, y_train)

print('GridSearchCV 최적 하이퍼 파라미터:', grid_rclf.best_params_)
print('GridSearchCV 최고 정확도:{0:.4f}'.format(grid_rclf.best_score_))
best_rclf = grid_rclf.best_estimator_

#GridSearchCV의 최적 하이퍼 파라미터로 학습된 Estimator로 예측 및 평가 수행.
rpredictions = best_rclf.predict(X_test)
accuracy = accuracy_score(y_test, rpredictions)
print('test set 정확도 :{0:.4f}'.format(accuracy))

▶결과

분류모델 최적화 X KFold CV (k=5) cross_val_score(cv=5) GridSearch CV (cv=5)
DecisionTree Accuracy  78.77 % 78.23 % 78.79 % 82.12 %
RandomForest Accuracy 83.24 % 81.48 % 81.37 % 84.92 %
Logistic Regression Accuracy 82.68 % 78.34 % 78.45% x

 


 

4. 결과요약 및 제안(의사결정)

 

RandomForest 모델로 GridSearch CV (최적화) 했을 때 84.92%의 최고 성능을 보입니다.

 

그래프를 보면 전체적으로 RandomForest 모델을 사용했을 때, GridSearchCV로 최적화 했을 때 좋은 성능을 냅니다.

(물론 타이타닉의 test 데이터 수가 작기도 하고, 반복적인 test set를 이용해 예측한 과적합된 결과라 확실한 성능 결과라고는 할 수 없습니다.)

 

※ 예측 모델을 만든 Features 로는 객실등급, 탑승객 성별, 나이, 형제자매 배우자 수, 부모자식 수, 탑승요금, 객실번호, 중간 정착 항구 가 있습니다. (Pclass, Sex, Age, SibSp, Parch, Fare, Cabin, Embarked)

 

 

728x90
반응형