PL/Python

[코드 스터디] UCI-HAR 데이터셋3: 결정트리 적용

PIYA 2022. 12. 15.

Introduction

일전 스터디 UCI-HAR 데이터셋2 포스팅에서,

중복칼럼들을 확인하고 리네이밍 하는것까지 진행했다.

 

이번에는 결정트리에 그리드서치를 적용하여 최적 하이퍼파라미터를 찾고,

어떤 피쳐가 가장 큰 영향을 미쳤는지 그래프까지 그려볼 예정이다.

 

 

dataset preprocessing

이전 포스팅을 요약한 코드.

중복 피쳐명을 수정하는 로직을 get_new_feature_name_df() 함수로 만들어 각 데이터셋에 적용한다.

결과적으로 바로 사용할 수 있는 X_train, X_test, y_train, y_test를 얻었다.

import pandas as pd

def get_human_dataset( ):
    
    # 각 데이터 파일들은 공백으로 분리되어 있으므로 read_csv에서 공백 문자를 sep으로 할당.
    feature_name_df = pd.read_csv('./human_activity/features.txt',sep='\s+',
                        header=None, names=['column_index','column_name'])
    
    # 중복된 피처명을 수정하는 get_new_feature_name_df()를 이용, 신규 피처명 DataFrame생성. 
    new_feature_name_df = get_new_feature_name_df(feature_name_df)
    
    # DataFrame에 피처명을 컬럼으로 부여하기 위해 리스트 객체로 다시 변환
    feature_name = new_feature_name_df.iloc[:, 1].values.tolist()
    
    # 학습 피처 데이터 셋과 테스트 피처 데이터을 DataFrame으로 로딩. 컬럼명은 feature_name 적용
    X_train = pd.read_csv('./human_activity/train/X_train.txt',sep='\s+', names=feature_name )
    X_test = pd.read_csv('./human_activity/test/X_test.txt',sep='\s+', names=feature_name)
    
    # 학습 레이블과 테스트 레이블 데이터을 DataFrame으로 로딩하고 컬럼명은 action으로 부여
    y_train = pd.read_csv('./human_activity/train/y_train.txt',sep='\s+',header=None,names=['action'])
    y_test = pd.read_csv('./human_activity/test/y_test.txt',sep='\s+',header=None,names=['action'])
    
    # 로드된 학습/테스트용 DataFrame을 모두 반환 
    return X_train, X_test, y_train, y_test

X_train, X_test, y_train, y_test = get_human_dataset()

 

 

결정트리에 GridSearchCV 적용

max_depth와 min_samples_split 두개의 하이퍼파라미터를 대상으로 그리드서치를 적용한다.

트레이닝데이터에 적용 후 best_score_, best_params_ 프로퍼티를 확인할 수 있다.

여기서의 best_score_는 트레이닝세트에 cv=5로 피팅했을때의 스코어를 말하는거겠지.

 

데이터가 꽤 크기때문에 약 1-2분의 시간이 걸린다.

from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

# 결정트리 생성
dt = DecisionTreeClassifier()

# 그리드서치CV 세팅 및 적용, fitting
params = {'max_depth':[6,8,10], 'min_samples_split':[16]}
grid = GridSearchCV(dt, param_grid=params, scoring='accuracy', cv=5, verbose=1)
grid.fit(X_train, y_train)

# GridSearchCV의 fit()메소드를 불렀으니 best_score_, best_params_, cv_results_등을 확인할 수 있다.
print('GridSearchCV 최고 평균 정확도 수치:{0:.4f}'.format(grid.best_score_))
print('GridSearchCV 최적 하이퍼 파라미터:', grid.best_params_)
cv_results_df = pd.DataFrame(grid.cv_results_) # 보기 편하게 데이터프레임으로 바꿈

# max_depth 파라미터 값과 그때의 테스트(Evaluation)셋, 학습 데이터 셋의 정확도 수치 추출
cv_results_df[['param_max_depth', 'mean_test_score']]

 

 

결과값 확인

GridSearchCV로 최적 하이퍼파라미터를 찾아 refit된 best_estimator_를 받아 predict() 메소드를 수행한다.

성능이 올라갔는지 확인하기 위해 naive한 버전의 결정트리 예측값도 준비했다.

파라미터값이 어떻게 세팅되었는지도 확인할 수 있다.

# best_estimator_ 프로퍼티에 최적 하이퍼파라미터로 refit된 estimator가 들어가있다.
pred = grid.best_estimator_.predict(X_test)

# 그리드서치CV를 적용한 결정트리와
accuracy = accuracy_score(y_test, pred)
print('결정 트리 예측 정확도:{0:.4f}'.format(accuracy))
print('세팅한 파라미터:', grid.best_estimator_.get_params(), '\n')

# 비교대상으로 그냥 naive한 결정트리의 예측값과 파라미터
dt_comp = DecisionTreeClassifier()
dt_comp.fit(X_train, y_train)
print('그리드서치CV 적용 안한거:{0:.4f}'.format(accuracy_score(y_test, dt_comp.predict(X_test))))
print('적용 안한거 파라미터:', dt_comp.get_params())

GridSearchCV의 성능향상 비교확인

 

 

feature_importances_ 확인하기

이번에는 어떤 피쳐가 가장 중요하게 작용하였는지를 판단하는 feature_importances_ 프로퍼티를 확인해보자.

아래 그림에서 보면 tGravityAcc-min()-X가 가장 큰 값을 가졌음을 확인할 수 있다.

# 결정트리 estimator의 feature_importances_ 프로퍼티를 확인해보자
ftr_importances_values = grid.best_estimator_.feature_importances_

# Top 중요도로 정렬을 쉽게 하고, 시본(Seaborn)의 막대그래프로 쉽게 표현하기 위해 Series변환
ftr_importances = pd.Series(ftr_importances_values, index=X_train.columns)

ftr_importances.sort_values(ascending=False)

내림차순 정렬

 

seaborn 그래프로 확인하기

시각화도 중요하지. 막대그래프로 어떤 피쳐가 가장 중요한지 확인하는 작업을 해보자.

import seaborn as sns
import matplotlib.pyplot as plt

# 중요도값 순으로 Series를 정렬
ftr_top20 = ftr_importances.sort_values(ascending=False)[:20]
plt.figure(figsize=(8,6))
plt.title('Feature importances Top 20')
sns.barplot(x=ftr_top20 , y = ftr_top20.index)
plt.show()

 

 

Conclusion

이정도면 UCI-HAR (Human Activity Recognition) 데이터셋으로 정말 뽕 잘 뽑았다고 할 수 있지 않을까.

양이 많이 언제 다 정리해 생각도 들었지만, 해냈다..!

 

 

 

댓글