728x90

비지도 학습 : 훈련 데이터에 타깃이 없다. 때문에 외부의 도움 없이 스스로 유용한 무언가를 학습해야 함. 대표적인 비지도 학습은 군집, 차원축소

히스토그램 : 구간별로 값이 발생한 빈도를 그래프로 표시한 것. x축이 구간(계급), y축이 발생 빈도(도수)

군집 : 비슷한 샘플끼리 하나의 그룹으로 모은다. 군집으로 모은 샘플 그룹을 쿨러스터라고 함

 

Unsupervised Learning : target이 없어 스스로 학습해야 함

 

군집 알고리즘

과일 사진 데이터 준비하기

!wget https://bit.ly/fruits_300_data -O fruits_300.npy

import numpy as np
import matplotlib.pyplot as plt

fruits = np.load('fruits_300.npy')

print(fruits.shape)
print(fruits[0, 0, :])
plt.imshow(fruits[0], cmap='gray')
plt.show()
plt.imshow(fruits[0], cmap='gray_r')
plt.show()
plt.imshow(fruits[0])
plt.show()

(300, 100, 100)

[ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 2 3 2 1 2 1 1 1 1 2 1 3 2 1 3 1 4 1 2 5 5 5 19 148 192 117 28 1 1 2 1 4 1 1 3 1 1 1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]

fig, axs = plt.subplots(1, 2)
axs[0].imshow(fruits[100], cmap='gray_r')
axs[1].imshow(fruits[200], cmap='gray_r')
plt.show()

픽셀 값 분석하기

apple = fruits[0:100].reshape(-1, 100*100)
pineapple = fruits[100:200].reshape(-1, 100*100)
banana = fruits[200:300].reshape(-1, 100*100)

print(apple.shape)
print(apple.mean(axis=1))

(100, 10000)

[ 88.3346 97.9249 87.3709 98.3703 92.8705 82.6439 94.4244 95.5999 90.681 81.6226 87.0578 95.0745 93.8416 87.017 97.5078 87.2019 88.9827 100.9158 92.7823 100.9184 104.9854 88.674 99.5643 97.2495 94.1179 92.1935 95.1671 93.3322 102.8967 94.6695 90.5285 89.0744 97.7641 97.2938 100.7564 90.5236 100.2542 85.8452 96.4615 97.1492 90.711 102.3193 87.1629 89.8751 86.7327 86.3991 95.2865 89.1709 96.8163 91.6604 96.1065 99.6829 94.9718 87.4812 89.2596 89.5268 93.799 97.3983 87.151 97.825 103.22 94.4239 83.6657 83.5159 102.8453 87.0379 91.2742 100.4848 93.8388 90.8568 97.4616 97.5022 82.446 87.1789 96.9206 90.3135 90.565 97.6538 98.0919 93.6252 87.3867 84.7073 89.1135 86.7646 88.7301 86.643 96.7323 97.2604 81.9424 87.1687 97.2066 83.4712 95.9781 91.8096 98.4086 100.7823 101.556 100.7027 91.6098 88.8976]

100*100짜리 이미지를 10000의 1차 배열로 생각하여 처리한다.

 

plt.hist(np.mean(apple, axis=1), alpha=0.8)
plt.hist(np.mean(pineapple, axis=1), alpha=0.8)
plt.hist(np.mean(banana, axis=1), alpha=0.8)
plt.legend(['apple', 'pineapple', 'banana'])
plt.show()

fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].bar(range(10000), np.mean(apple, axis=0))
axs[1].bar(range(10000), np.mean(pineapple, axis=0))
axs[2].bar(range(10000), np.mean(banana, axis=0))
plt.show()

apple_mean = np.mean(apple, axis=0).reshape(100, 100)
pineapple_mean = np.mean(pineapple, axis=0).reshape(100, 100)
banana_mean = np.mean(banana, axis=0).reshape(100, 100)

fig, axs = plt.subplots(1, 3, figsize=(20, 5))
axs[0].imshow(apple_mean, cmap='gray_r')
axs[1].imshow(pineapple_mean, cmap='gray_r')
axs[2].imshow(banana_mean, cmap='gray_r')
plt.show()

평균값과 가까운 사진 고르기

abs_diff = np.abs(fruits - apple_mean)
abs_mean = np.mean(abs_diff, axis=(1,2))
print(abs_mean.shape)

