Data Analysis/ML & DL

혼자 공부하는 머신러닝+딥러닝 / Chapter 05 트리 알고리즘

Bay Im 2023. 7. 30. 22:37
Chapter 05-1
결정 트리

 

- 결정 트리(Decision Tree)

예, 아니오에 대한 질문을 이어가면서 정답을 찾아 학습하는 알고리즘

사이킷런의 DecisionTreeClassifier 클래스 사용

 

특성값의 스케일은 결정 트리 알고리즘에 영향을 미치지 않기 때문에 표준화 전처리를 할 필요없다.

특성 중요도(불순도를 감소하는데 기여한 정도)를 활용하면 결정 트리 모델을 특성 선택에 활용할 수 있다.

 

 

불순도: 결정 트리가 최적의 질문을 찾기 위한 기준

지니 불순도(Gini impuricity)는 1 - (음성 클래스 비율의 제곱 + 양성 클래스 비율의 제곱)으로 구한다.

지니 불순도가 0이라면 순수 노드라고 부른다.

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

 

 

가지치기: 트리의 최대 깊이를 지정하여 가지치기를 한다.

DecisionTreeClassifier 클래스의 max_depth 매개변수를 지정한다.

 

 

 

- 함수 모음

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

describe(): 열에 대한 간략한 통계를 출력해주는 메서드

plot_tree(): 결정 트리를 이해하기 쉬운 트리 그림으로 출력해주는 함수

 

 

 

 코랩 실습 화면
# 결정 트리 모델
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))

# 트리 그림 출력
plt.figure(figsize=(10, 7))
plot_tree(dt)
plt.show()

# 깊이 1로 제한한 트리 그림
plt.figure(figsize=(10, 7))
plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

# 깊이 3의 결정 트리 모델
dt = DecisionTreeClassifier(max_depth=3, random_state = 42)
dt.fit(train_scaled, train_target)
print("깊이 3의 결정 트리 모델 훈련 세트 점수: ", dt.score(train_scaled, train_target))
print("깊이 3의 결정 트리 모델 테스트 세트 점수: ", dt.score(test_scaled, test_target))

