#!/usr/bin/env python3


Decision Tree Regression



ram 가격 데이터를 이용해 Decision Tree Regression을 알아보겠습니다.

먼저 ram 가격 데이터를 시각화하여 구조를 파악해보면

import pandas as pd

import os

import matplotlib.pyplot as plt

import mglearn

import numpy as np

path = os.path.join(mglearn.datasets.DATA_PATH, 'ram_price.csv')


ram_prices = pd.read_csv(path)

ram_prices = ram_prices.iloc[:, 1:] # iloc: 정수로 columns접근,  index number : 몇번째 인덱스 까지의 형태


plt.semilogy(ram_prices['date'], ram_prices['price'])

plt.xlabel('year', size=15)

plt.ylabel('price ($/Mbyte)', size=15)

plt.show()

log scale로 그린 램 가격 동향

시간이 지날수록 램 가격은 점점 감소하는 것을 알 수 있습니다.



DecisionTreeRegressor는 train set범위 밖의 데이터에 대해서는 예측을 할 수가 없는데 

다음의 코드는 이 것을 확인할 수 있습니다.

from sklearn.tree import DecisionTreeRegressor

from sklearn.linear_model import LinearRegression


data_train = ram_prices[ram_prices['date'] < 2000]

data_test = ram_prices[ram_prices['date'] >= 2000]


x_train = data_train['date'][:, np.newaxis] # train data를 1열로 만듭니다.

y_train = np.log(data_train['price'])


tree = DecisionTreeRegressor().fit(x_train, y_train)

lr = LinearRegression().fit(x_train, y_train)


# test는 모든 데이터에 대해 적용합니다.

x_all = ram_prices['date'].reshape(-1, 1) # x_all를 1열로 만듭니다.


pred_tree = tree.predict(x_all)

price_tree = np.exp(pred_tree) # log값 되돌리기


pred_lr = lr.predict(x_all)

price_lr = np.exp(pred_lr) # log값 되돌리기


plt.semilogy(ram_prices['date'], price_tree, label='tree predict', ls='--', dashes=(2,1))

plt.semilogy(ram_prices['date'], price_lr, label='linear reg. predict', ls=':')

plt.semilogy(data_train['date'], data_train['price'], label='train data', alpha=0.4)

plt.semilogy(data_test['date'], data_test['price'], label='test data')

plt.legend(loc=1)

plt.xlabel('year', size=15)

plt.ylabel('price ($/Mbyte)', size=15)

plt.show()

ram 가격 데이터로 만든 linear model과 regression tree의 예측값 비교

linear model은 직선으로 데이터를 근사합니다.

tree model은 train set을 완벽하게 fitting했습니다. 이는 tree의 complexity를 지정하지 않아서 전체 데이터를 fitting 하기 때문입니다.

그러나 tree model은 train 데이터를 넘어가버리면 마지막 포인트를 이용해 예측하는 것이 전부입니다.

Decision Tree의 주요 단점은 pre-pruning를 함에도 불구하고 overfitting되는 경향이 있어 일반화 성능이 좋지 않습니다.

이에 대안으로 ensemble 방법을 많이 사용합니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Lasso  (0) 2018.03.13
Ridge  (0) 2018.03.12
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12

#!/usr/bin/env python3


Decision Tree


Decision Tree결정트리는 True/False 질문을 이어나가면서 학습합니다.


다음 코드는 decision tree의 algorithm을 보여줍니다.

from mglearn.plots import plot_animal_tree

import matplotlib.pyplot as plt


plot_animal_tree()

plt.show()

몇 가지 동물들을 구분하기 위한 결정 트리

여기에서 tree의 node는 질문이나 정답을 담은 네모 상자를 말하며

root node는 최상위 node이고

leaf node는 마지막 node입니다.


decision tree를 학습한다는 것은 정답에 가장 빨리 도달하는 True/False 질문 목록을 학습하는 것입니다.

머신러닝에서 이런 질문들을 'test'라 합니다.


만약 tree를 만들 때 모든 leaf node가 pure node가 될 때 까지 진행하면 model의 complexity는 매우 높아지고 overfitting됩니다. 즉 train set의 모든 데이터포인트가 leaf node에 있다는 뜻입니다.