apple_index = np.argsort(abs_mean)[:100]
fig, axs = plt.subplots(10, 10, figsize=(10,10))
for i in range(10):
    for j in range(10):
        axs[i, j].imshow(fruits[apple_index[i*10 + j]], cmap='gray_r')
        axs[i, j].axis('off')
plt.show()

(300,)

여기서 의문은 비지도 학습인데도 불구하고 사과 이미지들의 평균을 구하고 여기에 비슷한 사과들을 추출하였다.

과연 이것을 비지도 학습이라고 볼 수 있을까?

해당 학습장 마지막에 그에 대해 똑같은 질문이 있다. 바로 다음 장에서 정말 target이 없는 경우 어떻게 하는지 알려 주겠다고 한다.

728x90
728x90

* 앙상블 학습 : 더 좋은 예측 결과를 만들기 위해 여러 개의 모델을 훈련하는 러신머닝 알고리즘

   - 정형 데이터를 다루는 데 가장 뛰어난 성과를 내고 있다. 대부분 결정 트리 기반

* 랜덤 포레스트 : 대표적인 결정 트리 기반 앙상블. bootstrap sample을 사용하고 랜덤하게 일부 특성을 선택하여 트리를 만드는 것이 특징

* 엑스트라 트리 : bootstrap sample을 만들지 않고 훈련 데이터를 사용. 대신 랜덤하게 노드를 분할해 과대적합을 감소

* 그레이디언트 부스팅 : 결정트리를 연속적으로 추가하여 손실 함수를 최소화. 훈련 속도가 느리지만 더 나은 성능을 기대할 수 있다. 이의 속도를 개선한 것이 히스토그램 기반 그레이디언트 부스팅이며 안정적인 결과와 높은 성능으로 인기

 

정형데이터 : 일정한 구조로 되어 있는 데이터 -> 앙상블 학습

비정형데이터 : 사진, 음악, 문학 등 일정하게 처리하기 어려운 데이터 -> 신경망 알고리즘

 

Random Forest

결정 트리를 랜덤하게 만들어 결정트리의 숲을 만든다.

bootstrap sample : train data에서 random으로 추출하여 sample을 만든다. 이 때 size는 train data와 같고, 중복 추출을 허용한다. -> train data가 1000개면 중복 추출 허용 방식으로 1000개를 뽑아 bootstrap sample을 만든다.

사이킷런의 random forest는 기본적으로 100개의 결정 트리를 훈련한 다음 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼는다. (회귀일 때는 단순히 각 트리의 예측을 평균한다고 한다)

Extra Trees

random forest와 매우 비슷하게 동작. 기본 100개의 결정 트리를 훈련. parameter도 동일.

bootstrap sample 대신 전체 훈련 세트를 사용. 대신 노드를 분할할 때 랜덤으로 분할.(splitter='random')

성능이 떨어질 수 있으나 과대적합을 막는데 효과가 있다.

Gradient boosting

깊이 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식.

사이킷런의 GradientBoostingClassifier는 기본 깊이 3인 결정 트리 100개 사용.

깊이가 얕기 때문에 과대적합에 강함. 높은 일반화 성능 기대.

4장에서 다루었던 하강법을 사용하여 트리를 앙상블에 추가. 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수 사용.

Histogram-based Gradient Boosting

입력 특성을 256개의 구간으로 나눈다. -> 노드를 분할할 때 최적의 분할을 빠르게 찾음

256개의 구간 중 하나를 떼어 놓고 누락된 값을 위해 사용한다. -> 누락된 특성이 있어도 이를 전처리 할 필요 없음

HistGradientBoostingClassifier는 트리 개수를 정하는데 n_estimators대신 부스팅 반복 횟수를 지정하는 max_iter를 사용. max_iter를 조정하여 성능을 조율.

 

사이킷런 외의 library

* XGBoost

* LightGBM

 

랜덤포레스트

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

wine = pd.read_csv('https://bit.ly/wine_csv_data')

data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()

train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)

from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.9973541965122431 0.8905151032797809

return_train_score의 기본값은 false : train socre를 같이 확인하면 과대적합을 파악하는데 용이.

훈련세트에 과대적합 되어 있다.

 

rf.fit(train_input, train_target)
print(rf.feature_importances_)

