빅데이터 서비스 교육/머신러닝

머신러닝 Decision Tree

Manly 2022. 6. 24. 11:43
반응형

import pandas as pd
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier

 

목표

  • 버섯의 특징을 활용해 독/식용 버섯을 분류
  • Decision tree 시각화 & 과대적합 제어
  • 특성선택(Feature selection) 해보기

data = pd.read_csv('./data/mushroom.csv')
data

 

poisonous	cap-shape	cap-surface	cap-color	bruises	odor	gill-attachment	gill-spacing	gill-size	gill-color	...	stalk-surface-below-ring	stalk-color-above-ring	stalk-color-below-ring	veil-type	veil-color	ring-number	ring-type	spore-print-color	population	habitat
0	p	x	s	n	t	p	f	c	n	k	...	s	w	w	p	w	o	p	k	s	u
1	e	x	s	y	t	a	f	c	b	k	...	s	w	w	p	w	o	p	n	n	g
2	e	b	s	w	t	l	f	c	b	n	...	s	w	w	p	w	o	p	n	n	m
3	p	x	y	w	t	p	f	c	n	n	...	s	w	w	p	w	o	p	k	s	u
4	e	x	s	g	f	n	f	w	b	k	...	s	w	w	p	w	o	e	n	a	g
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
8119	e	k	s	n	f	n	a	c	b	y	...	s	o	o	p	o	o	p	b	c	l
8120	e	x	s	n	f	n	a	c	b	y	...	s	o	o	p	n	o	p	b	v	l
8121	e	f	s	n	f	n	a	c	b	n	...	s	o	o	p	o	o	p	b	c	l
8122	p	k	y	n	f	y	f	c	n	b	...	k	w	w	p	w	o	e	w	v	l
8123	e	x	s	n	f	n	a	c	b	y	...	s	o	o	p	o	o	p	o	c	l
8124 rows × 23 columns

X = data.iloc[:,1:]            # 문제
y = data.iloc[:,0]   # y = data['poisonous']    정답

 

y.value_counts()

e    4208
p    3916
Name: poisonous, dtype: int64

 

# cap shape가 x인 cap color 행의 수는?
X[X['cap-shape']=='x']['cap-color'].value_counts()                 # cap-color로 굳이 한번 더 인덱싱 안해도 같은 숫자

 

n    920
g    920
e    596
y    528
w    512
p     84
b     64
c     16
r      8
u      8
Name: cap-color, dtype: int64

# cap-surface가 f와 같고 gill-size가 b인 cap-shape컬럼값을 value_counts() 해보자
X[(X['cap-surface']=='f')&(X['gill-size']=='b')]['cap-shape'].value_counts()

x    996
f    948
b     48
k     48
Name: cap-shape, dtype: int64

                Object형을 숫자형으로 바꿔줘야 할때 -> 인코딩

                        S -> 0 / C->1 / Q-> 2로 표현

표현하고 싶은 컬럼을 1로 나머지는 0으로 변경

One-hot 인코딩을 할 수록 특징이 늘어나고 -> 많아지면 과대적합이 된다.

 

원 핫 인코딩

X_one_hot = pd.get_dummies(X)   #문제 X변수 원 핫 인코딩
# 각 컬럼별로 전부 원핫 인코딩

	cap-shape_b	cap-shape_c	cap-shape_f	cap-shape_k	cap-shape_s	cap-shape_x	cap-surface_f	cap-surface_g	cap-surface_s	cap-surface_y	...	population_s	population_v	population_y	habitat_d	habitat_g	habitat_l	habitat_m	habitat_p	habitat_u	habitat_w
0	0	0	0	0	0	1	0	0	1	0	...	1	0	0	0	0	0	0	0	1	0
1	0	0	0	0	0	1	0	0	1	0	...	0	0	0	0	1	0	0	0	0	0
2	1	0	0	0	0	0	0	0	1	0	...	0	0	0	0	0	0	1	0	0	0
3	0	0	0	0	0	1	0	0	0	1	...	1	0	0	0	0	0	0	0	1	0
4	0	0	0	0	0	1	0	0	1	0	...	0	0	0	0	1	0	0	0	0	0
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
8119	0	0	0	1	0	0	0	0	1	0	...	0	0	0	0	0	1	0	0	0	0
8120	0	0	0	0	0	1	0	0	1	0	...	0	1	0	0	0	1	0	0	0	0
8121	0	0	1	0	0	0	0	0	1	0	...	0	0	0	0	0	1	0	0	0	0
8122	0	0	0	1	0	0	0	0	0	1	...	0	1	0	0	0	1	0	0	0	0
8123	0	0	0	0	0	1	0	0	1	0	...	0	0	0	0	0	1	0	0	0	0
8124 rows × 117 columns

