
혼공학습단도 벌써 4주차!! 생각보다 시간이 빠르다.
5주차에는 한 주 휴가다!! 락앤롤!!

Ch.05 트리 알고리즘
화이트 와인을 찾아라!
Ch.05-1 결정 트리
오프라인에서 캔 와인을 판매하려고 신상 와인을 만들었다.
그런데!! 입고 된 와인을 확인해보니 화이트 와인인지, 레드 와인인지 표기가 누락되었다.
캔에 정보에는 알코올 도수, 당도, pH 값이 있다.
해당 값들로 와인 종류를 구별할 수 있을까?
로지스틱 회귀로 와인 분류하기
지난 시간에 로지스틱 회귀는 어떤 일이 일어날지 말지를 확률로 예측하는 모델로,
어떤 사람이 물건을 살지 말지와 같은 0~1의 값을 예측한다.
자 그럼 먼저 와인의 데이터들을 가지고 와보자!
import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')
wine.head()
wine.info()
< head / info 의 와인 데이터 >
와인의 데이터를 확인해보니 약 6497개의 샘플이 있고, 4개의 열은 모두 실수인 것을 확인할 수 있다.
이 수 많은 데이터의 간략한 통계를 알아보려면 describe() 함수를 사용하면 된다.
wine.describe()
< 와인 데이터의 통계 값 > mean : 평균, std : 표준 편차, min : 최소, 25% : 1사분위수, 50% : 중간값/2사분위수, 75% : 3사분위수 max : 최대
이제 값들이 잘 들어가 있는 것을 확인하였으니,
훈련 세트와 테스트 세트로 나누어보자.
data = wine[['alcohol', 'sugar', 'pH']]
target = wine['class']
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)
훈련 세트는 5,197개이고 테스트 세트는 1,300개 인 것을 확인 할 수 있다.
그럼 전처리 후에 로지스틱 회귀 모델을 훈련 시켜보자.
# 전처리 과정
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
엥 ? 그런데 훈련한 점수를 보니 생각보다 높지가 않다.
로지스틱 회귀는 선형적으로 구분하는 모델인데, 주어진 정보들은 어느 것이 레드 와인인지, 화이트 와인인지 판별하기 어려운 정보들이다.
그렇기 때문에 직선하나로 구분하기가 쉽지 않다.
그럼 이러한 경우에는 어떤 모델을 사용해야 할까?
결정트리