# 깊이 3의 결정 트리 그림
plt.figure(figsize=(20, 15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()


# 데이터 전처리없이 결정 트리 모델 훈련
dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_input, train_target)
print("데이터 전처리없이 결정 트리 모델 훈련 세트 점수: ", dt.score(train_input, train_target))
print("데이터 전처리없이 결정 트리 모델 테스트 세트 점수: ", dt.score(test_input, test_target))

# 데이터 전처리없는 결정 트리 그림
plt.figure(figsize=(20, 15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()

 

- 출력 화면

 

결정 트리 모델 훈련 세트 점수:  0.996921300750433
결정 트리 모델 테스트 세트 점수:  0.8592307692307692
깊이 3의 결정 트리 모델 훈련 세트 점수:  0.8454877814123533
깊이 3의 결정 트리 모델 테스트 세트 점수:  0.8415384615384616
데이터 전처리없이 결정 트리 모델 훈련 세트 점수:  0.8454877814123533
데이터 전처리없이 결정 트리 모델 테스트 세트 점수:  0.8415384615384616
 

 

 

 

 

Chapter 05-2
교차 검증과 그리드 서치

 

검증 세트(validation set): 훈련 세트를 또 나눠서 테스트 세트를 사용하지 않고 모델을 평가하는 세트

 

 

교차 검증(cross validation): 검증 세트를 떼어 내어 평가하는 과정을 여러 번 반복하는 것

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

 

 

기본 미션
교차 검증을 그림으로 설명하기

 

 

코랩 실습 화면
# 교차 검증
# cross_validate() 사용
scores = cross_validate(dt, train_input, train_target)
print("교차 검증: ", scores)

# 교차 검증의 최종 점수 (test_score 의 평균)
print("교차 검증의 최종 점수: ", np.mean(scores['test_score']))


# 훈련 세트를 섞은 교차 검증
# StratifiedKFold() 사용
splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
print("훈련 세트를 섞은 교차 검증의 최종 점수: ", np.mean(scores['test_score']))

 

- 출력 화면

교차 검증: {'fit_time': array([0.00725913, 0.00694489, 0.00768757, 0.0073359 , 0.00700569]), 'score_time': array([0.00112009, 0.00117517, 0.00124049, 0.00114226, 0.00115561]), 'test_score': array([0.86346154, 0.85 , 0.87487969, 0.85755534, 0.8373436 ])}

교차 검증의 최종 점수: 0.856648034352558

훈련 세트를 섞은 교차 검증의 최종 점수: 0.8591544390099303

 

 

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

튜닝은 라이브러리가 제공하는 기본값을 그대로 사용해 모델을 훈련하고 교차 검증을 통해서 매개변수를 조금씩 바꾼다.

 

 

그리드 서치(Grid Search): 하이퍼파라미터 탐색을 자동화해 주는 도구

사이킷런의 GridSearchCV 클래스 사용

 

 

코랩 실습 화면
# 하이파라미터 탐색과 교차 검증 한번에 수행
# GridSearch 클래스 사용
params = {'min_impurity_decrease': [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]}
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(train_input, train_target)

# GridSearch가 찾은 검증 점수가 가장 높은 모델
dt = gs.best_estimator_
print("GridSearch를 이용한 교차 검증의 최종 점수: ", dt.score(train_input, train_target))
print("GridSearch가 찾은 최적의 매개변수: ", gs.best_params_)
print("교차 검증의 평균 점수: ", gs.cv_results_['mean_test_score'])

# 교차 검증의 평균 점수 중 가장 큰 값 찾기
# argmax() 사용
best_index = np.argmax(gs.cv_results_['mean_test_score'])
print("argmax()로 찾은 최적의 매개변수: ", gs.cv_results_['params'][best_index])

 

- 출력 화면

GridSearch를 이용한 교차 검증의 최종 점수: 0.9615162593804117

GridSearch가 찾은 최적의 매개변수: {'min_impurity_decrease': 0.0001}

교차 검증의 평균 점수: [0.86819297 0.86453617 0.86492226 0.86780891 0.86761605]

argmax()로 찾은 최적의 매개변수: {'min_impurity_decrease': 0.0001}

 

 

랜덤 서치(Random Search): 매개변수를 샘플링할 수 있는 확률 분포 객체를 전달한다. 연속된 매개변수 값을 탐색할 때 유용하다.

 

 

코랩 실습 화면
# 0~9의 랜덤 숫자 10개 출력
rgen = randint(0, 10)
rgen.rvs(10)

# 1000개의 숫자 샘플링 후 0~9의 각 개수 출력
np.unique(rgen.rvs(1000), return_counts=True)

# uniform 클래스로 0~1사이의 랜점 숫자 10개 출력
ugen = uniform(0, 1)
ugen.rvs(10)


# 탐색할 매개변수의 범위 지정
params = {'min_impurity_decrease': uniform(0.0001, 0.001),
        'max_depth': randint(20, 50),
        'min_samples_split': randint(2, 25),
        'min_samples_leaf': randint(1, 25),
        }

# 교차 검증 수행 및 최적의 매개변수 조합 찾기
gs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42), params, n_iter=100, n_jobs=-1, random_state=42)
gs.fit(train_input, train_target)
print("최적의 매개변수 조합: ", gs.best_params_)
print("최고의 교차 검증 점수: ", np.max(gs.cv_results_['mean_test_score']))

# 최적 모델의 성능 홧인
dt = gs.best_estimator_
print("최적 모델의 점수: ", dt.score(test_input, test_target))

 

- 출력 화면

최상의 매개변수 조합: {'max_depth': 14, 'min_impurity_decrease': 0.0004, 'min_samples_split': 12}

최상의 교차 검증 점수: 0.8683865773302731

최적의 매개변수 조합: {'max_depth': 39, 'min_impurity_decrease': 0.00034102546602601173, 'min_samples_leaf': 7, 'min_samples_split': 13}

최고의 교차 검증 점수: 0.8695428296438884

최적 모델의 점수: 0.86

 

 

 

- 함수 모음

cross_validate(): 교차 검증 함수, 평가할 모델 객체를 첫 번째 매개변수로 전달하고 훈련 세트를 전달한다.

회귀 모델일 경우 KFold 분할기를 사용하고 cv=StratifiedKFold()를 전달한다.

 

 

 

 

 

Chapter 05-3
 트리의 앙상블

 

정형 데이터(structured data): 어떤 구조의 형태로 되어 있는 데이터  ex) CSV, 데이터베이스, 엑셀 등

