#!/usr/bin/env python3


Random Forest


ensemble여러 머신러닝 model을 연결하여 강력한 model을 만드는 기법입니다.

ensemble model이 classifier와 regression 문제의 다양한 데이터셋에서 효과적이며

random forestgradient boosting은 둘 다 model을 구성하는 기본 요소로 decision tree를 사용합니다.


random forest는 기본적으로 조금씩 다른 여러 decision tree의 묶음입니다.


random forest의 Idea

각각의 tree는 비교적 예측을 잘 할 수 있지만 데이터의 일부에 overfitting하는 경향을 가진다는 데 기초합니다.

잘 작동하되 서로 다른 방향으로 overfitting된 tree를 많이 만들면 그 결과를 평균냄으로써 overfitting된 양을 줄일 수 있습니다.

이렇게 하면 tree model의 예측 성능이 유지되면서 overfitting이 줄어드는 것이 수학적으로 증명되었습니다.


이런 Idea를 구현하기 위해 decision tree를 많이 만들어야하고

각각의 tree는 타깃 예측을 잘해야 하고 다른 tree와는 구별되어야 합니다.


random forest는 tree들이 달라지도록 tree를 생성할 때 random하게 생성합니다.

random forest에서 tree를 random하게 만드는 방법은 2가지가 있습니다.


1. tree를 만들 때 사용하는 데이터를 무작위로 선택하고

2. 분할 테스트에서 특성을 무작위로 선택합니다.


random forest model에서 주요 parameter

n_estimators : 생성할 tree의 개수와

max_features : 최대 선택할 특성의 수입니다.


random forest는 기본적으로 bootstrap sampling(복원추출)을 사용하며

decision tree 생성으로 algorithm으로 진행합니다.


bootstrap sampling에서 어떤 데이터 포인트는 약 36.6%정도 누락될 확률이 존재하는데

이 것은 다음과정으로 확인할 수 있습니다.

 - 100개의 표본중 표본 하나가 선택되지 않을 확률은 99/100

 - 뽑은 표본을 제외하지 않고 100번 반복할 때 한번도 선택되지 않을 확률: (0.99)^100 = 0.366

 

n_estimators에서

bootstrap sampling은 random forest의 tree가 조금씩 다른 데이터셋으로 만들어지도록합니다.

max_feature에서 각 node는 특성의 일부를 무작위로 추출하여 사용합니다.


max_features를 전체 특성의수로 설정하면 모든 특성을 고려하므로 decision tree에서 무작위성이 들어가지 않습니다.

그러나 bootstrap sampling의 무작위성은 존재합니다.


max_features 값을 크게 하면 

random forest의 tree들은 같은 특성을 고려하므로 tree들이 매우 비슷해지고 가장 두드러진 특성을 이용해 데이터에 잘 맞춰집니다.


max_features를 낮추면 

random forest tree들은 많이 달라지고 각 tree는 데이터에 맞추기 위해 tree의 깊이가 깊어집니다.


인위적 데이터로 random forest를 tree별로 알아보면

from sklearn.ensemble import RandomForestClassifier

from sklearn.datasets import make_moons

from sklearn.model_selection import train_test_split


x, y = make_moons(n_samples=100, noise=0.25, random_state=3) # noise: Standard deviation of Gaussian noise added to the data.


x_train, x_test, y_train, y_test = train_test_split(x, y,

                                                    stratify=y, random_state=42)


forest = RandomForestClassifier(n_estimators=5, n_jobs=-1, random_state=42) # n_estimators: 사용할 tree수

forest.fit(x_train, y_train)


import matplotlib.pyplot as plt

import numpy as np

from mglearn.plots import plot_2d_classification


_, axes = plt.subplots(2, 3)

marker_set = ['o', '^']


for i, (axe, tree) in enumerate(zip(axes.ravel(), forest.estimators_)):

    axe.set_title('tree {}'.format(i))

    plot_2d_classification(tree, x, fill=True, ax=axe, alpha=0.4)


    for i, m in zip(np.unique(y), marker_set):

        axe.scatter(x[y==i][:, 0], x[y==i][:, 1], marker=m,

                    label='class {}'.format(i), edgecolors='k')

        axe.set_xlabel('feature 0')

        axe.set_ylabel('feature 1')


