본문 바로가기

파이썬 머신러닝 완벽가이드

4.2 결정 트리 실습 - 사용자 행동 인식 데이터 세트

728x90

'사용자 행동 인식 데이터셋'을 통해 

결정 트리 실습을 진행해보도록 하겠습니다.

 

해당 내용은 '파이썬 머신러닝 완벽 가이드'를 정리한 내용입니다.


먼저 데이터 전처리를 해주도록 하겠습니다. 데이터 전처리는 머신러닝에서 매우 중요한 부분이지만 지금은 알고리즘을 학습시키는 방법에 집중하기로 하고 간단하게 보고만 넘어가도록 하겠습니다.

아래 코드는 pandas에서는 중복된 피처를 처리를 못하기 때문에 중복된 피처에 _1, _2와 같이 구분자를 추가하여 피처를 처리하는 과정입니다.

import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

### features.txt 파일에 있는 컬럼명을 입력 받아서 중복된 컬럼명은 원본 컬럼명+_1, _2와 같이 중복된 차수를 원본 컬럼명에 더해서 컬럼명을 update 하는 함수임. . 
def get_new_feature_name_df(old_feature_name_df):
    #column_name으로 중복된 컬럼명에 대해서는 중복 차수 부여, col1, col1과 같이 2개의 중복 컬럼이 있을 경우 1, 2 
    feature_dup_df = pd.DataFrame(data=old_feature_name_df.groupby('column_name').cumcount(), columns=['dup_cnt'])
    # feature_dup_df의 index인 column_name을 reset_index()를 이용하여 컬럼으로 변환. 
    feature_dup_df = feature_dup_df.reset_index()
    # 인자로 받은 features_txt의 컬럼명 DataFrame과 feature_dup_df를 조인. 
    new_feature_name_df = pd.merge(old_feature_name_df.reset_index(), feature_dup_df, how='outer')
    # 새로운 컬럼명은 앞에 중복 차수를 접미어로 결합. 
    new_feature_name_df['column_name'] = new_feature_name_df[['column_name', 'dup_cnt']].apply(lambda x : x[0]+'_'+str(x[1]) 
                                                                                           if x[1] >0 else x[0] ,  axis=1)
    new_feature_name_df = new_feature_name_df.drop(['index'], axis=1)
    return new_feature_name_df

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'])
    
    # 중복된 feature명을 새롭게 수정하는 get_new_feature_name_df()를 이용하여 새로운 feature명 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()

 

레이블 값을 보면 비교적 균일하게 분포하고 있음을 알 수 있습니다. 

print(y_train['action'].value_counts())

 

6    1407
5    1374
4    1286
1    1226
2    1073
3     986
Name: action, dtype: int64

 

우선 기본적인 파라미터를 이용하여 결정트리를 학습해보겠습니다.

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


dt_clf = DecisionTreeClassifier(random_state=156)
dt_clf.fit(X_train , y_train)
pred = dt_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred)
print('결정 트리 예측 정확도: {0:.4f}'.format(accuracy))

 

결정 트리 예측 정확도: 0.8548

 

85%로 비교적 나쁘지 않은 결과이지만 GridSearchCV를 이용하여 파라미터를 수정하여 성능을 더 향상해보겠습니다.

from sklearn.model_selection import GridSearchCV

params = {
    'max_depth' : [ 6, 8 ,10, 12, 16 ,20, 24]
}

grid_cv = GridSearchCV(dt_clf, param_grid=params, scoring='accuracy', cv=5, verbose=1 )
grid_cv.fit(X_train , y_train)
print('GridSearchCV 최고 평균 정확도 수치:{0:.4f}'.format(grid_cv.best_score_))
print('GridSearchCV 최적 하이퍼 파라미터:', grid_cv.best_params_)

 

Fitting 5 folds for each of 7 candidates, totalling 35 fits
GridSearchCV 최고 평균 정확도 수치:0.8513
GridSearchCV 최적 하이퍼 파라미터: {'max_depth': 16}

 

best_df_clf = grid_cv.best_estimator_

pred1 = best_df_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred1)
print('결정 트리 예측 정확도:{0:.4f}'.format(accuracy))

 

결정 트리 예측 정확도:0.8575

 

파라미터를 하나 수정해주었더니 성능이 소폭 상승된 것을 볼 수 있습니다.

그럼 이제 두 개의 파라미터를 수정하여 성능을 조금 더 향상해보도록 하겠습니다.

 

params = {
    'max_depth' : [ 8 , 12, 16 ,20], 
    'min_samples_split' : [16,24],
}

grid_cv = GridSearchCV(dt_clf, param_grid=params, scoring='accuracy', cv=5, verbose=1 )
grid_cv.fit(X_train , y_train)
print('GridSearchCV 최고 평균 정확도 수치: {0:.4f}'.format(grid_cv.best_score_))
print('GridSearchCV 최적 하이퍼 파라미터:', grid_cv.best_params_)

 

Fitting 5 folds for each of 8 candidates, totalling 40 fits
GridSearchCV 최고 평균 정확도 수치: 0.8549
GridSearchCV 최적 하이퍼 파라미터: {'max_depth': 8, 'min_samples_split': 16}

 

best_df_clf = grid_cv.best_estimator_

pred2 = best_df_clf.predict(X_test)
accuracy = accuracy_score(y_test , pred2)
print('결정 트리 예측 정확도:{0:.4f}'.format(accuracy))

 

결정 트리 예측 정확도:0.8717

87%로 무려 2%나 더욱 향상되었음을 볼 수 있습니다. 역시 결정 트리에서 어떤 파라미터를 사용하냐가 정말 중요한 것 같습니다!! 

진짜 신기하네요....ㅎㅎ

 

마지막으로 결정트리에 영향을 미치는 피쳐들에 대해서 확인하고 마무리하도록 하겠습니다.

import seaborn as sns

ftr_importances_values = best_df_clf.feature_importances_

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

# 중요도값 순으로 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()


이렇게 결정 트리에 대한 실습까지 모두 끝나게 되었습니다.

아직은 처음 공부하는 것이다 보니 전처리 코드, 그래프 등 이해하기가 버겁지만

분류에 대한 전체적인 흐름을 파악하는데 목적을 두고 넘어가도록 하겠습니다.

다음 시간부터는 이제 이 결정 트리를 기반으로 앙상블 기법을 적용해보도록 하겠습니다!!

다음 시간에 만나요~안뇽~~

반응형