비정형 데이터(unstructured data): 정형 데이터와 반대되는 데이터  ex) 텍스트 데이터, 사진, 음악 등

 

 

앙상블 학습(ensemble learning): 정형 데이터를 다루는 알고리즘 중 가장 뛰어난 성과를 내는 알고ㅗ리즘

대부분 결정 트리를 기반으로 만들어져 있다.

 

 

- 랜덤 포레스트(Random Forest)

결정 트리를 랜덤하게 만들어 결정 트리의 숲을 만든다. 그리고 각 결정 트리의 예측을 사용해 최종 예측을 만든다.

훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만든다. 샘플이 중복되어 추출될 수도 있다. (부트스트랩 샘플)

 

앙상블 학습의 대표 주자 중 하나로 안정적인 성능을 갖고있다.

사이킷런의 RandomForestClassifier 클래사 사용

 

부트스트랩 샘플(bootstrap sample): 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만드는 것, 중복 추출도 가능

 

OOB 샘플(out of bag): 부트스트랩 샘플에 포함되지 않고 남는 샘플

 

 

선택 미션
Ch.05(05-3) 앙상블 모델 손코딩 코랩 화면 인증하기
코랩 실습 화면

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)


# 랜덤 포레스트 모델
rf = RandomForestClassifier(n_jobs=-1, random_state=42)

# 교차 검증
# cross_validate 함수 사용
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)

print("랜덤 포레스트 모델 훈련 세트 점수: ", np.mean(scores['train_score']))
print("랜덤 포레스트 모델 테스트 세트 점수: ", np.mean(scores['test_score']))

rf.fit(train_input, train_target)
print("랜덤 포레스트 모델의 특성 중요도: ", rf.feature_importances_)

# OOB 샘플 사용
# oob_score 매개변수 True로 전달
rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print("랜덤 포레스트 모델의 OOB 점수: ", rf.oob_score_)

 

- 출력 화면

랜덤 포레스트 모델 훈련 세트 점수: 0.9973541965122431

랜덤 포레스트 모델 테스트 세트 점수: 0.8905151032797809

랜덤 포레스트 모델의 특성 중요도: [0.23167441 0.50039841 0.26792718]

랜덤 포레스트 모델의 OOB 점수: 0.8934000384837406

 

 

- 엑스트라 트리(Extra Trees)

랜덤 포레스트와 비슷하게 동작하지만 부트스트랩 샘플을 사용하지 않는다.

각 결정 트리를 만들 때 전체 훈련 세트를 사용한다.

대신 노드를 분할할 때 무작위로 분할한다.

사이킷런의 ExtraTreesClassifier 클래스 사용

 

 

코랩 실습 화면
# 엑스트라 트리 모델
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)

score = cross_validate(et, train_input, train_target, return_train_score=True, n_jobs=-1)

print("엑스트라 트리 모델 훈련 세트 점수: ", np.mean(scores['train_score']))
print("엑스트리 트리 모델 테스트 세트 점수: ", np.mean(score['test_score']))

et.fit(train_input, train_target)
print("엑스트라 트리 모델의 특성 중요도: ", et.feature_importances_)

 

- 출력 화면

엑스트라 트리 모델 훈련 세트 점수: 0.9973541965122431

엑스트리 트리 모델 테스트 세트 점수: 0.8887848893166506

엑스트라 트리 모델의 특성 중요도: [0.20183568 0.52242907 0.27573525]

 

 

- 그레이디언트 부스팅(gradient boosting)

깊이가 얕은 결정 트리를 사용, 결정 트리를 연속적으로 추가하여 손실 함수를 최소화하는 앙상블 방법

