교차 검증
지금까지는 훈련 세트에서 모델을 훈련하고 테스트 세트에서 모델을 평가
테스트 세트에서 얻은 점수를 보고 일반화 성능을 가능
그런데 테스트 세트를 사용해 자꾸 성능을 확인하다 보면 점점 테스트 세트에 맞추게 되는 셈
테스트 세트로 일반화 성능을 올바르게 예측하려면 가능한 한 테스트 세트를 사용하지 말아야 함.
모델을 만들고 나서 마지막에 딱 한번만 사용하는 것이 좋음
테스트 세트를 사용하지 않으면 모델이 과대적합인지 과소적합인지 판단하기 어렵다.
테스트 세트를 사용하지 않고 이를 측정하는 간단한 방법은 훈련 세트를 또 나누는 것.
해당 데이터를 검증 세트라고 부른다.
전체 데이터 중 20%를 테스트 세트로 만들고 나머지 80%를 훈련 세트로 만들고, 이 훈련 세트 중에서 다시 20%를 떼어 검증 세트로 만듬.훈련세트에서 모델을 훈련하고 검증 세트로 모델을 평가. 이런식으로 테스트하고 싶은 매개변수를 바꿔가며 가장 좋은 모델을 고름.
교차 검증 장,단점
장점
- 모든 데이터셋을 훈련에 활용할 수 있음
- 정확도 향상
- 데이터 부족으로 인한 underfitting을 방지
- 모든 데이터셋을 평가에 활용할 수 있음
- 평가에 사용되는 데이터 편중을 막을 수 있음
- 평가 결과에 따라 좀 더 일반화된 모델을 만들 수 있음
단점
- 반복 횟수가 많아서 훈련 평가 시간이 오래 걸림
앙상블 학습
정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘.
하나의 데이터를 여러개의 분류기를 통해 다수의 학습 모델을 만들어 학습시키고 학습 결과를 결합함으로써 과적합을 방지하고 정확도를 높이는 학습 기법.
종류
- 보팅 : 앙상블 학습의 기본, 하위 모든 기법들이 보팅 사용
- 배깅 : 하나의 데이터를 여러개로 나누어 학습하는 앙상블 학습법
- 일반적으로 보팅은 하나의 데이터에 여러 알고리즘 적용
- 배깅은 여러개로 나우어진 데이터에 하나의 알고리즘을 적용하는 것으로 구분
- 여러개로 나누어진 데이터를 이용하는 배깅에서도 최종 예측값을 선택하는 행위 '보팅'이라고 함
- 부스팅 : 병렬로 수행되는 배깅과 달리 각 결과값을 이용하여 순차적으로 결합
- 랜덤 포레스트 : 배깅 + 결정 트리
랜덤 포레스트
앙상블 학습의 대표 주자 중 하나로 안정적인 성능 덕분에 널리 사용
결정 트리를 랜덤하게 만들어 결정트리의 숲을 만듬.
각 결정 트리의 예측을 사용해 최종 예측을 만듬.
각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾는다.
분류 모델인 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택하여 사용. 다만 회귀 모델인 RandomForestRegressor는 전체 특성을 사용.
RandomForest 학습 코드
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
wine = pd.read_csv('https://bit.ly/wine_csv_data')
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)
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
rf.fit(train_input, train_target)
print(rf.feature_importances_)
rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_)
result :
0.9973541965122431 0.8905151032797809
[0.23167441 0.50039841 0.26792718]
0.8934000384837406
엑스트라 트리 ( Extra Trees)
랜덤 포레스트와 매우 비슷하게 동작. 기본적으로 100개의 결정 트리를 훈련.
전체 특성 중 일부 특성을 랜덤하게 선택하여 노드를 분할하는 데 사용.
랜덤 포레스트와 엑스트라 트리의 차이점은 부트스트랩 샘플을 사용하지 않는다는 점.
각 결정 트리를 만들 때 전체 훈련 세트를 사용. 대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할.
하나의 결정 트리에서 특성을 무작위로 분할한다면 성능이 낮아지겠지만 많은 트리를 앙상블 하기 때문에 과대적합을 막고 검증 세트의 점수를 높이는 효과가 있다.
엑스트라 트리 ( Extra Trees ) 학습 코드
from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
et.fit(train_input, train_target)
print(et.feature_importances_)
result:
0.9974503966084433 0.8887848893166506
[0.20183568 0.52242907 0.27573525]
그레이디언트 부스팅 ( Gradient boosting )
깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블 하는 방법
사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정 트리를 100개 사용. 깊이가 얕은 결정 트리를 사용하기 때문에 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있다.
경사 하강법을 사용하여 트리를 앙상블에 추가한다. 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수를 사용한다.
그레이디언트 부스팅은 결정 트리는 결정 트리를 계속 추가하면서 가장 낮은 곳을 찾아 이동한다.
그레이디언트 부스팅 ( Gradient boosting ) 학습 코드
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
gb = GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
gb.fit(train_input, train_target)
print(gb.feature_importances_)
result :
0.8881086892152563 0.8720430147331015
0.9464595437171814 0.8780082549788999
[0.15872278 0.68010884 0.16116839]
히스토그램 기반 그레이디언트 부스팅 ( Histogram-based gradient boosting )
정형 데이터를 다루는 머신러닝 알고리즘 중에 가장 인기가 높은 알고리즘
입력 특성을 256개의 구간으로 나눕니다. 따라서 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있다.
256개의 구간 중에서 하나를 떼어 놓고 누락된 값을 위해서 사용한다. 따라서 입력에 누락된 특성이 있더라도 이를 따로 전처리할 필요가 없다.
과대적합을 잘 억제하면서 그레이디언트 부스팅보다 조금 더 높은 성능을 제공한다.
히스토그램 기반 그레이디언트 부스팅 ( Histogram-based gradient boosting) 학습 코드
from sklearn.ensemble import HistGradientBoostingClassifier
hgb = HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
from sklearn.inspection import permutation_importance
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)
result = permutation_importance(hgb, test_input, test_target, n_repeats=10,
random_state=42, n_jobs=-1)
print(result.importances_mean)
hgb.score(test_input, test_target)
from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
from lightgbm import LGBMClassifier
lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
result :
0.9321723946453317 0.8801241948619236
[0.08876275 0.23438522 0.08027708]
[0.05969231 0.20238462 0.049 ]
0.8824322471423747 0.8726214185237284
0.9338079582727165 0.8789710890649293
Colab 실행 화면
'IT > 머신러닝&딥러닝' 카테고리의 다른 글
06. 딥러닝 (0) | 2023.02.19 |
---|---|
05. 비지도 학습 (0) | 2023.02.12 |
03. 로지스틱 회귀 (0) | 2023.01.24 |
02. 회귀 알고리즘과 모델 규제 (0) | 2023.01.15 |
01. 머신러닝, 딥러닝 정리 및 개발 환경 (0) | 2023.01.08 |