# tree모양 시각화를 하면 에러가 많이 납니다... graphviz의 경로 문제 때문인것 같은데 Graphviz 실행 파일을 pip install graphviz로 설치하지 마시고 conda로 설치하면 저는 문제가 해결됐습니다..
conda install python-graphviz
1. Tree-Based Methods¶
- 트리기반의 모델들은 설명변수의 공간을 다수의 영역으로 분할하는 것을 포함
- 주어진 관측치에 대한 예측을 하기 위해 보통 그 관측치가 속하는 영역의 훈련 관측치들의 평균 또는 최빈값을 사용
- 트리기반의 방법들은 해석하기 쉽고 유용
아래의 예시와 tree모형을 직접 보면서 트리기반의 모델들이 어떻게 학습하고 예측하는지 알아봅시다.
2. Iris 예제 사용¶
In [29]:
from sklearn.datasets import load_iris
iris = load_iris()
model = DecisionTreeClassifier(max_depth=3)
model.fit(iris.data, iris.target)
In [30]:
# 시각화
dot_data = export_graphviz(model, # 의사결정나무 모형 대입
out_file = None, # file로 변환할 것인가
feature_names = iris.feature_names, # feature 이름
class_names = iris.target_names, # target 이름
filled = True, # 그림에 색상을 넣을것인가
rounded = True, # 반올림을 진행할 것인가
special_characters = True) # 특수문자를 사용하나
graph = graphviz.Source(dot_data)
graph
- 가장 상위 영역에는 전체 데이터 150개가 들어있고, target값이 0인 setosa가 50개, 1인 versicolor가 50개, 2인 virginica가 50개씩 들어있습니다.
- 첫번째 기준인 (petal width (cm) <= 0.8)에 따라 2개의 영역으로 분할됩니다.
- 이처럼 트리기반의 모델은 '어떤 변수로 영역을 나누었을 때, 데이터를 가장 잘 분류할 수 있는지'를 학습하는 것입니다.
- 이때 데이터를 잘 분류하였다를 나타내는 기준으로 gini지수와 엔트로피 지수를 많이 사용합니다.
- petal width (cm) <= 0.8 을 만족하는 데이터는 50개이고 모두 setosa인것을 알 수 있습니다. 데이터가 모두 setosa이기 때문에 gini지수가 0인 것을 볼 수 있습니다. 즉 비유하자면 혼합용액에 불순도가 거의 없이 순수하다는 의미라고 할 수 있죠
- 색상도 의미가 있습니다. 위의 예시에서는 setosa의 영역을 주황색, versicolor의 영역을 연두색, virginica의 영역을 보라색으로 하고 더 뚜렷하게 분류될 수록 색이 진해집니다.
이런식으로 데이터를 학습한다면 이후 예측을 어떻게 할까요?¶
- 한가지 예시를 들어서 위의 모형에 의해서는 어떤 예측값을 반환할지 살펴봅시다.
- 아이리스 데이터를 살펴보면 다음 모습입니다.
In [36]:
iris = pd.DataFrame(data = iris['data'], columns = iris['feature_names'])
iris.tail(1)
Out[36]:
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | |
---|---|---|---|---|
149 | 5.9 | 3.0 | 5.1 | 1.8 |
In [37]:
new = [[5.9, 3.0, 5.1, 1.8]]
model.predict(new)
Out[37]:
array([2])
- target값을 모르는 저 new데이터를 저 위의 트리모형 가장 위에 툭 떨어뜨려놓는다고 생각해봅시다.
- 가장 처음 기준(petal width<=0.8)을 만족하지 않아 오른쪽으로 이동합니다.
- 그 다음 기준인 (petal width<=1.75)을 만족하지 않아 또 오른쪽으로 이동합니다.
- 이제 마지막 기준인 petal length<=4.85을 만족하지 않아 가장 오른쪽 영역으로 이동합니다.
- new데이터가 도착하는 가장 오른쪽 영역에 학습데이터 43개가 모두 viginica이기 때문에 이 영역으로 도착하는 모든 데이터에 대해서는 viginica로 예측할 것입니다.
실제로 predict했을 때, 2(viginica)를 반환하였습니다.
3. Titanic 예제¶
In [2]:
import pandas as pd
import numpy as np
import seaborn as sns
df = sns.load_dataset('titanic')
In [3]:
df.head(2)
Out[3]:
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 1 | 0 | 7.2500 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.0 | 1 | 0 | 71.2833 | C | First | woman | False | C | Cherbourg | yes | False |
PreProcess¶
- 정말 간단한 전처리만 해주었습니다.
In [7]:
# 수치형 변수의 null은 평균값으로, 범주형 변수의 null은 최빈값으로 대치
df['age'].fillna(df['age'].mean(), inplace=True)
df['embarked'].fillna(df['embarked'].value_counts().index[0], inplace=True)
df['embark_town'].fillna(df['embark_town'].value_counts().index[0], inplace=True)
# null이 너무 많은 deck변수와 survived와 중복되보이는 alive컬럼을 삭제
df.drop('deck', axis=1, inplace=True)
df.drop('alive', axis=1, inplace=True)
# 범주형 변환을 위해 bool타입을 object로 변경
df = df.astype({'adult_male':'object', 'alone':'object'})
# 범주형 변수들을 더미화
df = pd.get_dummies(df)
Modeling¶
In [17]:
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
X = df.drop('survived', axis=1)
y = df.survived
x_train,x_test,y_train,y_test = train_test_split(X, y, random_state=2)
model = DecisionTreeClassifier(max_depth=2)
model.fit(x_train,y_train)
model.score(x_test,y_test)
Out[17]:
0.7713004484304933
Visualizing decision tree using graphviz¶
In [ ]:
conda install python-graphviz
!pip install graphviz
# tree모양 시각화를 하면 에러가 많이 납니다... 이 에러때문에 블로그 업로드 하고보니 하루가 갔네요ㅜㅜ
# graphviz의 경로 문제 때문인것 같은데 Graphviz 실행 파일을 pip install graphviz로 설치하지 마시고
# conda로 설치하면 저는 문제가 해결됐습니다..
In [10]:
from sklearn.tree import export_graphviz
import graphviz
In [18]:
dot_data = export_graphviz(model, # 의사결정나무 모형 대입
out_file = None, # file로 변환할 것인가
feature_names = x_train.columns, # feature 이름
class_names = ['생존X','생존'], # target 이름
filled = True, # 그림에 색상사용 여부
rounded = True, # 반올림을 진행 여부
special_characters = True) # 특수문자를 사용여부
graph = graphviz.Source(dot_data)
graph
- 가장 상위에 x_train의 데이터 668개가 모두 들어가있습니다. 668개중에 생존X의 개수가 418, 생존의 개수가 250입니다. 생존x의 개수가 더 많기 때문에 이 구간의 분류는 생존x이네요
- 가장 상위 영역에서 who_man변수를 기준으로 0.5이하의 데이터(269)들은 왼쪽으로 0.5보다 큰 데이터들(399)을 오른쪽으로 나누어집니다.
- 즉 전체 668개의 데이터가 who_man <= 0.5기준으로 인해 269개, 399개 두개로 나누어진것입니다.
- who_man <= 0.5기준에 부합해 왼쪽으로 이동한 데이터 269개 중에 생존x가 78개, 생존 데이터가 191개입니다. 이 영역에서는 생존의 데이터가 더 많기 때문에 이 구간의 분류는 생존입니다.
- 이런식으로 데이터를 가장 잘 분류할 수 있는 변수들을 찾아 영역을 나누어 가며 데이터 학습은 이루어집니다.
- 이 예제에서는 생존 영역을 파란색으로, 생존x의 영역을 주황색으로 표시하고 더 뚜렷하게 구분할 수 있을수록 색이 진해집니다.