[0.23167441 0.50039841 0.26792718]

feature는 알코올 도수, 당도, pH순

5-1 결정트리에서는 아래와 같았다.

[0.12345626 0.86862934 0.0079144 ]
출처: https://bluelimn.tistory.com/entry/혼공머신-05-1-결정트리 [ANMIAN]

 

당도의 중요도가 내려가고 pH의 중요도가 높아졌다.

rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)

rf.fit(train_input, train_target)
print(rf.oob_score_)

0.8934000384837406

자체 알고리즘을 평가하는 기능이 있다. oob_score=True로 해주어야 한다.

엑스트라트리

from sklearn.ensemble import ExtraTreesClassifier

et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.9974503966084433 0.8887848893166506

et.fit(train_input, train_target)
print(et.feature_importances_)

[0.20183568 0.52242907 0.27573525]

그레이디언트 부스팅

from sklearn.ensemble import GradientBoostingClassifier

gb = GradientBoostingClassifier(random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.8881086892152563 0.8720430147331015

gb = GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.9464595437171814 0.8780082549788999

결정트리의 개수(default:100)를 500으로 늘려도 과대적합에 비교적 안전함

gb.fit(train_input, train_target)
print(gb.feature_importances_)

[0.15872278 0.68010884 0.16116839]

히스토그램 기반 부스팅

# 사이킷런 1.0 버전 아래에서는 다음 라인의 주석을 해제하고 실행하세요.
# from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier

hgb = HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.9321723946453317 0.8801241948619236

from sklearn.inspection import permutation_importance

hgb.fit(train_input, train_target)
result = permutation_importance(hgb, train_input, train_target, n_repeats=10,
                                random_state=42, n_jobs=-1)
print(result.importances_mean)

[0.08876275 0.23438522 0.08027708]

result = permutation_importance(hgb, test_input, test_target, n_repeats=10,
                                random_state=42, n_jobs=-1)
print(result.importances_mean)

[0.05969231 0.20238462 0.049 ]

hgb.score(test_input, test_target)

0.8723076923076923

XGBoost

from xgboost import XGBClassifier

xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.8824322471423747 0.8726214185237284

LightGBM

from lightgbm import LGBMClassifier

lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

0.9338079582727165 0.8789710890649293

 

결정트리
[0.12345626 0.86862934 0.0079144 ]
Random Forest
[0.23167441 0.50039841 0.26792718]
Extra Trees
[0.20183568 0.52242907 0.27573525]
Gradient Boosting
[0.15872278 0.68010884 0.16116839]
Histogram-based Gradient Boosting
[0.08876275 0.23438522 0.08027708]

 

728x90
728x90

이번 장에서는 하이퍼파라미터를 머신 러닝을 이용하여 찾을 수 있다는 것이 핵심으로 보인다.

 

검증세트: 하이퍼파라미터 튜닝을 위한 모델 평가 시, test set을 이용하지 않기 위해 훈련세트에서 다시 떼어낸 data set

교차검증: 훈련세트를 여러개의 폴드로 나누고, 하나는 검증세트로 사용하고 나머지는 훈련세트로 사용한다. 교차검증은 이러한 방식으로 검증세트를 바꿔가며 모든 폴드에 대해 검증 점수를 얻어 평균하는 방법

그리드서치: 하이퍼파라미터 탐색을 자동으로 해주는 도구. 탐색할 parameter를 나열하면 교차 검증을 수행하여 가장 좋은 검증 점수의 매개변수 조합을 선택한다.

랜덤서치: 연속된 매개변수 값을 탐색할 때 유용. 탐색 값을 직접 나열하는 것이 아니고 탐색 값을 샘플링할 수 있는 확률 분포 객체를 전달 함. 지정된 횟수만큼 샘플링하여 교차 검증을 수행하기 때문에 시스템 자원이 허락하는 만큼 탐색량을 조절할 수 있다.

 

 

검증 세트

import pandas as pd

wine = pd.read_csv('https://bit.ly/wine_csv_data')
data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(
    data, target, test_size=0.2, random_state=42)

sub_input, val_input, sub_target, val_target = train_test_split(
    train_input, train_target, test_size=0.2, random_state=42)

print(sub_input.shape, val_input.shape)

(4157, 3) (1040, 3)

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)

