-
[혼공머] 5-1. 결정 트리Data Science/딥러닝 & 머신러닝 2025. 1. 12. 19:31
1. 로지스틱 회귀로 와인 분류하기
1. 배경
- 알코올, 도수, 당소, pH 값에 로지스틱 회귀 모델을 적용 → 레드 와인과 화이트 와인 구분
2. 데이터셋 준비
- head() : 앞 6개 데이터 확인
- info() : 각 열의 데이터 타입과 누락 여부
- describe() : 열에 대한 간략한 통계 출력
import pandas as pd wine = pd.read_csv('<https://bit.ly/wine_csv_data>') wine.head() wine.info() wine.describe()
0 이면 레드 와인
1이면 화이트 와인 (양성)
6497개의 샘플
4개의 열은 실숫값
누락 없음
스케일 달라서 표준화 필요
3. 훈련 데이터와 타겟 데이터 분리
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)
4. 데이터 전처리 - 표준화
from sklearn.preprocessing import StandardScaler ss = StandardScaler() ss.fit(train_input) train_scaled = ss.transform(train_input) test_scaled = ss.transform(test_input)
5. 로지스틱 회귀 모델 훈련
from sklearn.linear_model import LogisticRegression lr = LogisticRegression() lr.fit(train_input, train_target) print(lr.score(train_scaled, train_target)) # 0.78 print(lr.score(test_scaled, test_target)) # 0.77
- 정확도 둘 다 낮아서 과소적합
- 규제 매개변수를 바꾸거나 다항 특성 추가
6. 로지스틱 회귀 모델의 문제
- 로지스틱 회귀가 학습한 계수와 절편
- 왜 해당 계수를 학습했는지 잘은 모름
- 정확한 숫자의 의미는 모름
- 다항 특성 추가 시 설명하기 어려움
2. 결정 트리
1. 결정 트리
- 질문을 추가하며 분류 정확도를 높이는 알고리즘
- 구성 요소
- 노드 : 훈련 데이터의 특성에 대한 표현
- 루트 노드 : 맨 위의 노드
- 리프 노드 : 맨 아래에 달린 노드
- 가지 : 테스트의 결과
- 노드 : 훈련 데이터의 특성에 대한 표현
- sklearn.tree의 알고리즘 사용
- DeceisionTreeClassifier : 사이킷런의 결정 트리 알고리즘
- random_state는 실습 때문에 지정한 것.
- criterion : 데이터를 분할할 기준
- plot_tree : 트리 그림 확인
- max_depth 매개 변수 : 깊이 제한
- filled 매개변수 : 클래스에 맞게 노드 색칠
- features_names 매개변수 : 특성의 이름 전달
- DeceisionTreeClassifier : 사이킷런의 결정 트리 알고리즘
2. 결정 트리 모델 훈련
from sklearn.tree import DecisionTreeClassifier dt = DecisionTreeClassifier(random_state=42) dt.fit(train_scaled, train_target) print(dt.score(train_scaled, train_target)) # 0.99 print(dt.score(test_scaled, test_target)) # 0.85
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()
3. 트리 분석하기
- 노드의 구성 요소
- 테스트 조건
- 불순도
- 총 샘플 수
- 클래스별 샘플 수
- 화살표 : 조건 만족하면 Yes (왼쪽)
- 루트 노드의 색 변화 - filled=True
- 클래스의 비율이 높아질수록 점점 진한 색
- 결정 트리에서의 예측 : 리프 노드에서 가장 많은 클래스가 예측 클래스
-
3. 불순도
1. 지니 불순도
- DecisionTreeClassifier 클래스의 criterion 매개변수의 기본값
- 지니 불순도 공식
- 지니 불순도 = 1 - (음성 클래스 비율^2 + 양성 클래스 비율^2)
- 작을수록 순수하다.
- 부모 노드와 자식 노드의 불순도 차이가 크도록 트리를 성장시킨다.
2. 정보 이득 : 불순도의 차이; 클수록 좋다.
부모의 불순도 - (왼쪽 노드 샘플 수 / 부모의 샘플 수)왼쪽 노드 불순도 - (오른쪽 노드 샘플 수 / 부모의 샘플 수)오른쪽 노드 불순도
3. 엔트로피 불순도
- criterion =’entropy’
- 제곱을 사용하는 지니 불순도 대신 밑이 2인 ‘로그’ 사용
- -음성 클래스 비율 log_2(음성 클래스 비율) - 양성 클래스 비율log_2(양성 클래스 비율)
→ 불순도 기준을 사용해 정보 이득이 최대가 되도록 노드를 분할
→ 노드를 순수하게 나눌수록 정보 이득이 커진다.
→ 노드를 순수하게 나눌수록 정보 이득이 커진다.
4. 가지치기
1. 배경
- 트리가 제한 없이 자라나면 훈련 세트보다 테스트 세트에서 점수가 크게 낮았다.
- 무작정 자라나면 일반화가 잘 안 된다.
2. 가지치기 방법
- 트리의 최대 깊이 지정
- 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)
- 트리 구조 확인
- 0 : 레드와인, 1 : 화이트 와인
- 당도가 ‘음수’가 될 수는 없다.
- 불순도는 클래스 별 비율로 계산하니까 특성값에 표준화를 할 필요가 없다.
- 결정 트리의 장점 : 특성값에 표준화를 할 필요가 없는 것
- 위의 사진에서는 당도가 음수라는 특이한 점이 있다.
3. 표준화가 필요 없는 결정트리
dt = DecisionTreeClassifier(max_depth=3, random_state=42) dt.fit(train_input, train_target) dt.score(train_input, train_target), 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()
4. 트리의 특성 중요도
dt.feature_importances_
5. 이해하기 쉬운 결정 트리 모델 전체 소스 코드
# 데이터 준비 import pandas as pd wine = pd.read_csv('<https://bit.ly/wine_csv_data>') wine.head() wine.info() # 훈련 데이터와 타겟 데이터 준비 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) # 로지스틱 회귀의 과정 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) lr.score(train_scaled, train_target), lr.score(test_scaled, test_target) # 결정 트리 from sklearn.tree import DecisionTreeClassifier dt = DecisionTreeClassifier(random_state=42) dt.fit(train_input, train_target) dt.score(train_input, train_target), dt.score(test_input, test_target) # 전체적인 결정 트리 확인 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() # 불순도 DecisionTreeClassifier(criterion='gini') DecisionTreeClassifier(criterion='entropy') # 가지치기 dt = DecisionTreeClassifier(max_depth=3, random_state=42) dt.fit(train_input, train_target) dt.score(train_input, train_target), dt.score(test_input, test_target) plt.figure(figsize=(20, 15)) plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH']) plt.show() # 특성 중요도 dt.feature_importances_
'Data Science > 딥러닝 & 머신러닝' 카테고리의 다른 글
[혼공머] 4-2. 확률적 경사 하강법 (0) 2025.01.11 [혼공머] 4-1. 로지스틱 회귀 (0) 2025.01.10 [혼공머] 3-3. 특성 공학과 규제 (0) 2025.01.10 [혼공머] 3-2. 선형 회귀 (0) 2025.01.10 [혼공머] 3-1. K-최근접 이웃 회귀 (0) 2025.01.10