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

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

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

 

이전까지 전처리 과정과 데이터 탐색을 마쳤으므로 이번에는 데이터 가공을 해보겠습니다. 

 

데이터 가공

1. Survived 속성 별도 분리 후 클래스 결정값 데이터 세트로 설정 (학습 데이터 생성)

원본 CSV 데이터를 다시 로딩한 뒤, 피처 데이터 세트와 레이블 데이터 세트 추출 생성된 데이터 세트에 transform_features() 함수로 일괄 데이터 가공합니다.

 

titanic_df = pd.read_csv('./titanic_train.csv')  # 재로딩
y_titanic_df = titanic_df['Survived']  # Survived 값만 별도로 y 값 지정 
X_titanic_df= titanic_df.drop('Survived',axis=1)  # 기존 칼럼 삭제 후 새 칼럼 생성

X_titanic_df = transform_features(X_titanic_df)  # 일괄 데이터 가공

 

2. 테스트 데이터 세트 추출

학습 데이터를 기반으로 train_test_split() API 로 별도의 테스트 데이터 세트 추출합니다. (학습용 데이터와 테스트용 데이터 분리)

 

테스트 데이터 세트의 크기는 전체의 20%로 설정(0.2) = 전체 데이터 중 테스트 데이터가 20%, 학습 데이터가 80%로 데이터를 분할합니다.

 

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test=train_test_split(X_titanic_df, y_titanic_df, \
                                                  test_size=0.2, random_state=11)

 

  • X_train 는 학습용 피처 데이터 세트y_train 는 학습용 레이블 세트
  • y_test 는 테스트용 레이블 세트
  • X_test 는 테스트용 피처 데이터 세트
  • X_titanic_df 는 피처 데이터 세트test_size=0.2 는 전체 데이터 중 테스트 데이터 세트의 비율
  • random_state=11 는 난수를 발생시키기 위한 기초 데이터
  • y_titanic_df 는 레이블 데이터 세트

 

타이타닉 생존자 예측

 

1. 결정트리DecisionTreeClassifier, 랜덤 포레스트RandomForestClassifier, 로지스틱 회귀LogisticRegression를 이용한 생존자 예측 알고리즘 생성

train_test_split() 으로 분리한 학습 데이터와 테스트 데이터를 기반으로 머신러닝 모델 학습(fit), 예측(predit) 합니다.

accuracy_score() API를 사용할 거예요.

 

 

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

# 결정트리, Random Forest, 로지스틱 회귀를 위한 사이킷런 Classifier 클래스 생성
dt_clf = DecisionTreeClassifier(random_state=11)
rf_clf = RandomForestClassifier(random_state=11)
lr_clf = LogisticRegression(solver='liblinear')

# 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('RandomForestClassifier 정확도:{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('LogisticRegression 정확도: {0:.4f}'.format(accuracy_score(y_test, lr_pred)))

 

  • Classifier 생성

로지스틱 회귀의 생성인자로 설정된 LogisticRegression(solver='liblinear') 는 최적화 알고리즘을 liblinear으로 설정하는 것. (LIBLINEAR와 LIBSVM은 많은 선형 분류기를 아주 빠르게 훈련할 수 있는 장점이 있습니다. C/C++ 라이브러리(http://www.csie.ntu.edu.tw/~cjlin/liblinear/) 작은 dataset의 경우 'liblinear' 이 좋은 선택일 수 있으며, 'sag' 과 'saga' 는 큰 dataset에서 더욱 빠르게 동작합니다.)

Classifier 는 TEST 단계에서 모르는 X가 입력으로 들어왔을 때, 몇 개의 label 중 하나를 선택하는 일을 함, 학습 단계에서는 label 이 있는 데이터를 가지고 test 단계를 거칠 수 있도록 합니다. (그럴 듯 한 것을 찍는 것. 확률이 가장 큰 것.)

 

  • 결정트리의 학습/예측/평가

accuracy_score : 정답률(=정확도)를 의미하며 실제 데이터 중 맞게 예측한 데이터의 비율을 뜻합니다.

{0:.4f}'.format(accuracy_score(y_test, dt_pred))) 결정트리 클래스로 예측한 값에 대하여 정확도를 계산하고 그 정확도를 소숫점 4자리까지 표현하여 출력합니다. 

 

 

2. 교차 검증 (1)

  • 교차 검증을 위한 사이릿런 모델 model_seletion 패키지의 KFold 클래스, cross_val_score(), GridSearchCV 클래스를 모두 사용합니다.
  • exec_kfold 함수를 만들어 KFold 클래스로 교차 검증 수행. 폴드 개수는 5개로 설정합니다. K란 몇 조각이라는 뜻이며 n_splits 는 데이터 분할 수이며, 전체 데이터 수를 넘을 수 없습니다. 이 경우 5개로 제한됩니다.
  • 만약 X_titanic_df 100개 이고 K Fold를 5개로 설정을 했다고 가정할 때 다음과 같은 코드가 수행된다면,

    for train_index, test_index in kfold.split(X_titanic_df)):

 

(1) 해당 for 문은 5번 loop 를 수행하면서 X_titanic_df 에 접근할 수 있는 index값을 각각 train_index와  test_index 로 할당합니다. 그리고 loop를 돌 때마다 train_index와 test_index값이 교차되어 할당됩니다.

(2) 가령 첫번째 loop 시에는 index 0 부터 79번 까지가 train_index에, 80번 부터 99번 까지가 test_index로 할당 될 수 있습니다. 그러므로 80개의 학습 데이터와 20개의 테스트 데이트를 X_titaic_df에 train_index, test_index로 접근하여 만들 수 있는 것입니다. 

(3) 이런 식으로 최종 5번을 loop를 돌면서 서로 다른 80개의 학습 데이터와 20개의 테스트 데이터를 생성됩니다. 

(4) enumerate로 감싼 형식은 몇번째 loop 수행이 되는지를 iter_count로 반환하는 기능이 추가됩니다. 

    for iter_count, (train_index, test_index) in enumerate(kfold.split(X_titanic_df))

 

predict : 새로운 속성을 넣었을 때, 그 클래스에 속하는지 속하지 않는지를 나타내는 1 또는 0 으로 구성된 벡터를 반환하여 줍니다. 

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)