print(dt.score(sub_input, sub_target))
print(dt.score(val_input, val_target))

0.9971133028626413
0.864423076923077

교차 검증

from sklearn.model_selection import cross_validate

scores = cross_validate(dt, train_input, train_target)
print(scores)

{'fit_time': array([0.00867891, 0.00763416, 0.00746775, 0.00764298, 0.00717449]),
'score_time': array([0.00082707, 0.00078511, 0.00080347, 0.00081134, 0.00074959]),
'test_score': array([0.86923077, 0.84615385, 0.87680462, 0.84889317, 0.83541867])}

import numpy as np

print(np.mean(scores['test_score']))

0.855300214703487

<<< 위와 아래는 같은 내용이다

from sklearn.model_selection import StratifiedKFold

scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())
print(np.mean(scores['test_score']))

0.855300214703487

splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
print(np.mean(scores['test_score']))

0.8574181117533719

하이퍼파라미터 튜닝

from sklearn.model_selection import GridSearchCV

params = {'min_impurity_decrease': [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]}

gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)

gs.fit(train_input, train_target)

GridSearchCV(estimator=DecisionTreeClassifier(random_state=42),
n_jobs=-1,
param_grid={'min_impurity_decrease': [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]})

 

GridSearch는 상당히 많은 작업량 때문에 시간이 오래 걸린다. n_jobs은 작업에 사용할 CPU 개수이며 -1은 system 최대치
dt = gs.best_estimator_
print(dt.score(train_input, train_target))

0.9615162593804117

print(gs.best_params_)

{'min_impurity_decrease': 0.0001}

print(gs.cv_results_['mean_test_score'])

[0.86819297 0.86453617 0.86492226 0.86780891 0.86761605]

best_index = np.argmax(gs.cv_results_['mean_test_score'])
print(gs.cv_results_['params'][best_index])

{'min_impurity_decrease': 0.0001}

params = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001),
          'max_depth': range(5, 20, 1),
          'min_samples_split': range(2, 100, 10)
          }

gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(train_input, train_target)

GridSearchCV(estimator=DecisionTreeClassifier(random_state=42), n_jobs=-1, param_grid={'max_depth': range(5, 20), 'min_impurity_decrease': array([0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0008, 0.0009]), 'min_samples_split': range(2, 100, 10)})

 np.arange()는 parameter가 0.0001 ~ 0.001까지 0.0001씩 더한 배열 생성

range()도 동일하나 정수만 사용 가능

 

print(gs.best_params_)

{'max_depth': 14, 'min_impurity_decrease': 0.0004, 'min_samples_split': 12}

print(np.max(gs.cv_results_['mean_test_score']))

0.8683865773302731

랜덤 서치

from scipy.stats import uniform, randint
rgen = randint(0, 10)
rgen.rvs(10)
np.unique(rgen.rvs(1000), return_counts=True)

(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
array([102, 87, 91, 105, 122, 91, 109, 90, 87, 116]))

ugen = uniform(0, 1)
ugen.rvs(10)

array([0.09471503, 0.74711048, 0.81052059, 0.30578852, 0.37093519, 0.17989678, 0.96227617, 0.807383 , 0.69161244, 0.62003229])

params = {'min_impurity_decrease': uniform(0.0001, 0.001),
          'max_depth': randint(20, 50),
          'min_samples_split': randint(2, 25),
          'min_samples_leaf': randint(1, 25),
          }

from sklearn.model_selection import RandomizedSearchCV

gs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42), params, 
                        n_iter=100, n_jobs=-1, random_state=42)
gs.fit(train_input, train_target)

RandomizedSearchCV(estimator=DecisionTreeClassifier(random_state=42), n_iter=100, n_jobs=-1, param_distributions={'max_depth': <scipy.stats._distn_infrastructure.rv_frozen object at 0x7fdf61082d10>, 'min_impurity_decrease': <scipy.stats._distn_infrastructure.rv_frozen object at 0x7fdf7000f5d0>, 'min_samples_leaf': <scipy.stats._distn_infrastructure.rv_frozen object at 0x7fdf61082a10>, 'min_samples_split': <scipy.stats._distn_infrastructure.rv_frozen object at 0x7fdf61082090>}, random_state=42)

print(gs.best_params_)

{'max_depth': 39, 'min_impurity_decrease': 0.00034102546602601173, 'min_samples_leaf': 7, 'min_samples_split': 13}

