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