머신러닝 공부 - 트리 알고리즘

머신러닝 공부 - 트리 알고리즘

결정 트리

import pandas as pd

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

wine.head()

csv 파일을 읽어 와서 5개를 확인 한다.

판다스의 유용한 함수인 info()와 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)

# 기본적으로 언급이 없다면 split()함수는 25%를 테스트로 저장, 현재 test_size 0.2로 주었으므로 20%를 테스트세트로 저장

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

생각보다 낮은 점수가 나온다, 모두 점수가 낮으므로 모델이 과소 적합 되어 잇다.

# 학습한 계수와 절편 출력

print(lr.coef_, lr.intercept_)

= [[ 0.51270274 1.6733911 -0.68767781]] [1.81777902]

즉, 각각의 샘플에 0.51, 1.6, -0.68 값을 곱한 후 더하고 마지막에 1.81을 더해서 분류가 수행된다.

이진 분류 이므로 이 값이 0보다 크면 화이트와인, 작으면 레드 와인으로 구분한다.

결정 트리 모델을 살펴보자. 장점은 이유를 설명하기 쉽다.

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

높은 정확도가 나온다.

import matplotlib.pyplot as plt

from sklearn.tree import plot_tree

plt.figure(figsize=(10, 7))

plot_tree(dt)

plt.show()

결정 트리 모습을 살펴볼 수 있다.

맨 위의 노드를 루프노드라고 부르고, 맨 아래 끝 노드를 리프노드라고 부른다.

너무 복잡하므로 깊이를 제한해서 살펴보자.

plt.figure(figsize=(10,7))

plot_tree(dt, max_depth = 1, filled = True, feature_names=['alcohol', 'sugar', 'pH'])

plt.show()

그림이 담고 있는 정보를 살펴보면, sugar이 테스트 조건으로 이에 해당하는 지에 따라 참이면 왼쪽, 맞지 않으면 오른쪽으로 이동한다. 다음으로 gini는 불순도이며 samples 는 총 샘플 수, value는 클래스 별 샘플 수를 의미한다.

리프노드의 가장 많은 클래스가 예측 클래스가 되는 구조이다.

불순도 (gini)

노드에서 데이터를 분할할 기준을 정하는 것

불순도 = 1- (음성 클래스 비율^2 + 양성 클래스 비율^2)

만일 지니 불순도가 0.5이면 음성과 양성 반반이므로 최악이고, 0일 경우 하나 뿐인 순수노드라고 부른다.

결정 트리 모델은 부모노드와 자식노드의 불순도 차이가 가능한 크도록 트리를 성장시킨다.

이 차이를 정보 이득이라고 부르며 정보 이득이 최대가 되어야 한다.

이제, 깊이를 3으로 제한하고 다시 해보자

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))

plt.figure(figsize=(20,15))

plot_tree(dt, filled=True, feature_names=['alchol', 'sugar', 'pH'])

plt.show()

깊이 1까지는 모두 sugar 을 기준으로 나누었으나, 2부터 alchol이 등장하기 시작했다.

왼쪽에서 부터 3번째 노드만 음성 크래스가 더 많다. (음성 클래스는 왼쪽) 즉, 이 노드에 도달해야 레드 와인으로 예측한다.

중요한 점은, 결정 트리 알고리즘의 장점 중 하나인 전처리를 할 필요가 없다는 것이다.

특성을 분류할 때 가장 유용한 특성을 알아보려면

print(dt.feature_importances_)

= [0.12345626 0.86862934 0.0079144 ]

즉, 두번째 특성인 당도 sugar가 가장 높다. 다음으로는 알콜, pH 순이다.

교차 검증과 그리드 서치

테스트 세트로 일반화 성능을 올바르게 예측하려면 가능한 테스트 세트를 사용하면 안된다.

검증세트

훈련세트 60%, 검증세트 20%, 테스트세트 20%

이런 식으로 대부분 많이 사용하는 방법이다.

훈련 세트에서 모델을 훈련하고, 검증 세트로 모델을 평가 그 후 매개변수를 바꿔가며 가장 좋은 모델을 고른다.

다음 마지막 테스트 세트에서 최종 점수를 평가한다.

import pandas as pd

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

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)

# 1차 분류

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

# 2차 분류

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

테스트, 훈련, 검증을 나누고 훈련에 검증을 넣은 결과이다.

훈련세트에 과대 적합 되어 있으므로 매개변수를 바꾸어 모델을 바꾸어야 한다.

교차 검증

보통 많은 데이터를 훈련에 사용할수록 좋은 모델이 만들어 진다.

그렇다고 검증 세트를 너무 조금 만들면 불안정하다. 이럴 때 교차 검증을 활용한다.

훈련세트를 k 부분으로 나누어 교차 검증을 수행하는 것을 k-폴드 교차 검증이라고 한다.

이렇게 얻은 점수를 평균하여 최종 검증 점수를 얻는다.

from sklearn.model_selection import cross_validate

scores = cross_validate(dt, train_input, train_target)

print(scores)

={'fit_time': array([0.0078795 , 0.00768542, 0.00772214, 0.0077827 , 0.00725532]), 'score_time': array([0.00083137, 0.00078273, 0.00078082, 0.00082922, 0.00073647]), 'test_score': array([0.86923077, 0.84615385, 0.87680462, 0.84889317, 0.83541867])}

위의 test score 값이 5개 이므로 5-폴드 교차 검증을 수행한다.

이 값을 평균내면

import numpy as np

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

= 0.855300214703487

교차 검증을 수행하면 모델에서 얻을 수 있는 최상의 검증 점수를 가늠할 수 있다.

이를 통해 결정트리의 매개변수 값을 바꿔가며 가장 좋은 성능이 나오는 모델을 찾는다. ( 테스트 세트 사용 않고)

하이퍼파라미터 튜닝

하이퍼파라미터 : 모델이 학습할 수 없어 사용자가 지정해야만 하는 파라미터

사이킷런에서 제공하는 그리드 서치(Grid Search)를 사용한다. 하이퍼 파라미터 탐색과 교차 검증을 한번에 수행 가능

GridSearchCV 클래스를 사용하면 매개변수를 일일이 바꿔가면서 찾는 것이 아닌, 자동으로 최상의 매개변수를 찾을 수 있다. 이때, 매개 변수 값을 랜덤 서치로 사용한다.

from http://kingjae.tistory.com/91 by ccl(A) rewrite - 2021-08-16 13:26:30