PL/Python

피쳐 중요도 feature_importances_

PIYA 2022. 10. 18.

포스팅 목적

결정트리 Decision Tree Classifier와

결정트리를 기반으로 앙상블 학습하는 Random Forest에서 확인할 수 있는

피쳐 중요도에 대해 정리해보는 시간.

 

다른 학습기들에서도 똑같이 사용할 수 있는지는 아직 모르겠다.

feature_importances_ 프로퍼티에 대해 간단히 알아보자.

 

 

피쳐 중요도

 

이 프로퍼티 feature_importances_는 결정트리에서 노드를 분기할때,

해당 피쳐가 클래스를 나누는데 얼마나 영향을 미쳤는지를 표기하는 척도이다.

 

노말라이즈된 ndarray를 반환하기 때문에 0~1값을 가진다.

0이면 클래스를 구분하는데 해당 피쳐가 선택되지 않았다는것,

1이면 해당 피쳐가 클래스를 완벽하게 나누었다는것을 의미한다

 

 

실습1: iris basic

우선 iris 데이터셋에 아래와같이 간단한 결정트리를 만들어보자.

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import numpy as np

# 내가 사랑하는 붓꽃 데이터셋 로드
iris = load_iris()

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

# 성능을 시험할 것은 아니니까 모든 데이터셋을 학습시킨다
dt.fit(iris.data, iris.target)

# feature importance 추출
print('피쳐 목록:\n\t{0}'.format(iris.feature_names))
print("피쳐 중요도:\n\t{0}".format(np.round(dt.feature_importances_, 2)))

 

피쳐는 sepal length, sepal width, petal length, petal width 네 가지가 있는데

붓꽃 클래스를 결정트리로 분류하는데에는 petal length와 width값이 중요하게 작용하는것으로 보인다.

 

이 세번째, 네번째 피쳐의 중요도를 합치면 거의 1에 수렴하므로,

앞의 두 피쳐는 클래스를 구분하는 데 미치는 영향이 미미하다는 뜻이 된다.

 

 

sepal length와 width를 x축과 y축으로 산점도를 그려보면 아래와 같다.

두개의 피쳐만으로도 클래스가 충분히 잘 구분된다는 것을 확인할 수 있다.

import matplotlib.pyplot as plt
plt.scatter(iris.data[:,2], iris.data[:,3],
            c=iris.target, s=25, cmap='rainbow', edgecolor='k')

sepal length, width 두가지로만 그린 산점도

 

 

 

실습2: many features

이번엔 한 발 나아가, 위스콘신 유방암 데이터셋에 랜덤 포레스트를 적용하는 경우를 실습해보자.

유방암 데이터셋은 피쳐가 많아 한눈에 보기 어렵다.

이런 경우 처리하는 로직을 간단하게 정리해두려 한다.

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score
import pandas as pd

# 위스콘신 유방암 데이터 로드, train_test_split으로 데이터 나누기
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size=0.2)

# 기본설정 랜덤포레스트
rf = RandomForestClassifier(n_jobs=-1) # 모든 코어 사용

# 피쳐중요도만 확인할 것이기 때문에 fit만 한다.
rf.fit(X_train, y_train)

# 그냥 확인하기에 피쳐종류가 30개나 되어 한눈에 들어오지 않는다.
print(rf.feature_importances_, '\n')

# 시리즈로 만들어 인덱스를 붙인다
ser = pd.Series(rf.feature_importances_, index=cancer.feature_names)

# 내림차순 정렬을 이용한다
top15 = ser.sort_values(ascending=False)[:15]
print(top15)

위와 같이 피쳐들이 30개나 되는 경우, 육안으로 어떤 피쳐가 중요한 지 확인하기 어렵다.

Series를 만들어 sort_values()를 이용해 중요도 순으로 상위 피쳐들만 뽑는 코드를 작성했다.

 

 

아래는 이를 barplot으로 시각화한 코드를 작성했다.

barplot에다가 시리즈만 x와 y에 넣어주면 간단하게 막대그리프를 그릴 수 있다.

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(8,6))
plt.title('Feature Importances Top 15')
sns.barplot(x=top15, y=top15.index)
plt.show()

피쳐 중요도 top 15

 

 

Conclusion

feature_importances_에 대해 알아보았다.

 

실습1: iris basic

iris 데이터셋의 petal 값만으로 그래프를 그렸는데, 꽤 잘 클래스가 구분되는것을 관찰할 수 있었다!

해당 피쳐의 중요도값이 1에 가까우면, 그만큼 클래스 구분이 잘 된다는 것을 알 수 있었다.

 

실습2: many features

위스콘신 유방암 데이터세트를 이용하여 랜덤포레스트 코드를 작성했다.

피쳐가 30개나 되어 한눈에 확인하기 어려웠다.

판다스 시리즈를 이용하여 sort_values()메소드로 내림차순 정렬하였고,

seaborn barplot 그래프를 써서 시각화하였다.

'PL > Python' 카테고리의 다른 글

Pandas merge함수 사용법 기초  (0) 2022.10.26
numpy.r_ 연산자 사용법  (0) 2022.10.21
[seaborn] barplot 기초  (0) 2022.10.18
데이터분석: 카디널리티 (Cardinality)  (0) 2022.10.18
graphviz 설치 및 기본 사용법 개요  (1) 2022.10.18

댓글