결정트리란?
데이터를 마치 스무고개 하듯이 질문을 따라가며 분류하는 모델이며,
특성값의 스케일은 결정 트리 알고리즘에 아무런 영향을 미치지 않기 때문에 표준화 전처리를 할 필요가 없는 모델이다.
그럼 이와 같은 상황에서 결정트리 모델이 적합한지 모델을 훈련시켜 점수를 확인해보자.
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
로지스틱 회귀와는 다르게 훈련 세트에 대한 점수가 엄청 높은 것을 확인할 수 있다.
그럼 결정트리 모델에서는 어떻게 해당 데이터를 판별했는지 분석해보자.
plt.figure(figsize=(10, 7))
plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()
위 그래프를 확인해보면 맨 위의 루트 노드는 당도가 -0.239 인지 물어보고, 같거나 작으면 왼쪽 그렇지 않으면 오른쪽으로 이동한다.
현재 루트 노드의 샘플 수는 5197개이고, 음성 클래스(레드 와인)의 수는 1258개, 양성 클래스(화이트 와인)의 수는 3939개 인 것을 확인 할 수 있다.
이어서 왼쪽 노드를 살펴보자.
이 노드는 당도가 더 낮은지를 물어보고 있다.(-0.802) 이때 음성 클래스와 양성 클래스의 수는 각각 1177개, 1754개로 루트 노드의 샘플 수보다 줄어들었다.
불순도
위 노드의 값을 보면 gini 값이 인쓴데 해당 값은 지니 불순도를 의미한다.
지니 불순도란?
섞인 정도를 나타내는 숫자로, 한쪽으로 모일수록 작아진다!!
그럼 앞의 트리에서 루트 노드는 어떻게 당도 -0.239를 기준으로 왼쪽과 오른쪽 노드로 나누었을까?
바로 노드를 나눌때 좋은 분리 판단인지기준을 하는 criterion을 이용해서 나누었다.
지니 블순도는 클래스 비율을 제곱해서 더한 다음 1에서 뺴면 값을 구할 수 있다.
지니 불순도 = 1 - (음성 클래스 비율² + 양성 클래스 비율²)
예를 들어 위 표에서 루트 노드로 계산을 한번 해보자.
루트 노드는 총 5,197개의 샘플이 있고 그중에 1,258개가 음성 클래스, 3,939개가 양성클래스이다.
해당 값을 공식에 대입해보면 아래와 같다.
1 - ((1258 / 5197)² + (3939 / 5197)²) = 0.367
값이 0 가까워 질수록 더 좋은 분리 상태이기 때문에 조금 섞여는 있지만, 나쁘지는 않은 상태라고 볼수 있다.
순수 노드
만약에 노드에 하나의 클래스만 있다면 지니 불순도는 0이 되어 가장 작은 상태가 된다.
이러한 노드를 순수 노드라고 한다.
정보 이득
결정트리에서 데이터를 얼마나 잘 나눴는지를 알려주는 기준을 정보이득이라고 하며,
부모와 자식 노드 사이의 불순도 차이를 계산하여 확인 할 수 있다.
가지치기
나무도 섞은 나뭇가지는 잘라내고 나무가 무럭 무럭 자랄수 있도록 가지치기를 해주는데,
결정 트리 모델에서도 이러한 과정이 꼭 필요하다.
가지치기를 하지 않으면 너무 깊어지면서 훈련 데이터에만 잘 맞고, 새로운 데이터에는 엉뚱한 예측을하게 되는 과적합이 발생하기 때문이다.
그렇기 때문에 가지치기를 해서 트리를 단순하게 만들어 과적합을 막고, 더 똑똑하게 예측을 하도록 하는 작업이 필요하다.
Ch. 05-2 교차 검증과 그리드 서치
| 항목 | 검증 세트 | 교차 검증 |
| 방식 | 데이터 일부를 떼어내 평가용으로 사용 | 데이터를 여러 개로 나누고 여러 번 학습+평가 반복 |
| 장점 | 빠르고 간단함 | 더 정확하고 안정적인 평가 가능 |
| 단점 | 평가가 데이터 나누기에 따라 달라질 수 있음 | 시간 오래 걸림 (학습 여러 번 함) |
검증 세트
모델 성능을 시험해보는 연습용 평가 데이터로, 모델이 과적합되었는지 확인할 때 사용한다.
import pandas as pd
wine = pd.read_csv('https://bit.ly/wine_csv_data')
wine.head()
# class 열을 타깃으로 사용, 나머지는 특성으로 사용
data = wine[['alcohol', 'sugar', 'pH']]
target = wine['class']
# test_size 매개변수를 0.2로 지정하여 train_input의 약 20%를 val_input으로 만듬
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)
5,197개 였던 훈련세트가 4,157개로 줄고, 검증 세트는 1,040개가 된 것을 확인 할 수 있다.
교차 검증
보통은 많은 데이터를 훈련에 사용할수록 좋은 모델이 만들어지나, 앞서 검증 세트를 만드느라 훈련 세트가 줄어버렸다.
이럴 때 교차 검증을 이용하면 안정적인 검증 점수를 얻고 훈련에 더 많은 데이터를 사용할 수 있다.
교차 검증은 검증 세트를 떼어 내어 학습하는 것을 여러번 반복 하기 때문에 더 정확하고 안정적이나, 시간이 오래 걸린다.

위 그림은 5-폴드 교차 검증의 예시다.
5-폴드 교차 검증은 아래와 같이 진행 된다.
- 원본 데이터셋을 k등분(5등분)
- 1/5를 검증 세트로, 4/5를 훈련 세트로 사용
- 검증 세트를 변경하면서 훈련 세트를 반복 학습한다.
하이퍼파라미터 튜닝
머신러닝 모델이 학습하는 파라미터를 모델 파라미터라고 부른다.
그럼 모델이 학습할 수 없어서 사용자가 지정해야하는 파라미터를 뭐라고 부를까?
바로 하이퍼 하라미터 튜닝이다.
예로 학습률, 트리 깊이, 이웃 수 등으로 데이터 기반으로 자동 조정하기 힘든 값들로 이루어져있다.
랜덤 서치
하이퍼파라미터 조합 중 일부만 무작위로 시도해서 빠르게!! 적당히!! 좋은 모델을 찾는 방법이다.
Ch. 05-3 트리의 앙상블
앙상블 학습이란?
어려운 문제를 한 사람에게 물어보는 것보다, 여러 사람에게 물어보고 의견을 모으면 더 정확한 답을 얻을 수 있다.
즉 여러 개의 모델을 합쳐서 하나의 더 똑똑한 모델을 만드는 방법이다.
정형 데이터와 비정형 데이터
학습할 때 코드에서 정리된 데이터를 썻던 CSV 파일들을 정형 데이터라고 부르며,
텍스트 데이터, 사진, 음악 등 데이터베이스나 엑셀로 표현하기 어려운 데이터들을 비정형 데이터라고 부른다.
랜덤 포레스트
여러 개의 결정트리를 만들고, 그 결과를 모아 최종 예측을 하는 앙상블 모델이다.
즉 데이터를 여러번 무작위로 샘플링하고, 각각 다른 결정트리를 만들어서, 그 결과를 모아서 예측한다.
'Newb > 머신러닝' 카테고리의 다른 글
| [혼공머신] 6주차 [6/6] (8) | 2025.08.15 |
|---|---|
| [혼공머신] 5주차 [5/6] (13) | 2025.08.09 |
| [혼공머신] 3주차[3/6] (1) | 2025.07.20 |
| [혼공머신] 2주차 (11) | 2025.07.13 |
| [혼공머신] 1주차 (2) | 2025.07.06 |


