UCI에서 제공하는 사용자 행동 인식 데이터를 사용해서 결정 트리 알고리즘 실습을 해보겠습니다. 이 데이터는 사람들에게 스마트폰 센서를 장착시킨 후에 사람의 동작과 관련된 여러 가지 피처를 수집한 데이터입니다.
In
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
# feature.txt 파일은 index와 피처명이 공백으로 분리되어 있어 다음과 같이 sep으로 할당시켜 불러와 줘야 함.
feature_name_df = pd.read_csv('./human_activity/features.txt', sep='\s+',
header=None, names = ['column_index', 'column_name'])
feature_name_df.head()
Out
In
# 피처명 index를 제거한 후에 피처명만 리스트 객체로 생성한 뒤 샘플로 10개만 추출 함.
feature_name = feature_name_df.iloc[:, 1].values.tolist()
feature_name[:10]
Out
데이터의 일부 전처리 방법은 생략하도록 하겠습니다.
In
import pandas as pd
def human_dataset():
# 공백 데이터를 분리하게 위해 공백 문자를 sep로 할당시켜 줌.
feature_name_df = pd.read_csv('./human_activity/features.txt',sep='\s+', header=None, names=['column_index',
'column_name'])
# 피처명을 칼럼으로 부여해 주기 위해서 리스트 객체로 다시 변환하여 준다.
feature_name = 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+',names=['action'])
y_test= pd.read_csv('./human_activity/test/y_test.txt',sep='\s+',names=['action'])
# 학습&테스트용 DataFrame을 모두 반환 시킴.
return X_train, X_test, y_train, y_test
X_train, X_test, y_train, y_test = human_dataset()
-
데이터의 형태를 살펴보겠습니다.
In
print(X_train.info())
Out
학습 데이터 세트는 7352개의 레코드로 561개의 피처를 가지고 있습니다.
In
print(y_train['action'].value_counts())
Out
레이블 값의 비율은 비교적 고르게 분포되어 있음을 확인하였습니다.
-
이제 사이킷런에서 제공하는 DecisionTreeClassifier을 사용해서 예측 분류를 해보겠습니다. 하이퍼 파리미터는 우선 디폴트 값으로 설정해 주겠습니다.
In
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
# 예제 반복을 할때 동일한 예측 결과를 위해서 random_state를 설정해 준다.
dt_clf = DecisionTreeClassifier(random_state=156)
dt_clf.fit(X_train, y_train)
dt_pred=dt_clf.predict(X_test)
accuarcy=accuracy_score(y_test, dt_pred)
print('예측 정확도:{0:.4f}'.format(accuarcy))
Out
예측 정확도가 약 85.48%로 나왔습니다.
-
이때의 하이퍼파라미터 값들을 추출해 보도록 하겠습니다.
In
print('기본 하이퍼 파라미터:\n', dt_clf.get_params())
Out
기본 파라미터들은 다음과 같습니다.
-
이번에는 트리 깊이(Tree depth)을 조절해서 예측 정확도에 어떤 영향을 미치는지 알아보도록 하겠습니다.
-
결정 트리는 리프 노드가 될 수 있는 적합한 수준이 될 때까지 지속해서 트리의 분할을 수행하면서 깊이가 깊어지게 됩니다.
-
max_depth값을 6, 8, 10, 12, 16, 20, 24로 계속 늘리면서 예측 성능을 측정해 보겠습니다.교차 검증은 5개 세트입니다
In
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('최고 평균 정확도:{0:.4f}'.format(grid_cv.best_score_))
print('최적 하이퍼 파라미터:',grid_cv.best_params_)
Out
max_depth가 8일 때 5개의 폴드 세트의 최고 평균 정확도가 약 85.26%로 나왔습니다.
-
5개의 CV 세트에서 max_depth값에 따라 어떻게 예측 성능이 변했는지 확인해보겠습니다
In
# GridSearchCV 객체의 cv_result_ 속성을 사용
cv_results_df = pd.DataFrame(grid_cv.cv_results_)
# param_max_depth, maan_test_score 추출
cv_results_df[['param_max_depth','mean_test_score']]
Out
mean_test_score은 5개 CV 세트에서 검증용 데이터 세트의 정확도 평균 수치를 의미합니다.
mean_test_score는 max_depth가 8일때 0.852로 정확도가 정점입니다. 이를 넘어가게 되면 정확도가 계속 떨어지게 됩니다.
-
다음은 별도의 데이터 세트에서 결정 트리의 정확도를 측정해 보도록 하겠습니다.
In
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
max_depth = [6, 8, 10, 12, 16, 20, 24]
# max_depth 값을 변화시키면서 학습과 테스트 세트에서의 예측 성능을 측정한다.
for depth in max_depth :
dt_clf = DecisionTreeClassifier(max_depth = depth, random_state = 156)
dt_clf.fit(X_train, y_train)
pred = dt_clf.predict(X_test)
accuracy = accuracy_score(y_test, pred)
print('max_depth = {0} 정확도 : {1:.4f}'.format(depth, accuracy))
Out
결과를 보면 max_depth가 8일때 약 87.07으로 가장 높은 정확도를 나타내고 있습니다. 그리고 max_depth가 8을 넘어가는 순간 정확도가 계속 감소하는 것을 알 수 있습니다.
앞의 예제와 마찬가지로 깊이가 깊어질수록 테스트 데이터 세트의 정확도는 떨어지게 됩니다.
결정 트리는 깊이가 깊어질수록 과적합의 위험성이 있기 때문에 하이퍼 파라미터를 이용해서 깊이를 제어하는 것이 중요합니다.
-
이번에는 max_depth와 min_samples_split를 같이 변경하면서 정확도 성능을 확인해 보겠습니다.
In
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_)
Out
max_depth가 8, min_samples_split이 16일때 가장 최고의 정확도로 약 85.5%를 나타냅니다.
-
이제 테스트 데이터 세트에 해당 하이퍼 파라미터를 적용해 보도록 하겠습니다.
In
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))
Out
max_depth가 8, min_samples_split이 16일때 테스트 데이터 세트의 예측 정확도는 약 87.17%로 확인되었습니다.
-
이제 결정 트리에서 각 피저의 중요도를 feature_importances_ 속성을 이용해서 알아보도록 하겠습니다.
In
# 중요도가 높은 순으로 Top 20 피처를 막대그래프로 표현한다.
import seaborn as sns
ftr_importances_values = best_df_clf.feature_importances_
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()
Out
그래프에서 가장 높은 중요도를 가진 TOP5의 피처들이 규칙을 생성하는데 매우 중요한 영향을 미치는 것을 알 수 있습니다.
-
결정 트리 시각화
In
feature_names = X_train.columns.tolist()
target_name = X_test.columns.tolist()
시각화에 필요한 파라미터를 위해 피처명과 레이블 명을 따로 저장하여 줍니다.
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
from sklearn.tree import export_graphviz
dt_dot_data = tree.export_graphviz(dt_clf, out_file = 'tree1',
feature_names = feature_names,
class_names = target_name,
filled = True, rounded = True,
special_characters = True)
import graphviz
with open('tree1') as f:
dot_graph=f.read()
graphviz.Source(dot_graph)
Out
다음과 같이 출력이 됩니다.
그럼 결정 트리 실습 포스팅을 마치도록 하겠습니다. 감사합니다. 화이팅!
Reference
'Machine Learning' 카테고리의 다른 글
랜덤 포레스트(Random forest) (0) | 2020.04.26 |
---|---|
앙!상블 (0) | 2020.04.21 |
결정 트리(Decision Tree) (0) | 2020.04.16 |
사이킷런으로 시작하는 머신러닝 - 데이터 전처리(피처 스케일링)- (0) | 2020.04.10 |
사이킷런으로 시작하는 머신러닝 - 데이터 전처리(데이터 인코딩)- (0) | 2020.04.10 |