라벨인코딩

X['habitat'].unique()

array(['u', 'g', 'm', 'd', 'p', 'w', 'l'], dtype=object)

dic = {
     'u': 2,
     'g': 1,
     'm': 3,
     'd': 5, 
     'p': 4, 
     'w': 6, 
     'l': 7
}

 

X['habitat'].map(dic)

0       2
1       1
2       3
3       2
4       1
       ..
8119    7
8120    7
8121    7
8122    7
8123    7
Name: habitat, Length: 8124, dtype: int64

X_train,X_test,y_train,y_test = train_test_split(X_one_hot,y,test_size=0.3,random_state=1)

 

print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)

(5686, 117)
(2438, 117)
(5686,)
(2438,)

t_model = DecisionTreeClassifier()

t_model.fit(X_train,y_train)

DecisionTreeClassifier()

t_model.score(X_test,y_test)

1.0

!pip install graphviz            # 시각화 할때 쓰는 라이브러리

 

from sklearn.tree import export_graphviz

# class_names -> 정답 이름, feature_names -> 문제이름  (컬럼명들을 넣는다),
# filled -> 색깔,impurity -> 불순도값 표시 여부
export_graphviz(t_model, out_file = 'tree.dot',class_names = ['독', '식용'], 
                feature_names= X_one_hot.columns, filled=True, impurity=False )

 

# graphviz형태로 tree.dot으로 파일을 내보냈는데 이를 가져와서 시각화 한다
import graphviz

with open('./tree.dot', encoding='UTF-8') as f:
    dot_graph = f.read()

# graphviz.Source(소스값)
display(graphviz.Source(dot_graph))

 

#이때 pip install로 경로를 못 잡아서 직접 graphviz 다운받고 ,

환경변수 -> 사용자변수 path에 설치된 graphviz 경로추가  ,

시스템변수 path에 설치된 graphviz경로 + dot.exe 추가 후 재실행

value = [0, X] or [X,0]인것 :  순수노드들

질문을 통해 순수노드만 나올때까지 질문을 한다.

 

t_model = DecisionTreeClassifier( max_depth = 4)     # max_dept =4로 지정한 후 다시 돌려본 결과

질문이 4개까지로 제한되어 나온다.

질문을 제한하여 순수노드가 아닌 leaf_node가 (value=[76,62]) 나온다

impurity = True로 바꾸면 gini의 값도 나온다

 

 

min_samples_leaf=30으로 samples가 30이상인 질문들만 가능하게 제한한다.

 

특성선택

fi = t_model.feature_importances_         #특성이 영향을 끼친 정도를 알 수 있다.
fi

 

df = pd.DataFrame(fi, index = X_one_hot.columns)
df.sort_values(by = 0, ascending=False)  # ascending = false-> 내림차순

	0
odor_n	0.627391
stalk-root_c	0.170885
stalk-surface-below-ring_y	0.091794
spore-print-color_r	0.033148
gill-spacing_w	0.027991
...	...
gill-color_e	0.000000
gill-color_b	0.000000
gill-size_b	0.000000
gill-spacing_c	0.000000
habitat_w	0.000000
117 rows × 1 columns

특성이 영향을 끼친 정도를 알 수 있다.  -> 중요한 특성만을 가지고 모델에 넣거나

다른 모델에 적용 시킬 수 있다.

반응형

'빅데이터 서비스 교육 > 머신러닝' 카테고리의 다른 글

예제 타이타닉 생존자 예측분석  (0) 2022.06.24
Cross validation  (0) 2022.06.24
Decision Tree  (0) 2022.06.23
머신러닝 데이터 예측 (KNN모델)  (0) 2022.06.23
KNN 모델  (0) 2022.06.22