ML_AI/24_여름방학 인공지능 스터디

[교재] 5. 트리 알고리즘 (1)

안정민 2024. 7. 9. 23:03

5-1 결정 트리

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

- 판다스 데이터프레임으로 csv 파일을 제대로 읽어들였는지 확인하기 위해 head() 메서드로 처음 5개의 샘플을 확인

- 타깃값으로 0이면 레드와인, 1이면 화이트와인인 이진분류문제, 화이트와인이 양성클래스 (화이트와인을 골라내야함)

- info() 메서드 : 데이터프레임의 각 열의 데이터 타입과 누락된 데이터가 있는 지 확인하는 데 유용하다

- 4개의 열은 모두 float 실수값, 누락값은 없음 

- describe() 메서드 : 열에 대한 간략한 통계를 출력해 준다 (최소, 최대, 평균값 등을 확인 가능하다)

-알 수 있는 것은 알코올과 당도, pH 값의 스케일이 다르다는 것이다 (StandardScaler 클래스를 활용해 특성을 표준화)

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

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
)

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

 

- train_test_split() 함수는 파라미터 값을 지정하지 않으면 25%를 테스트세트로 지정 -> test_set 파라미터 0.2로 조정해서 20%만 테스트세트로 지정하도록 설정 변경

- (train_input.shape), (test_input.shape) = (5197, 3), (1300, 3)

 

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    -> 둘 다 점수가 낮으니 다소 과소적합되었다고 판단

 

- 이 수치만 보고서는 모델을 잘 표현하고 이해할 수가 없음, 설명하고 이해하기 쉬운 모델은 아님

 

 

2. 결정트리

-결정 트리 (decision tree) : 스무고개와 같이 질문(특징벡터)을 하나씩 던져서 분류하며 정답을 맞추어 나가는 것

-사이킷런의 DecisionTreeClassifier 클래스를 사용해 결정 트리 모델을 훈련할 수 있다.

- 사용법은 동일, fit() 메서드로 훈련하고 score() 메서드로 정확도를 평가한다

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

 

- 결정트리 모델을 만들 때 random_state의 의미 : 결정트리 알고리즘이 최적의 분할을 찾기 위해 특성의 순서를 ㅓㅅㄲ는데, 이의 무작위성을 고정하기 위함 -> 실전에서는 필요 없다

-훈련세트에 대한 점수가 굉장히 높고, 테스트세트에 대한 점수가 낮음

-과대 적합된 모델임

-사이킷런에서는 plot_tree() 함수를 사용해 결정트리를 이해하기 쉬운 트리 그림으로 출력해 준다

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

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

맨 위의 노드를 루트노드 (root node), 맨 아래의 노드를 리프 노드 (leaf node)라고 함

 

- plot_tree() 함수의 매개변수를 조정하여 원하는 만큼 간단한 트리 모양으로 조정하여 출력이 가능하다

- max_depth 파라미터 : 간선의 개수

- feature_names :특성의 이름을 전달할 수 있다, 특성의 이름은 리스트 형태로 전달

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

 

- 결정 트리에서는, 리프 노드에서 가장 많은 클래스가 예측 클래스가 된다

- 결정 트리에 회귀 문제를 적용한다면 리프 노드에 도달한 샘플 타깃의 평균을 예측값으로 사용하게 된다 -> DecisionTreeRegressor 클래스에서 지원

 

 

3. 불순도

(1) 지니 불순도 (제곱)

- 바로 위의 트리 박스 안에서 발견할 수 있는 gini는 지니 불순도 (Gini Impurity)를 의미한다

- DecisionTreeClassifier 클래스의 criterion (데이터 분할 기준 선정용) 매개변수의 기본값이 gini

- gini 불순도 계산법 = 클래스의 비율을 제곱해서 더한 다음 1에서 뺀다

 

-나뉘어진 두 클래스의 비율이 각각 0.5라면, 지니불순도는 0.5가 되어 최악이 된다

- 노드에 하나의 클래스만 있다면 지니 불순도는 0이 되어 가장 작아 최선이 되며, 이러한 노드를 순수 노드라고 함

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

- 불순도 차이는 샘플개수에 비례하여 모두 더한 후 부모 노드에서 빼면 됨

부모의 불순도 - (왼쪽노드 샘플 수 / 부모 샘플 수)*왼쪽노드 불순도 - (오른쪽노드 샘플 수 / 부모샘플 수)*오른쪽노드불순도

 

- 이러한 부모와 자식 노드 사이의 불순도 차이를 정보 이득 (Information gain) 이라고 한다

 

(2) 엔트로피 불순도 (밑이 2인 로그)

- DecisionTreeClassifier 클래스의 criterion='entropy'로 지정하여 엔트로피 불순도를 사용할 수 있음

- 엔트로피 불순도도 노드의 클래스 비율을 사용하지만 지니 불순도처럼 제곱이 아니라 밑이 2인 로그를 사용하여 곱한다

- 보통 지니불순도와 엔트로피 불순도의 결과의 차이는 크지 않음

 

<Conclusion>

-불순도 기준을 사용해 정보 이득이 최대가 되도록 노드를 분할한다
-노드를 순수하게 나눌 수록 정보 이득이 커진다

 

 

4. 가지치기 (pruning)

- 가지치기를 하는 가장 간단한 방법은 자라날 수 있는 트리의 최대 깊이를 지정하는 것이다

- DecisionTreeClassifier 클래스의 max_depth 파라미터의 숫자를 지정하여 트리의 깊이를 조절할 수 있음

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

 

 - 훈련세트의 성능은 낮아졌으나 테스트 세트의 성능은 거의 그대로이다, 이를 시각화하면

 

★★★★ 특성값의 스케일은 결정 트리 알고리즘에 아무런 영향을 미치지 않으므로 표준화 전처리를 할 필요가 없다

- 불순도는 클래스별 비율을 가지고 계산하고, 이렇게 계산한 불순도가 판단 기준이 되므로 스케일은 아무런 관련이 없음

 

-결정 트리는 어떤 특성이 가장 유용한지 나타내는 특성 중요도를 계산해 준다

- 루트노드에 가까울 수록 중요한 특성 (더 information gain이 높음)

- 특성 중요도는 결정 트리 모델의 feature_importances_ 속성에 저장되어있다

print(dt.feature_importances_)

>>> [0.12345626 0.86862934 0.0079144 ]

 

 

 

 ** 실습파일

5_1_결정트리.ipynb
0.52MB

 

 


 

**핵심 패키지와 함수

패키지 함수 설명
pandas head() 판다스 데이터프레임으로 csv 파일을 제대로 읽어들였는지 확인하기 위해 처음 5개의 샘플을 확인
info() 데이터프레임의 각 열의 데이터 타입과 누락된 데이터가 있는 지 확인
describe() 열에 대한 간략한 통계를 출력해 준다 (평균, 표준편차, 최소, 최대, 중간값, 1사분위수, 3사분위수를 확인 가능하다)
sklearn.tree DecisionTreeClassifier 결정 트리 모델 클래스, fit() 메서드로 훈련하고 score() 메서드로 정확도를 평가criterion 파라미터 : 기본값 gini
plot_tree() 결정트리를 이해하기 쉬운 트리 그림으로 출력
max_depth 파라미터 : 간선의 개수
feature_names :특성의 이름을 전달할 수 있다, 특성의 이름은 리스트 형태로 전달
DecisionTreeRegressor 결정 트리에 회귀 문제를 적용한 클래스
리프 노드에 도달한 샘플 타깃의 평균을 예측값으로 사용
feature_importances_  결정트리모델의 특성 중요도