05-1 결정 트리
로지스틱 회귀로 와인 분류하기
알코올 도수와 당도, pH 값의 스케일이 다릅니다.
→ 사이킷런의 StandardScaler 클래스를 사용해 특성을 표준화
결정트리
결정트리(Decision Tree) : 이유를 설명하기 쉽다
결정트리는 위에서부터 아래로 거꾸로 자라납니다.
루트 노드(root node) : 맨 위의 노드
리프 노드(leaf node) : 맨 아래 끝에 달린 노드
노드란?
결정 트리를 구성하는 핵심 요소
훈련 데이터의 특성에 대한 테스트를 표현
sugar : 테스트 조건
gini : 불순도
samples : 총 샘플 수
value : 클래스별 샘플 수[음성클래스, 양성클래스]
filled_True : 클래스마다 색깔을 부여하고, 어떤 클래스의 비율이 높아지면 점점 진한 색으로 표시합니다.
결정 트리에서 예측하는 방법은 리프 노드에서 가장 많은 클래스가 예측 클래스가 되는 것입니다.
만약 이 결정 트리의 성장을 여기서 멈춘다면 왼쪽 노드에 도달한 샘플과 오른쪽 노드에 도달한 샘플은 모두 양성 클래스로 예측됩니다. (두 노드 모두 양성 클래스의 개수가 많기 때문)
만약 결정 트리를 회귀 문제에 적용하면 리프 노드에 도달한 샘플의 타깃을 평균하여 예측값으로 사용합니다.
불순도
gini : 지니 불순도(Gini impurity)
DecisionTreeClassifier 클래스의 criterion(기준) 매개변수의 기본값이 ‘gini’입니다.
G = 1 − (p2 + (1−p)2)
- 양성 클래스 비율 : p
- 음성 클래스 비율 : 1-p
순수 노드 : 지니 불순도 0 (하나의 클래스만 존재)
결정 트리 모델은 부모 노드와 자식 노트의 불순도 차이가 가능한 크도록 트리를 성장시킵니다.
부모와 자식 노드 사이의 불순도 차이(정보이득) =
부모의 불순도 – (왼쪽 노드 샘플수/부모의 샘플수)*왼쪽 노드 불순도 – (오른쪽 노드 샘플수/부모의 샘플수)*오른쪽 노드 불순도
DecisionTreeClassifier 클래스에서 criterion=’entropy’를 지정하여 엔트로피 불순도를 사용할 수 있습니다.
엔트로피 불순도도 노드의 클래스 비율을 사용하지만 지니 불순도처럼 제곱이 아니라 밑이 2인 로그를 사용하여 곱합니다.
Entropy = −plog2(p) −(1−p)log2(1−p)
가지치기
무작정 끝까지 자라나는 프리가 만들어지면 훈련 세트에서는 아주 잘 맞겠지만 테스트 세트에서 점수는 그에 못 미칠 것입니다.
이를 두고 일반화가 잘 안될 것 같다고 말합니다.
결정 트리에서 가지치기를 하는 가장 간단한 방법은 자라날 수 있는 트리의 최대 깊이를 지정하는 것입니다.
특성값의 스케일은 결정 트리 알고리즘에 아무런 영향을 미치지 않습니다.
따라서 표준화 전처리를 할 필요가 없습니다.
이것이 결정 트리 알고리즘의 또 다른 장점 중 하나입니다.
05-2 교차 검증과 그리드 서치
검증 세트
훈련 세트(Training Set) : 모델을 학습시키는 데 사용
검증 세트(Validation Set) : 학습한 모델의 성능을 평가하고 하이퍼파라이터를 조정하기 위해 사용 (개발 세트 dev set 라고도 부름)
테스트 세트(Test Set) : 최종적으로 모델의 일반화 성능을 평가
파라미터(Parameter) : 모델이 학습하면서 자동으로 결정되는 값
하이퍼파라미터(Hyperparameter) : 모델이 학습되기 전에 미리 정해줘야 하는 값
여러 모델을 만들어서 계속 테스트 세트로 비교하면 테스트 세트에 가장 운좋게 잘 맞은 모델을 고르게 됩니다.
결국 테스트 세트에 간접적으로 과적합된 모델이 만들어지게 됩니다.
테스트 세트를 사용하지 않고 이를 측정하는 간단한 방법은 검증 세트를 따로 두는 것입니다.
상황 | 훈련 | 검증 | 테스트 |
---|---|---|---|
일반적 | 60~70% | 15~20% | 15~20% |
데이터 적을 때 | 80~90% (교차 검증 포함) | – | 10~20% |
딥러닝 등 실무 | 80% | 10% | 10% |
교차 검증
보통 많은 데이터를 훈련에 사용할수록 좋은 모델이 만들어집니다.
그렇다고 검증 세트를 너무 조금 떼어 놓으면 검증 점수가 들쭉날쭉하고 불안정할 것입니다.
이럴때 교차 검증(cross validaiton)을 이용하면 안정적인 검증 점수를 얻고 훈련에 더 많은 데이터를 사용할 수 있습니다.
3-폴드 교차검증이란?
훈련 세트를 세 부분으로 나눠서 교차 검증을 수행하는 것을 3-폴드 교차 검증이라고 합니다.
통칭 k-폴드 교차 검증(k-fold cross validation)이라고 하며, 훈련 세트를 몇 부분으로 나누냐에 따라 다르게 부릅니다.
k-겹 교차 검증이라고도 부릅니다.
보통 5-폴드 교차 검증이나 10-폴드 교차 검증을 많이 사용합니다.
이렇게 하면 데이터의 80 ~ 90%까지 훈련에 사용할 수 있습니다.
검증 세트가 줄어들지만 각 폴드에서 계산한 검증 점수를 평균하기 때문에 안정된 점수로 생각할 수 있습니다.
cross_val_score() : 단일 점수만 간편하게 구하고 싶을 때
항목 | 설명 |
---|---|
반환값 | 각 폴드에서의 점수 (배열) |
결과 종류 | 한 가지 스코어만 (test_score) |
파라미터 | scoring='accuracy' , cv=5 등 |
간단한 비교용 | ✔ 추천 |
- scoring : 평가 지표(기본값은 분류일 땐 정확도)
- cv : 교차 검증 폴드 수
cross_validate() : 다양한 결과(시간, 여러 지표 등)를 보고 싶을 때
항목 | 설명 |
---|---|
반환값 | 딕셔너리 형태 (fit_time , score_time , test_score , train_score ) |
결과 종류 | 다양한 지표 사용 가능 |
여러 지표 비교 | ✔ 추천 |
학습 시간, 검증 시간까지 포함 | ✔ 추천 |
fit_time : 훈련하는 시간
score_time : 검증하는 시간
각 키마다 5개의 숫자 → cross_validate() 함수는 기본적으로 5-폴드 교차 검증을 수행합니다.
교차 검증의 최종 점수는 test_score 키에 담긴 5개의 점수를 평균하여 얻을 수 있습니다.
이름은 test_score지만 검증 폴드의 점수입니다.
한 가지 주의할 점은 cross_validate() 는 훈련 세트를 섞어 폴드를 나누지 않습니다.
앞서 우리는 train_test_split() 함수로 전체 데이터를 섞은 후 훈련 세트를 준비했기 때문에 따로 섞을 필요가 없습니다.
하지만 교차 검증을 할때 훈련 세트를 섞으려면 분할기를 지정해야 합니다.
항목 | KFold | StratifiedKFold |
---|---|---|
분할 방식 | 단순하게 K개로 나눔 | 클래스 비율 유지하며 K개로 나눔 |
분류 문제 적합도 | 중간 | 매우 적합 |
클래스 불균형 고려 | ❌ | ✅ |
회귀 문제 사용 가능 | ✅ | ❌ |
코드 | KFold(n_splits=5) |
StratifiedKFold(n_splits=5) |
하이퍼파라미터 튜닝
모델 파라미터 : 머신러닝 모델이 학습하는 파라미터
하이퍼파라미터 : 모델이 학습할 수 없어서 사용자가 지정해야만 하는 파라미터
AutoML : 사람의 개입 없이 하이퍼파라미터 튜닝을 자동으로 수행하는 기술
그리드서치(Grid Search) : 여러 하이퍼파라미터 조합을 모두 시도해서 가장 좋은 성능을 내는 조합을 찾는 방법과 함수
사이킷런의 GridSearchCV클래스는 그리드서치 + 교차 점증(CV)을 결합한 도구입니다.
cv_results_['params']
는 여러 하이퍼파라미터 조합이 담긴 리스트gs.best_index_
는 이 리스트에서 가장 좋은 조합의 인덱스 번호- 따라서 이것은 최적 하이퍼파라미터 조합(dict) 을 가져오는 코드
그리드 서치 탐색 과정
- 먼저 탐색할 매개변수 지정
- 훈련 세트에서 그리드 서치를 수행하여 최상의 평균 검증 점수가 나오는 매개변수 조합을 찾는다. (이 조합은 그리드 서치 객체에 저장)
- 그리드 서치는 최상의 매개변수에서 (교차 검증에 사용한 훈련 세트가 아니라) 전체 훈련 세트를 사용해 최종 모델을 훈련한다. 이 모델도 그리드 서치 객체에 저장된다.
랜덤 서치
매개변수의 값이 수치일 때 값의 범위나 간격을 미리 정하기 어려울 수 있습니다.
이럴때 랜덤 서치(Random Search)를 사용하면 좋습니다.
랜덤 서치에는 매개변수 값의 목록을 전달하는 것이 아니라 매개변수를 샘플링할 수 있는 확률분포 객체를 전달합니다.
싸이파이(scipy) 라이브러리란?
싸이파이는 파이썬의 핵심 과학 라이브러리 중 하나입니다.
적분, 보간, 선형 대수, 확률 등을 포함한 수치 계산 전용 라이브러리입니다.
from scipy.stats import uniform, randint
GridSearchCV
는 모든 조합을 탐색하지만, 경우의 수가 너무 많으면 속도가 느려집니다.- 그래서 일부 조합만 무작위로 탐색하는
RandomizedSearchCV
가 등장 - 이때 탐색 범위를 지정해줄 때 필요한 게 바로
scipy.stats.uniform
,randint
같은 확률 분포 객체 randint
: 정수 범위를 균등하게 무작위 샘플링uniform
: 실수(부동소수점) 범위를 균등하게 무작위 샘플링
rvs(n)
: 그 분포에서 n개의 무작위 값을 생성, random variates (무작위 표본)의 약자
05-3 트리의 앙상블
정형 데이터와 비정형 데이터
정형 데이터(structured data)
- 행과 열의 형태로 명확하게 구조화된 데이터
- 보통 엑셀 표, 데이터베이스 테이블 형태로 되어 있음
비정형 데이터(unstructured data)
- 정해진 구조가 없고, 행/열로 명확히 표현하기 어려운 데이터
- 사람이 이해할 수는 있지만, 컴퓨터는 전처리나 변환 없이는 바로 분석 불가
앙상블 학습(ensemble learning) : 정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘
신경망 알고리즘 : 비정형 데이터를 다루는 알고리즘
랜덤 포레스트
랜덤 포레스트(Random Forest)는 앙상블 학습의 대표 주자 증 하나로 안정적인 성능 덕분에 널리 사용되고 있습니다.
랜덤 포레스트는 결정 트리를 랜덤하게 만들어 결정 트리의 숲을 만듭니다.
그리고 각 결정 트리의 예측을 사용해 최종 예측을 만듭니다.
랜덤 포레스트는 각 트리를 훈련하기 위한 데이터를 랜덤하게 만드는데, 이 데이터를 만드는 방법이 독특합니다.
우리가 입력한 훈련 데이터에서 랜덤하게 샘플을 추출하여 훈련 데이터를 만듭니다.
이때 한 샘플이 중복되어 추출될 수 있습니다.
이렇게 만들어진 샘플을 부트스트랩(bootstrap sample)이라고 합니다.
기본적으로 부트스트랩 샘플은 훈련 세트의 크기와 같게 만듭니다.
1,000개의 샘플이 있을 때 먼저 1개를 뽑고, 다시 가방에 넣어 그 다음 샘플을 뽑는 방식을 뜻하는 것으로, 1,000개의 샘플이 들어 있는 가방에서 중복하여 1,000개의 샘플을 뽑습니다.
또한 각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾습니다.
분류 모델인 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택합니다.
다만 회귀 모델인 RandomForestRegressor는 전체 특성을 사용합니다.
사이킷런의 랜덤 포레스트는 기본적으로 100개의 결정 트리를 이런 방식으로 훈련합니다.
분류일 때는 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼습니다.
회귀일 때는 단순히 각 트리의 예측을 평균합니다.
랜덤 포레스트는 랜덤하게 선택한 샘플과 특성을 사용하기 때문에 훈련 세트에 과대적합되는 것을 막아주고 검증 세트와 테스트 세트에서 안정적인 성능을 얻을 수 있습니다.
RandomForestClassifier는 자체적으로 모델을 평가하는 점수를 얻을 수 있습니다.
OOB(out of bag) 샘플 : 훈련 세트에서 중복을 허용하여 만든 부트스트랩 샘플에 포함되지 않고 남는 샘플
이 남는 샘플을 사용하여 부트스트랩 샘플로 훈련한 결정 트리를 평가할 수 있습니다. (검증 세트의 역할)
RandamForestClassifier 클래스의 oob_score=True로 지정하면(기본값 False) 각 결정 트리의 OOB 점수를 평균하여 출력합니다.
엑스트라 트리
엑스트라 트리(Extra Trees)는 랜덤 포레스트와 매우 비슷하게 동작합니다.
랜덤 포레스트와 엑스트라 트리의 차이점은 부트스트랩을 사용하지 않는다는 점입니다.
즉 각 결정 트리를 만들 때 전체 훈련 세트를 사용합니다.
대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할합니다.
하나의 결정 트리에서 특성을 무작위로 분할한다면 성능이 낮아지겠지만, 많은 트리를 앙상블 하기 때문에 과대적합을 막고 검증 세트의 점수를 높이는 효과가 있습니다.
그레이디언트 부스팅
그레이디언트 부스팅(gradient boosting)은 깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블하는 방법입니다.
사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정 트리를 100개 사용합니다.
깊이가 얕은 결정 트리를 사용하기 때문에 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있습니다.
경사하강법을 사용하여 트리를 앙상블에 추가하며 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수를 사용합니다.
경사하상법은 모델이 틀린 정도(손실)를 최소화하기 위해 파라미터(모델의 가중치와 절편)를 조금씩 조정하는 최적화 알고리즘으로 손실 함수가 있어야 경사하강법을 쓸 수 있습니다.
학습률(learning rate) : 손실 함수를 줄이기 위해 얼마만큼 이동할지를 결정하는 값
학습률을 증가시키고 트리의 개수를 늘리면 조금 더 성능이 향상될 수 있습니다.
subsample : 각 트리를 학습할 때 사용하는 훈련 데이터의 비율을 결정하는 매개변수
subsample이 1.0(기본값)이면 전체 훈련 세트를 사용하지만 1보다 작으면 훈련 세트의 일부를 사용합니다.
이는 마치 경사 하강법 단계마다 일부 샘플을 랜덤하게 선택하여 진행하는 확률적 경사 하강법이나 미니배치 경사 하강법과 비슷합니다.
일반적으로 그레이디언트 부스팅이 랜덤 포레스트보다 조금 더 높은 성능을 얻을 수 있으나 훈련 속도가 느립니다.
GradientBoostingClassifier는 트리들이 순차적으로 의존해서 학습되기 때문에 트리들을 동시에 병렬로 학습할 수 없습니다.
따라서 n_jobs 매개변수(병렬 처리할 CPU 코어 수를 지정하는 매개변수)는 의미가 없으므로 지원되지 않습니다.
히스토그램 기반 그레이디언트 부스팅
히스토그램 기반 그레이디언트 부스팅(Histogram-based Gradient Boosting)은 정형 데이터를 다루는 머시러닝 알고리즘 중에 가장 인기가 높은 알고리즘입니다.
히스토그램 기반 그레이디언트 부스팅은 먼저 입력 특성을 256개의 구간(bin)으로 미리 나눠서, 모든 분할 후보를 직접 검사하지 않고, 빈 단위로만 계산합니다.
따라서 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있습니다.
히스토그램 기반 그레이디언트 부스팅은 256개의 구간 중에서 하나를 떼어 놓고 누락된 값을 위해서 사용합니다.
비유로 쉽게 말하면 256개의 방이 있는데, 그 중 한 방은 ‘결측 손님 전용 방’으로 따로 비워둬서, 손님이 아무 것도 안 가져와도(NaN) 쫓아내지 않고 따로 받아주는 방식이라고 생각하면 됩니다.
따라서 입력에 누락된 특성이 있더라도 이를 따로 전처리할 필요가 없습니다.
HistGradientBoostingClassifier에는 트리의 개수를 지정하는데 n_estimators 대신에 부스팅 반복 횟수를 지정하는 max_iter를 사용합니다.
히스토그램 기반 그레이디언트 부스팅은 자체적으로 특성 중요도를 제공하지 않습니다.
그래서 특성 중요도를 계산하기 위해 permutation_importance()
함수를 사용하겠습니다.
permutation : 순열
이 함수는 특성을 하나씩 랜덤하게 섞어서 모델의 성능이 변화하는지를 관찰하여 어떤 특성이 중요한지를 계산합니다.
permutation_importance()
함수가 반환하는 객체는 반복하여 얻은 특성 중요도(importances), 평균(importances_mean), 표준 변차(importances_std)를 담고 있습니다.
XGBoost 라이브러리
eXtreme Gradient Boosting의 줄임말로 Gradient Boosting을 더 빠르고, 더 똑똑하게 구현한 오픈소스 라이브러리 입니다.
코랩에서 하용할 수 있을 뿐만 아니라 사이킷런의 cross_validate() 함수와 함께 사용할 수도 있습니다.
XGBoost는 다양한 부스팅 알고리즘을 지원하며 tree_method=’his’로 지정하면 히스토그램 기반 그레이디언트 부스팅을 사용할 수 있습니다.
LightGBM 라이브러리
마이크로소프트에서 개발한 Gradient Boosting 기반 라이브러입니다.
이름 그대로 가볍고 빠르다(Light)는 것이 장점이며 다용량 데이터셋, 고차원 특성에서도 훌륭한 성능을 보입니다.
XGBoost VS LightGBM
항목 | XGBoost | LightGBM |
---|---|---|
속도 | 빠름 | 더 빠름 |
트리 성장 방식 | Depth-wise | Leaf-wise |
결측값 처리 | 자동 | 자동 |
범주형 처리 | 수동 인코딩 필요 | 자동 처리 지원 |
메모리 사용 | 보통 | 더 효율적 |
기본 숙제
교차 검증을 그림으로 설명하기
창의성 이슈로 저자님의 강의를 들으면서 필기한 노트를 첨부합니다…
추가 숙제
Ch.05(05-3) 앙상블 모델 손코딩(p.290 ~ 295) 코랩 화면 캡처하기
본문에 첨부해 두었습니다.