axes[-1, -1].set_title('random forest')

axes[-1, -1].set_xlabel('feature 0')

axes[-1, -1].set_ylabel('feature 1')

plot_2d_classification(forest, x, fill=True, ax=axes[-1, -1], alpha=0.4)


for i, m in zip(np.unique(y), marker_set):

    plt.scatter(x[y==i][:, 0], x[y==i][:, 1], marker=m,

                label='class {}'.format(i), edgecolors='k')

plt.show()

5개의 random dicision tree의 decision boundary와 예측한 확률을 평균내어 만든 random forest

5개의 트리가 만든 decision boundary는 매우 다릅니다.

bootstraping sampling 때문에 한쪽 tree에 나타나는 train point가 다른 tree에는 포함되지 않을 수 있습니다.



random forest를 이용하여 breast cancer datasets을 분석해보겠습니다.

from sklearn.datasets import load_breast_cancer


cancer = load_breast_cancer()


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

                                                    stratify=cancer.target, random_state=0)


n_feature = cancer.data.shape[1]


score_n_tr_est = []

score_n_te_est = []

score_m_tr_mft = []

score_m_te_mft = []


for i in np.arange(1, n_feature+1): # n_estimators와 mat_features는 모두 0보다 큰 정수여야 하므로 1부터 시작합니다.

    params_n = {'n_estimators':i, 'max_features':'auto', 'n_jobs':-1} # **kwargs parameter

    params_m = {'n_estimators':10, 'max_features':i, 'n_jobs':-1}


    forest_n = RandomForestClassifier(**params_n).fit(x_train, y_train)

    forest_m = RandomForestClassifier(**params_m).fit(x_train, y_train)

    

    score_n_tr = forest_n.score(x_train, y_train)

    score_n_te = forest_n.score(x_test, y_test)

    score_m_tr = forest_m.score(x_train, y_train)

    score_m_te = forest_m.score(x_test, y_test)


    score_n_tr_est.append(score_n_tr)

    score_n_te_est.append(score_n_te)

    score_m_tr_mft.append(score_m_tr)

    score_m_te_mft.append(score_m_te)


index = np.arange(len(score_n_tr_est))

plt.plot(index, score_n_tr_est, label='n_estimators train score', color='lightblue', ls='--') # ls: linestyle

plt.plot(index, score_m_tr_mft, label='max_features train score', color='orange', ls='--')

plt.plot(index, score_n_te_est, label='n_estimators test score', color='lightblue')

plt.plot(index, score_m_te_mft, label='max_features test score', color='orange')

plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.1),

           ncol=2, fancybox=True, shadow=False) # fancybox: 박스모양, shadow: 그림자

plt.xlabel('number of parameter', size=15)

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

plt.show()

parameter 갯수에 따른 train score와 test score

parameter의 갯수가 적을 때보다 많을때가 성능이 더 좋아 보입니다.



이번에는 사용한 특성의 중요도를 시각화 하겠습니다.

n_feature = cancer.data.shape[1]

index = np.arange(n_feature)


forest = RandomForestClassifier(n_estimators=100, n_jobs=-1)

forest.fit(x_train, y_train)

plt.barh(index, forest.feature_importances_, align='center')

plt.yticks(index, cancer.feature_names)

plt.ylim(-1, n_feature)

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

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

plt.show()

breast cancer로 만든 random forest의 feature importances

decision tree처럼 random foreset도 featre importances를 제공합니다.

일반적으로 random forest의 feature importances가 하나의 tree에서 제공하는 것보다 더 신뢰할 만합니다.


decision tree에서는 'worst radius'특성이 가장 중요하다고 보지만 random forest에서는 'worst perimeter'를 가장 중요한 요소로 판단했습니다.

random forest는 단일 tree보다 더 넓은 시각으로 데이터를 바라볼 수 있습니다. 




참고 자료: 

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

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

Kernelized Support Vector Machines  (0) 2018.03.15
Gradient Boosting Model  (0) 2018.03.15
Decision Tree  (0) 2018.03.14
Multi Linear Classification  (0) 2018.03.14
Logistic Regression  (1) 2018.03.13

+ Recent posts