overfittng을 막는 전략은 크게 2가지가 있습니다.

1. tree 생성을 사전에 중단합니다 : pre-pruning

2. 데이터 포인트가 적은 node를 삭제하거나 병합합니다 : post-pruning



이제는 실제 데이터셋(wine dataset)으로 decision tree 분석을 해보겠습니다.

from sklearn.datasets import load_wine

from sklearn.model_selection import train_test_split

from sklearn.tree import DecisionTreeClassifier


wine = load_wine()


x_train, x_test, y_train, y_test = train_test_split(wine.data, wine.target,

                                                    stratify=wine.target, random_state=0)


tree = DecisionTreeClassifier(random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 1.000


print('{:.3f}'.format(score_te))

# 0.889

모든 leaf noe가 pure node이므로 train set의 정확도는 100%입니다.

tree는 train set의 모든 포인트들을 완벽하게 구분할 만큼 깊게 만들어집니다. 따라서 overfitting의 가능성이 매우 높아집니다.



이런 overfitting을 막기위해 깊이를 제한하는 방법을 사용할 수 있습니다.

pre-pruning의 방법 중 하나는 깊이의 최대를 설정하는 것입니다.

tree = DecisionTreeClassifier(max_depth=2, random_state=0)

tree.fit(x_train, y_train)


score_tr = tree.score(x_train, y_train)

score_te = tree.score(x_test, y_test)


print('{:.3f}'.format(score_tr))

# 0.910


print('{:.3f}'.format(score_te))

# 756

train_set의 score가 낮아진 것으로 보아 overfitting은 감소한 것처럼 보이지만, test set의 score또한 낮아졌으므로 이 데이터셋에 tree model은 적합하지 않음을 알 수 있습니다.



tree module의 export_graphviz함수를 이용해 tree를 시각화할 수 있습니다.

graphviz를 설치한 후 사용가능합니다

import graphviz

from sklearn.tree import export_graphviz


export_graphviz(tree, out_file='tree.dot',

                class_names=wine.target_names,

                feature_names=wine.feature_names,

                impurity=False# gini 미출력

                filled=True) # filled: node의 색깔을 다르게


with open('tree.dot') as file_reader:

    dot_graph = file_reader.read()


dot = graphviz.Source(dot_graph) # dot_graph의 source 저장

dot.render(filename='tree.png'# png로 저장

tree.png

wine 데이터셋으로 만든 Decision Tree

가장 중요한 특성이 proline아미노산임을 알 수 있습니다.



tree는 어떻게 작동하는지 요약하는 속성들을 사용할 수 있습니다.

가장 널리 사용되는 속성은 tree를 만드는 결정에 각 특성이 얼마나 중요한지는 평가하는 feature importance특성 중요도가 있습니다.

이 값은 0과 1사이의 숫자로 0은 전혀 사용되지 않았다는 뜻이고 1은 완벽하게 예측했다는 뜻입니다.

feature_imp = tree.feature_importances_

print('{}'.format(feature_imp))

# [0.         0.         0.         0.02885475 0.         0.

#  0.         0.         0.         0.43979596 0.         0.

#  0.53134929]



더 자세히 알아보기 위해 feature_importance를 시각화를 하겠습니다.

import numpy as np

n_feature = wine.data.shape[1]

idx = np.arange(n_feature)


plt.barh(idx, feature_imp, align='center')

plt.yticks(idx, wine.feature_names)

plt.xlabel('feature importance', size=15)

plt.ylabel('feature', size=15)

plt.show()

feature importance와 feature

root node에서 사용한 특성 'proline'이 가장 중요한 특성으로 나타납니다.


feature_importances_ 값이 낮다고 해서 이 특성이 유용하지 않다는 뜻은 아닙니다.

단지 이 tree가 특성을 선택하지 않았을 뿐이며, 다른 특성이 동일한 정보를 가지고 있어서 일 수도 있습니다.


feature importance 값은 'proline'가 중요하다가 알려주지만 이 값이 양성인지 음성인지는 알 수 없습니다.




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Classifier' 카테고리의 다른 글

Gradient Boosting Model  (0) 2018.03.15
Random Forest  (0) 2018.03.15
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13
k_NN(k-최근접 이웃) Classifier[2]  (1) 2018.03.12

+ Recent posts