3. 교차 검증 (2)

  • 이번에는 cross_val_score() API를 통해 수행

def exec_kfold() 함수와는 결과가 다른 이유는 cross_val_score()가 StratifiedKFold 를 통해서 세트를 분할하기 때문입니다. 사이킷런에서는 K-fold 교차 검증을 위해 Kfold 와 stratifiedKfold 클래스를 제공하는데, K-fold는 K번마다 K개의 학습 데이터 set을 나누어 평가를 진행합니다. 

 

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, accuarcy in enumerate(scores):
    print("교차 검증 {0} 정확도 {1:4f}".format(iter_count, accuracy))

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

 

  • Kfold : 가장 보편적인 K-fold 방법으로 학습 데이터 set과 검증 데이터 set을 나누어 진행합니다. Kfold 는 알아서 겹치지 않게 데이터를 나줘누고, 그 형태를 index 로 제공합니다. 하지만 이것은 class imbalance를 고려하지 않는다는 단점이 있습니다. (일정한 간격으로 잘라서 사용.)
  • stratifiedKFold : 불균형한 DaraSet을 위한 KFold 방법으로 각 클래스에 대한 비율을 고려하여 데이터 set을 나눕니다. 클래스 분포를 고려하기 위해 split 할 때 y의 라벨 정보를 주면 그것을 고려하여 사용합니다. (타겟에 속성 값의 갯수를 동일하게 하게 가져감으로써 kfold 같이 데이터가 한 곳으로 몰리는 것을 방지합니다.)

4. 최적 하이퍼 파라미터 찾기

마지막으로 GridSearchCV를 이용한 결정 트리의 최고의 파라미터를 찾고 예측 성능을 측정합니다.

 

GridSearchCV 는 교차검증과 하이퍼 파라미터(모델링할 때 사용자가 직접 세팅해주는 값을 뜻함)를 동시에 수행할 수 있는 유용한 API.

 

머신 러닝에서 모델의 성능향상을 위해 쓰이는 기법 중 하나로, 사용자가 직접 모델의 하이퍼 파라미터의 값을 리스트로 입력하면 값에 대한 경우의 수마다 예측 성능을 측정, 평가, 비교 하면서 최적의 하이퍼 파라미터 값을 찾습니다.

단, 시간이 오래 걸린다는 단점이 있습니다.

 

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

 

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)

-> cv 는 5개의 폴드 세트를 지정하고 하이퍼 파라미터는 max_depth, min_samples_split, min_samples_leaf 를 변경하면서 수행합니다.

 

best_dclf = grid_dclf.best_estimator_ 최적의 하이퍼 파라미터로 학습된 estimator를 통해 예측 정확도를 측정합니다. 

 

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

 

하이퍼 파라미터 변경 전보다 약 8% 증가한 87.15%의 정확도로 향상되었습니다. 

 

여기까지 사이킷런을 기반으로 머신러닝 애플리케이션을 구현했습니다. 

머신러닝 애플리케이션은 다음과 같은 과정을 거칩니다. 

 

(1) 데이터 가공 및 변환 과정의 전처리 작업 (오류 데이터 보정, 결손값Null 처리 등의 데이터 클렌징 작업, 인코딩 작업, 데이터의 스케일리과 정규화 작업 등으로 머신러닝 알고리즘이 최적으로 수행될 수 있게 데이터 사전처리 하는 작업 ) 

(2) 데이터를 학습 데이터와 테스트 데이터로 분리하는 데이터 세트 분리작업

(3)  학습 데이터를 기반으로 머신러닝 알고리즘을 적용해 모델 학습

(4)  학습된 모델을 기반으로 테스트 데이터 대한 예측 수행

(5) 예측된 결괏값을 실제 결괏값과 비교해 머신러닝 모델에 대한 평가 수행 


개인적으로는 학습이 조금 어려웠던터라,

캐글에 올라와있는 데이터 세트로 많이 예제를 실행해보아야 할 것 같습니다 ^^ㅠ 

여기까지 보시느라 수고많으셨습니다. 

 

 

 

 

반응형