[Python] 등고선 그래프 (contour plot)로 모델의 의사결정 경계(Decision Boundary) 시각화하기
Python 분석과 프로그래밍/Python 그래프_시각화 2020. 8. 2. 23:20이번 포스팅에서는 numpy의 meshgrid()와 matplotlib의 contourf(xx, yy, Z) 함수를 사용하여 Random Forest Classifer 의 의사결정 경계(Decision Boundary)를 시각화해보겠습니다.
(1) iris dataset 의 species 를 분류할 수 있는 Random Forest 분류 모델 훈련
(2) numpy의 meshgrid() 로 설명변수 공간의 좌표들을 생성하여 Random Forest 분류 모델로 예측
(3) matplotlib의 contourf() 함수로 Random Forest Classifier 예측 결과 시각화(채우기)
: 의사결정 경계(Decision Boundary)
(4) iris dataset 의 species 의 산점도를 겹쳐서 그리기
의 순서로 진행해보겠습니다.
(1) iris dataset 의 species 를 분류할 수 있는 Random Forest 분류 모델 훈련 |
먼저 iris dataset 을 업로드하고 어떻게 생긴 데이터인지 살펴보겠습니다.
#%% import libraries import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns #%% iris dataset iris = sns.load_dataset('iris') iris.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 150 entries, 0 to 149 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 sepal_length 150 non-null float64 1 sepal_width 150 non-null float64 2 petal_length 150 non-null float64 3 petal_width 150 non-null float64 4 species 150 non-null object dtypes: float64(4), object(1) memory usage: 6.0+ KB iris.groupby('species').size() Out[1]: species setosa 50 versicolor 50 virginica 50 dtype: int64 #%% scatter plot by 'species' sns.scatterplot(x='petal_length', y='petal_width', hue='species', style='species', s=100, data=iris) plt.show() |
이번 포스팅의 시각화 예에서는 'sepal_length', 'sepal_width' 의 두개 칼럼을 설명변수로 사용하고, 'species'를 목표변수로 하여 붓꽂 종류(species)를 Random Forest Classifier 로 분류하는 모델을 만들어보겠습니다.
(* 이번 포스팅의 주 목적은 모델의 의사결정경계 시각화이므로, 모델링 단계에서의 train/test set 분할, 모델 성과 평가 등은 생략합니다.)
#%% Classification using Random Forest from sklearn.ensemble import RandomForestClassifier X = np.array(iris[['petal_length', 'petal_width']]) y = iris['species'] y = np.where(y=='setosa', 0, np.where(y=='versicolor', 1, 2)) rfc = RandomForestClassifier(max_depth=2, n_estimators=200, random_state=1004) rfc.fit(X, y) |
(2) numpy의 meshgrid() 로 설명변수 공간의 좌표들을 생성하여 Random Forest 분류 모델로 예측 |
위의 (1)번에서 적합된 Random Forest Classifier 모델을 사용해서 붓꽂 종류를 예측하고자 할때는 predict() 라는 메소드를 사용하면 됩니다.
#%% predict pred = rfc.predict(X) print(pred == y) [ True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True True False True True True True True True False True True True True True False True True True True True True True True True True True True True True True True True True True True True True False True True True True True True True True True True True True False True True True True True True True True True True True True True False False True True True True True True True True True True True True True True True]
|
(a) 이제 x 축('petal_length')과 y 축('petal_width')의 최소값, 최대값을 구하고, (b) 이들 x축과 y축의 최소값 ~ 최대값 사이의 구간을 h = 0.01 단위의 간격으로 좌표를 생성하여, (c) np.meshgrid()로 이들 x축과 y축의 h=0.01 단위의 좌표 벡터를 가지고 격자 행렬을 생성합니다.
(d) 이렇게 생성한 격자 행렬 좌표값들에 대해 Random Forest Classifier 훈련된 모델의 predict() 메소드로 예측을 하여 contour plot의 높이에 해당하는 Z 값을 구합니다.
# create coordinate matrices from x_min~x_max, y_min~y_max coordinates h = 0.01 x_min, x_max = X[:, 0].min() - .1, X[:, 0].max() + .1 y_min, y_max = X[:, 1].min() - .1, X[:, 1].max() + .1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) XY = np.c_[xx.ravel(), yy.ravel()] XY.shape Out[4]: (158600, 2) # predict pred_cls = rfc.predict(XY) # align the shape of Z with xx Z = pred_cls.reshape(xx.shape)
|
(3) matplotlib.contourf() 로 Random Forest Classifier 예측 결과 시각화 --> (4) iris dataset 의 species 의 산점도를 겹쳐서 그리기 |
위의 (2)번에서 만들어놓은 x, y 격자 행렬 좌표값별로 Random Forest Classifier 예측 결과를 matplotlib의 confourf() 함수로 시각화 (채우기)를 하면 아래와 같습니다. 아래에 색깔로 구분된 영역들과 경계선이 바로 Random Forest Classifier가 훈련 데이터로 부터 학습한 species 분류 의사결정 경계(Decision Boundary)가 되겠습니다.
# Random Forest Classifier: Decision Boundary plt.contourf(xx, yy, Z) plt.axis('off') |
좀더 보기에 쉽도록 위의 의사결정경계 그래프 위에다가 학습에 사용했던 iris species 값들을 species별로 marker를 구분하여 겹쳐서 다시 한번 시각화해보겠습니다.
plt.contourf(xx, yy, Z) plt.axis('off') sns.scatterplot(x='petal_length', y='petal_width', hue='species', style='species', s=100, data=iris) plt.title('Decision Boundary by Random Forest', fontsize=14) plt.show()
|
iris species 별 산점도를 의사결정경계 배경 위에 겹쳐 그릴 때 seaborn.scatterplot() 대신에 아래의 코드처럼 matplotlib.scatter() 과 for loop을 사용해서 그릴 수도 있습니다.
plt.contourf(xx, yy, Z) plt.axis('off') # or plot data points using matplotlib and for loop N = 50 CLS_NUM = 3 markers = ['o', 'x', 's'] for i in range(CLS_NUM): plt.scatter(X[i*N: (i+1)*N, 0], X[i*N:(i+1)*N, 1], s=40, marker=markers[i]) plt.title('Decision Boundary by Random Forest', fontsize=14) plt.show() |
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. :-)