사이킷런의 GradientBoostingClassifier 클래스 사용

 

 

코랩 실습 화면
# 그레이디언트 부스팅 모델
gb = GradientBoostingClassifier(random_state=42)

score = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print("그레이디언트 부스팅 모델 훈련 세트 점수: ", np.mean(scores['train_score']))
print("그레이디언트 부스팅 모델 테스트 세트 점수: ", np.mean(scores['test_score']))

# 트리 개수와 학습률 늘린 그레이디언트 부스팅 모델
gb = GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)

score = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print("트리 늘린 그레이디언트 부스팅 모델 훈련 세트 점수: ", np.mean(score['train_score']))
print("트리 늘린 그레이디언트 부스팅 모델 테스트 세트 점수: ", np.mean(score['test_score']))

gb.fit(train_input, train_target)
print("트리 늘린 그레이디언트 부스팅 모델의 특성 중요도: ", gb.feature_importances_)

 

- 출력 화면

그레이디언트 부스팅 모델 훈련 세트 점수: 0.9973541965122431

그레이디언트 부스팅 모델 테스트 세트 점수: 0.8905151032797809

트리 늘린 그레이디언트 부스팅 모델 훈련 세트 점수: 0.9464595437171814

트리 늘린 그레이디언트 부스팅 모델 테스트 세트 점수: 0.8780082549788999

트리 늘린 그레이디언트 부스팅 모델의 특성 중요도: [0.15872278 0.68010884 0.16116839]

 

 

- 히스토그램 기반 그레이디언트 부스팅(Histogram-based Gradient Boosting)

데이터를 전처리할 필요 없는 모델

사이킷런의 HistGradientBoostingClassifier 클래스 사용

XGBoost, LightGBM 라이브러리로 히스토그램 기반 그레이디언트 부스팅을 사용할 수 있다.

 

 

코랩 실습 화면
# 히스토그램 기반 그레이디언트 부스팅
hgb = HistGradientBoostingClassifier(random_state=42)

score = cross_validate(hgb, train_input, train_target, return_train_score=True)

print("히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: ", np.mean(score['train_score']))
print("히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: ", np.mean(score['test_score']))

hgb.fit(train_input, train_target)

result = permutation_importance(hgb, train_input, train_target, n_repeats=10, random_state=42, n_jobs=-1)
print("히스토그램 기반 그레이디언트 부스팅 모델의 특성 중요도: ", result.importances_mean)

print("히스토그램 기반 그레이디언트 부스팅 모델의 성능 점수: ", hgb.score(test_input, test_target))


# XGBoost 라이브러리를 이용한 히스토그램 기반 그레이디언트 부스팅 모델
xgb = XGBClassifier(tree_method='hist', random_state=42)

score = cross_validate(xgb, train_input, train_target, return_train_score=True)

print("XGBoost의 히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: ", np.mean(scores['train_score']))
print("XGBoost의 히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: ", np.mean(scores['test_score']))


# LightGBM 라이브러리를 이용한 히스토그램 기반 그레이디언트 부스팅 모델
lgb = LGBMClassifier(random_state=42)

scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print("LightGBM의 히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: ", np.mean(scores['train_score']))
print("LightGBM의 히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: ", np.mean(score['test_score']))

 

- 출력 화면

히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: 0.9321723946453317

히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: 0.8801241948619236

히스토그램 기반 그레이디언트 부스팅 모델의 특성 중요도: [0.08876275 0.23438522 0.08027708]

히스토그램 기반 그레이디언트 부스팅 모델의 성능 점수: 0.8723076923076923

XGBoost의 히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: 0.9973541965122431

XGBoost의 히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: 0.8905151032797809

LightGBM의 히스토그램 기반 그레이디언트 부스팅 모델 훈련 세트 점수: 0.935828414851749

LightGBM의 히스토그램 기반 그레이디언트 부스팅 모델 테스트 세트 점수: 0.8799326275264677

 

 

 

- 함수 모음

permutation_importance(): 히스토그램 기반 그레이디언트 부스팅의 특성 중요도 계산 함수