컴퓨터 알고리즘에서 즐겨 사용하는 트리 구조를 사용하고, 각 노드에는 분석 대상의 속성들이 위치한다.
각 분기점마다 목표 값을 가장 잘 분류할 수 있는 속성을 찾아서 배치하고, 해당 속성이 갖는 값을 이용하여 새로운
가지를 만든다.
각 분기점에서 최적의 속성을 선택할 때는 해당 속성을 기준으로 분류한 값들이 구분되는 정도를 측정한다.
주로 엔트로피를 이용하는데, 엔트로피가 낮을수록 분류갸 잘 된 것이다.
데이터 준비
암세포 진단 데이터셋을 사용하자. URL을 입력하면 데이터를 다운로드 받을 수 있다.
import pandas as pd
import numpy as np
uci_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data'
df = pd.read_csv(uci_path, header=None)
df.columns = ['id', 'clump', 'cell_size','cell_shape','adhesion','epithlial','bare_nuclei','chromatin','normal_nucleoli','mitoses','class']
pd.set_option('display.max_columns', 15)
print(df.head())
print('\n')
print(df.info())
print('\n')
print(df.describe())
id clump cell_size cell_shape adhesion epithlial bare_nuclei \
0 1000025 5 1 1 1 2 1
1 1002945 5 4 4 5 7 10
2 1015425 3 1 1 1 2 2
3 1016277 6 8 8 1 3 4
4 1017023 4 1 1 3 2 1
chromatin normal_nucleoli mitoses class
0 3 1 1 2
1 3 2 1 2
2 3 1 1 2
3 3 7 1 2
4 3 1 1 2
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 699 entries, 0 to 698
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 id 699 non-null int64
1 clump 699 non-null int64
2 cell_size 699 non-null int64
3 cell_shape 699 non-null int64
4 adhesion 699 non-null int64
5 epithlial 699 non-null int64
6 bare_nuclei 699 non-null object
7 chromatin 699 non-null int64
8 normal_nucleoli 699 non-null int64
9 mitoses 699 non-null int64
10 class 699 non-null int64
dtypes: int64(10), object(1)
memory usage: 60.2+ KB
None
id clump cell_size cell_shape adhesion \
count 6.990000e+02 699.000000 699.000000 699.000000 699.000000
mean 1.071704e+06 4.417740 3.134478 3.207439 2.806867
std 6.170957e+05 2.815741 3.051459 2.971913 2.855379
min 6.163400e+04 1.000000 1.000000 1.000000 1.000000
25% 8.706885e+05 2.000000 1.000000 1.000000 1.000000
50% 1.171710e+06 4.000000 1.000000 1.000000 1.000000
75% 1.238298e+06 6.000000 5.000000 5.000000 4.000000
max 1.345435e+07 10.000000 10.000000 10.000000 10.000000
epithlial chromatin normal_nucleoli mitoses class
count 699.000000 699.000000 699.000000 699.000000 699.000000
mean 3.216023 3.437768 2.866953 1.589413 2.689557
std 2.214300 2.438364 3.053634 1.715078 0.951273
min 1.000000 1.000000 1.000000 1.000000 2.000000
25% 2.000000 2.000000 1.000000 1.000000 2.000000
50% 2.000000 3.000000 1.000000 1.000000 2.000000
75% 4.000000 5.000000 4.000000 1.000000 4.000000
max 10.000000 10.000000 10.000000 10.000000 4.000000
결측값을 처리하고, 결측값이 들어있는 행을 삭제한다. 그리고 bare_nuclei 열을 정수형으로 변환한다.
print(df['bare_nuclei'].unique())
print('\n')
df['bare_nuclei'].replace('?', np.nan, inplace=True)
df.dropna(subset=['bare_nuclei'], axis=0, inplace=True)
df['bare_nuclei'] = df['bare_nuclei'].astype('int')
print(df.describe())
['1' '10' '2' '4' '3' '9' '7' '?' '5' '8' '6']
id clump cell_size cell_shape adhesion \
count 6.830000e+02 683.000000 683.000000 683.000000 683.000000
mean 1.076720e+06 4.442167 3.150805 3.215227 2.830161
std 6.206440e+05 2.820761 3.065145 2.988581 2.864562
min 6.337500e+04 1.000000 1.000000 1.000000 1.000000
25% 8.776170e+05 2.000000 1.000000 1.000000 1.000000
50% 1.171795e+06 4.000000 1.000000 1.000000 1.000000
75% 1.238705e+06 6.000000 5.000000 5.000000 4.000000
max 1.345435e+07 10.000000 10.000000 10.000000 10.000000
epithlial bare_nuclei chromatin normal_nucleoli mitoses \
count 683.000000 683.000000 683.000000 683.000000 683.000000
mean 3.234261 3.544656 3.445095 2.869693 1.603221
std 2.223085 3.643857 2.449697 3.052666 1.732674
min 1.000000 1.000000 1.000000 1.000000 1.000000
25% 2.000000 1.000000 2.000000 1.000000 1.000000
50% 2.000000 1.000000 3.000000 1.000000 1.000000
75% 4.000000 6.000000 5.000000 4.000000 1.000000
max 10.000000 10.000000 10.000000 10.000000 10.000000
class
count 683.000000
mean 2.699854
std 0.954592
min 2.000000
25% 2.000000
50% 2.000000
75% 4.000000
max 4.000000
그리고 설명 변수 x로 사용할 열들을 선택하고, 예측 변수 y로 사용할 열을 선택한다.
그리고, 정규화 실행 후에 훈련 데이터와 검증 데이터를 나눈다.
x = df[['clump', 'cell_size', 'cell_shape', 'adhesion', 'epithlial', 'bare_nuclei', chromatin',
'normal_nucleoli', 'mitoses']]
y = df['class']
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(x)
x = ss.transform(x)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=10)
print(x_train.shape)
print(x_test.shape)
(478, 9)
(205, 9)
모형 학습 및 검증
sklearn 라이브러리의 tree 모듈을 임포트한다. DecisionTreeClassifier() 함수를 사용하여 모형 객체를 생성하고
각 분기점에서 최적의 속성을 찾기 위해 분류 정도를 평가하는 기준으로 'entropy' 값을 사용한다.
트리 레벨을 5로 지정하는데, 5단계까지 가지를 확장할 수 있음을 의미한다.
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(criterion='entropy', max_depth=5)
dt.fit(x_train, y_train)
y_hat = dt.predict(x_test)
print(y_hat[0:10])
print(y_test.values[0:10])
[4 4 4 4 4 4 2 2 4 4]
[4 4 4 4 4 4 2 2 4 4]
모형을 통해 예측한 값 y_hat와 실제 값 y_test를 비교하면 다음과 같다.
이 의사결정 나무의 모형 평가 지표를 출력해보자.
from sklearn import metrics
tree_matrix = metrics.confusion_matrix(y_test, y_hat)
print(tree_matrix)
print('\n')
tree_report = metrics.classification_report(y_test, y_hat)
print(tree_report)
[[127 4]
[ 2 72]]
precision recall f1-score support
2 0.98 0.97 0.98 131
4 0.95 0.97 0.96 74
accuracy 0.97 205
macro avg 0.97 0.97 0.97 205
weighted avg 0.97 0.97 0.97 205
양성을 정확히 예측한 TP는 127개, 양성을 악성으로 잘못 분류한 FP는 4개
약성을 양성으로 잘못 분류한 FN은 2개, 악성을 정확히 예측한 TN은 72개이다.
이를 그림으로 나타내는 매서드는 plot_tree 이다
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(10, 7))
plot_tree(dt)
plt.show()
'Study > 혼자 공부하는 판다스' 카테고리의 다른 글
혼자 공부하는 판다스 - 머신러닝 (KNN, SVM) (0) | 2022.04.29 |
---|---|
혼자 공부하는 판다스 - 머신러닝 데이터 분석 (머신러닝 개요, 회귀분석) (0) | 2022.04.29 |
혼자 공부하는 판다스 - 데이터프레임의 다양한 응용(함수 매핑, 열 재구성) (0) | 2022.04.26 |
혼자 공부하는 판다스 - 데이터 사전처리(정규화, 시계열 데이터) (0) | 2022.04.22 |
혼자 공부하는 판다스 - 데이터 사전 처리(데이터 표준화, 범주형 데이터 처리) (0) | 2022.04.22 |