print(np.max(gs.cv_results_['mean_test_score']))

0.8695428296438884

dt = gs.best_estimator_

print(dt.score(test_input, test_target))

0.86

 

 

scikit-learn

* cross_validate() : 교차 검증 수행(default 5-폴드)

* GridSearchCV : 교차 검증으로 하이퍼파라미터 탐색을 수행

* RandomizedSearchCV : 교차 검증으로 랜덤한 하이퍼파라미터 탐색을 수행

728x90
728x90

결정트리: yes/no로 구분하여 트리로 답을 찾는 알고리즘, 이해하기 쉽고 성능도 뛰어남

불순도: 결정트리가 최적의 질문을 찾기 위한 기준. sklearn은 gini불순도와 엔트로피 불순도를 제공

정보이득: 부도 노드와 자식 노드의 불순도 차이. 결정 트리 알고리즘은 정보 이득이 최대화 되도록 학습

  - 결정트리는 제한 없이 성장하면 훈련세트에 과대적합되기 쉬움.

  - 가지치기는 결정트리의 성장을 제한하는 방법

특성 중요도: 결정트리에 사용된 특성이 불순도를 감소하는데 기여한 정도

 

결정 트리

로지스틱 회귀로 와인 분류하기

import pandas as pd

wine = pd.read_csv('https://bit.ly/wine_csv_data')
wine.head()

wine.info()

 

info() 함수는 누락된 내용이 있는지 파악하는데 용이함

총 6497 entries중 non-null이 모두 6497이므로 누락된 내용은 없음

누락된 값이 있다면 그 data를 버리거나 평균 값으로 채워 넣어야 한다.

 

wine.describe()

describe()는 간단한 통계를 보여 준다.

data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(
    data, target, test_size=0.2, random_state=42)

print(train_input.shape, test_input.shape)

(5197, 3) (1300, 3)

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
ss.fit(train_input)

train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)

#로지스틱으로 계산을 해본다
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_scaled, train_target)

print(lr.score(train_scaled, train_target))
print(lr.score(test_scaled, test_target))

0.7808350971714451

0.7776923076923077

훈련세트(0.78), 테스트세트(0.77)로 과소적합

 

print(lr.coef_, lr.intercept_)

[[ 0.51270274 1.6733911 -0.68767781]] [1.81777902]

 

결정 트리

from sklearn.tree import DecisionTreeClassifier

dt = DecisionTreeClassifier(random_state=42)
dt.fit(train_scaled, train_target)

print(dt.score(train_scaled, train_target))
print(dt.score(test_scaled, test_target))

0.996921300750433

0.8592307692307692

로지스틱보다 나은 결과가 나왔지만 훈련세트가 0.99로 아주 높고 테스트세트가 0.85로 낮아 과대적합이다.

 

import matplotlib.pyplot as plt
from sklearn.tree import plot_tree

plt.figure(figsize=(10,7))
plot_tree(dt)
plt.show()

depth가 너무 깊어 과대적합이 되었다. 이를 제한하여 어떻게 결정되었는지 알아보자

plt.figure(figsize=(10,7))
plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

가지치기

dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_scaled, train_target)

print(dt.score(train_scaled, train_target))
print(dt.score(test_scaled, test_target))

0.8454877814123533

0.8415384615384616

max_depth를 5로 할 때 더 좋은 결과가 나왔는데 조건을 확인하기가 어려웠다

plt.figure(figsize=(20,15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

조건 식의 값들이 일반적으로 알기 어려운 숫자들이다. 이는 전처리를 거쳤기 때문으로 전처리 되지 않은 자료를 다시 넣고 결과를 확인해보자.

data에 대한 전처리가 필요하지 않다는 것이 결정 트리 알고리즘의 장점 중 하나

 

dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_input, train_target)

print(dt.score(train_input, train_target))
print(dt.score(test_input, test_target))

0.8454877814123533

0.8415384615384616

plt.figure(figsize=(20,15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

당도(sugar)가 4.325 이하, 1.625 이상이면서 alcohol이 11.025 이하면 red wine으로 인식하고 나머지는 white wine으로 인식

print(dt.feature_importances_)

[0.12345626 0.86862934 0.0079144 ]

 

728x90

+ Recent posts