지난 포스팅에서는 주요 칼럼이라고 생각되는 것들과 레이블 데이터인 생존(Survived)의 관계를 시각화하는 과정까지 했다. 

 

레이블 인코딩

 

이번에는 문자열로 되어있는 데이터, 즉, DataFrame에서는 object 형이라고 표현되어있는 데이터를 숫자형으로 바꿔주는 작업을 할 것이다. 이런 과정을 LabelEncoding이라고 하고, Scikit learn에서는 LabelEncoder 클래스를 통해서 구현할 수 있다. LabelEncoder 객체를 통해서 fit / transform 과정을 거치면 0 ~ (카테고리 유형 수 -1) 까지의 숫자 값으로 변환된다. 

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

 

 

 

최종 전처리 함수 제작

 

이미지를 보면 기존에는 string 형태(object) 였던 'Sex', 'Cabin', 'Embarked' 칼럼의 데이터 값들이 전부 숫자형으로 바뀐 것을 확인할 수 있다. Null 처리 / 불필요한 속성 제거('PassengerId' ,' Name', 'Ticket') / 레이블 인코딩을 한꺼번에 수행하는 함수를 제작한다.

 

 

#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
    
#레이블 인코딩 수행
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

 

 

 

학습 / 테스트 데이터 분리

 

원본 데이터를 다시 로딩하고, 전처리 함수(transform_features())를 실행한다. 이렇게 전처리한 데이터를 train_test_split() 메서드를 통해서 학습 데이터와 테스트 데이터로 분리한다. 

 

#원본 데이터를 재로딩하고, 피처 데이터 세트와 레이블 데이터 세트 추출 
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)

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)

 

 

 

학습 / 예측 수행

 

이제 Scikit-Learn에서 제공하는 결정 트리, 랜덤 포레스트, 로지스틱 회귀를 알고리즘 모델로 사용할 것이고, 정확도를 성능 평가 지표로 사용할 것이다. 그러기 위해서 Scikit-Learn으로부터 해당 모듈을 임포트하여 학습 - 예측 - 평가의 과정을 진행한다. 

 

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

#Decision Tree 학습 / 예측 / 평가
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)))

 

 

결정트리는 78%, 랜덤 포레스트는 83%, 로지스틱 회귀는 86%의 정확도가 나오는 것을 확인할 수 있다. 그 후에, 성능 향상을 위해서 교차 검증을 수행한다. 교차 검증은 KFold 혹은 cross_val_score가 있는데, 둘이 어떤 차이점을 가지고 있는지에 대해서도 알아볼 것이다. 

 

 

교차 검증 (KFold, cross_val_score)

 

 

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

평균 정확도가 78.23%정도 나온 것을 확인할 수 있다. 이후에 cross_val_score를 통해서 교차 검증을 수행해본다. 

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

 

 

이 경우에는 78.35로 미세하게나마 성능이 향상된 것을 볼 수 있다. 이는 레이블 데이터의 비율을 맞춰서 학습 / 테스트 데이터로 분류하는 StratifiedKFold를 사용하기 때문이다. 또한, 함수를 제작하는 데에 많은 코드가 필요했던 KFold보다 cross_val_score 메서드를 이용하면 상대적으로 간단하게 교차 검증을 수행할 수 있다. 

 

 

하이퍼 파라미터 튜닝 (GridSearchCV)

 

 

마지막으로 하이퍼 파라미터 마지막으로 하이퍼 파라미터 튜닝을 진행다. 'max_depth', 'min_samples_split', 'min_samples_leaf' 하이퍼 파라미터를 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('GridSerachCV 최고 정확도 : {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))

 

'max_depth'는 3, 'min_samples_leaf'는 1, 'min_samples_split'은 2일때 가장 정확도가 높다는 것을 확인할 수 있다. 이때의 정확도는 79.97%였고, 테스트 세트에서는 87.15%인 것을 확인할 수 있다. 이전에 약 78%였던 것을 감안하면 거의 10%가 올랐다. 이렇게 성능이 향상되는 것이 일반적인 경우는 아니지만, 데이터의 수가 적어서 예측 성능이 많이 증가한 것으로 추정된다.

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기