[혼공머신러닝+딥러닝] 트리 알고리즘
5.1. Decision Tree
- 로지스틱 회귀로 와인 분류하기
- 결정 트리
- 이해하기 쉬운 결정 트리 모델
5.2. 교차 검증과 그리드 서치
- 검증 세트
- 교차 검증
- 하이퍼파라미터 튜닝
- 최적의 모델을 위한 하이퍼파라미터 탐색
5.3. 트리의 앙상블
- 정형 데이터와 비정형 데이터
- 랜덤 포레스트
- 엑스트라 트리
- 그레이디언트 부스팅
- 히스토그램 기반 그레디언트 부스팅
- 앙상블 학습을 통한 성능 향상
info() > 누락된 값이 있으면 어떻게 하나요?
결측치는 훈련 세트의 mean으로 채우거나 버리거나, 최선은 둘 다 해봐야 압니다.
**훈련 세트의 통계값으로 테스트 세트를 변환한다는 사실을 잊지 마세요**
> 훈련 세트의 평균값으로 테스트 세트의 누락값을 채워야 합니다.
??? 같은 통계 세트로 특성 변환하는 거지 훈련 세트가 영향을 주는 건 아니지 않나???
wine.describe() 를 통해 특성의 스케일이 모두 다르다는 것을 확인했다. 특성 표준화를 위해 StandardScaler 클래스를 이용한다.
회귀 모델에서 적합도
- 회귀 모델에서 적합도는 회귀 모델이 얼마나 잘 생성되었는지 통계적으로 확인하는 방법
- 잔차를 이용한다
- 잔차와 오차의 차이는, 잔차는 모델 추정값과 정답의 차이다.
- 잔차 검정 통계량: 등분산성
- 회귀 모델 적합도 지수에는 R2, F통계량, T통계량이 있다.
- R2 결정계수는 회귀 모형이 데이터를 얼마나 잘 설명하는 지를 나타내며 1에 가까울수록 설명력이 높다.
?? 검정 통계량에서 검정은 뭐지? 적합도 지수에 F 통계량은 검정 통계량이다??
?? 분류 모델이란게 말입니다. Score가 R2라는 건가??
아닙니다. accuracy
linear , multiple linear, ridge, lasso는 연속형 변수 예측 > score로 r2를 사용합니다.
r2를 사용하는 이유는.
보십시오. discrete vs. continuous 변수가 있습니다. 이진 분류 같은 discrete 한 경우에는 accuracy가 사용됩니다. 얼마나 정확하게 예측했나를 0-1로 표현합니다. 선형 회귀에서는 연속형 변수이므로 오차가 중요합니다. 오차도 연속적이기 때문에 MSE나 RMSE, MAE 를 이용하면 오차를 기반으로 모델의 성능을 평가할 수 있다.
- 주택 가격을 예측할 때, 예측 값이 실제 값과 얼마나 차이가 나는지가 중요하지, 차이가 나는 걸 정확도로 평가하는 것은 의미가 없습니다.
- MSE 는 Mean Squared Error 오차의 제곱값의 평균을 나타냅니다. 값이 큰 이상치는 MSE에 큰 영향을 줍니다.
- RMSE (Root Mean Squared Error) MSE의 단점(: 단위 변환)을 보완하고자 MSE에 루트를 씌웠다. 그러나 MSE 기반이기에 이상치에 더 민감하다.
- MAE (Mean Absolute Error) 예측값과 실제값의 절대 오차 평균을 나타낸다. 제곱하지 않기 때문에 큰 오차에 덜 민감하다. 따라서 전체적인 모델의 성능을 평가하고 싶을 때 사용한다.
직관적인 평균 예측 오차를 이해하기 좋다.
Tree Algorithm
노드의 최적 분할을 찾아야 합니다.
- 노드란 결정 트리를 구성하는 핵심 요소입니다. 훈련 데이터의 특성에 대한 테스트를 표현합니다. branch는 테스트 결과 (True, False)를 나타냅니다.
- [ 음성 클래스, 양성 클래스]
- leaf 노드에서 클래스 개수가 많은게 예측 클래스가 된다.
만약 결정 트리를 회귀 문제에 적용하면 leaf node 에 도달한 샘플의 타깃을 평균하여 예측값으로 사용합니다.
plot_tree(dt)
- filled = True는 비율이 높아지면 진한 색을 채워준다.
? max_depth = 1 , 1로 주면 루트 노드를 제외하고 밑으로 한 level만 그린다.
gini (불순도) impurity
0일수록 순수, 1일수록 불순
parent node 와 child node 의 불순도 차이(정보이득 information gain)가 가능한 따라해봐요. 가능한~. 가능한 크도록 트리를 성장시킨다.
- 엥 크도록?? 정보 이득이 클수록 이득이 되니깐요.
- DecisionTreeClassifier 의 criterion 매개변수 기본값이 gini
- criterion 매개변수는 데이터 분할 기준을 정하는 것
- 1 - (양성 비율 제곱 + 음성 비율 제곱)
- 부모 자식간 불순도는 이동한 샘플 계수에 비례하여 더한 후 부모 불순도에서 뺀다.
- 부모 불순도 - (왼쪽 노드 샘플 수 / 부모 샘플 수 ) * 왼쪽 노드 불순도 - (오른쪽 노드 샘플 수 / 부모 샘플 수 ) * 오른쪽 노드 불순도
- criterion은 criterion = 'entropy'를 지정해 엔트로피 불순도를 이용할 수 있습니다.
- 지수가 2인 로
적절하게 가지 치기해주지 않으면 앞서 봤던 것 처럼 과대적합이 나타날 수 있다.
> 일반화가 잘 안될 것 같다. 고 표현합니다.
가지치기 하는 방법: 트리의 최대 깊이 정하기 max_depth
불순도를 가지고 샘플을 나눴습니다. 불순도는 클래스 비율을 가지고 계산했죠.
샘플을 어떤 클래스 비율로 나누는 지 계산할 때 특성값의 스케일이 계산을 영향을 줄까요? 아니요
특성값의 스케일은 결정 트리 알고리즘에 아무런 영향을 미치지 않습니다.
즉, 결정 트리는 표준화 전처리 과정이 필요없습니다.
비율이라서 그런거겠져?
결정 트리는 어떤 특성이 가장 유용한지 나타내는 특성 중요도를 계산해줍니다.
- root node에서 suger를 특성으로 사용했기 때문에 sugar라고 유추할 수 있다.
- https://github.com/Ahranah/ahranah.github.io/blob/master/Tree5.1.ipynb
ahranah.github.io/Tree5.1.ipynb at master · Ahranah/ahranah.github.io
2024/khuda/ML. Contribute to Ahranah/ahranah.github.io development by creating an account on GitHub.
github.com
정리
결정 트리: 보통은 모델 계수와 절편을 설명하기 어렵지만 결정 트리는 예/아니오 직관적이므로 설명하기 쉽다.
불순도: 결정 트리가 최적의 질문을 찾기 위한 기준
정보 이득: 자식과 부모 간 불순도 차이가 크면 좋다.
가지치기: 훈련 모델의 깊이가 깊으면 과대적합이 나타날 수 있으므로 max_depth를 설정한다. 기본값은 None
leaf node가 순수(불순도 0) 하거나 min_samples_split 보다 샘플 수가 적을 때까지 성장
특성 중요도: 결정 트리에 사용된 특성이 불순도 감소에 기여한 정도를 나타낸다. = 영향력있는 특성을 고른다.
5.2 교차 검증과 그리드 서치
검증 세트 Validation set : 테스트 세트를 사용하지 않고도 과소/과대 적합을 파악할 수 있는 방법
max_depth 매개변수를 사용한 하이퍼파라미터 튜닝 방법.
훈련 세트를 나눠서 검증 세트를 만든다.
그런데 훈련 세트는 많을 수록 모델 학습에 도움이 된다. 따라서 검증 세트를 떼어 놓는 위치를 바꿔가면서 훈련 세트가 모두 학습 데이터로 사용될 수 있도록 해보자.
교차 검증 cross validation _ K-fold cross validation
교차 검증으로 검증 점수의 최상을 가늠할 수 있다.
- print(np.mean(scores['test_score']))
사이킷런의 cross_validate()는 훈련 세트를 섞어서 fold를 나누지 않는다. <> train_test_split()
따라서 훈련 세트를 섞으려면 splitter를 지정해야 한다.
이어서 결정 트리의 매개변수 값을 바꿔가며 가장 좋은 성능이 나오는 모델을 찾아보겠스빈다. 테스트 세트를 사용하지 않고 교차 검증을 통해 좋은 모델을 고르면 되겠죠???
하이퍼 파라미터 튜닝
- 모델 파라미터: 모델이 학습하는 파라미터
- 하이퍼 파라미터: 사용자 지정
- AutoML: 사람 개입 없이 하이퍼 파라미터 튜닝을 자동으로 하는 기술
예를 들어, 최적의 max_depth를 찾았을 때 min_samples_split를 바꿔가며 최적의 값을 찾고 있었다. 이러면 안된다. 불행하게도 두 매개변수는 동시에 바꿔가며 최적의 값을 찾아야 한다.
매개변수들을 동시에 바꿔가며 최적의 값을 찾기 위해 Grid Search를 이용한다.
GridSearchCV() 는 교차검증도 한 번에 수행한다.
- 탐색할 매개변수를 정한다.
- 훈련 세트에서 그리드 서치로 검증 점수 1등의 매개변수 조합을 찾는다. 이 조합은 그리드 서치에 저장된다.
- gs.best_params_
- best_index = np.argmax(gs.cv_results_['mean_test_score'])
print(gs.cv_results_['params'][best_index]) - gs.best_estimator_
- 그리드 서치는 best_estimator_ 에서 교차 검증 훈련 세트가 아닌 전체 훈련 세트를 사용해 최종 모델을 훈렵합니다. 이 모델도 그리드 서치 객체에 저장됩니다.
Grid Search
- 하이퍼파라미터 탐색을 자동화해 주는 도구입니다. 탐색할 매개변수를 나열하면 교차검증을 수행해 가장 놓은 검증 점수의 매개변수 조합을 선택합니다. 마지막으로 이 매개벼수 조합으로 최종 모델을 훈련합니다.
Random Search
매개변수 값 변경을 자동으로 해주는 라이브러리 _ 난수 발생기 > scipy 이용
- uniform : 실숫값, randint: 정수
https://github.com/Ahranah/ahranah.github.io/blob/master/Tree5.2.ipynb
ahranah.github.io/Tree5.2.ipynb at master · Ahranah/ahranah.github.io
2024/khuda/ML. Contribute to Ahranah/ahranah.github.io development by creating an account on GitHub.
github.com
5.3. 트리의 앙상블_ Random Forest
가장 좋은 알고리즘이 있다고 해서 문제마다 최적화되는 알고리즘이 다를 수 있기에 어떤 알고리즘이 더 뛰어나다고 미리 판단해서는 안 됩니다.
정형 데이터와 비정형 데이터
- 정형 데이터
Ensemble learning은 정형 데이터 다루는 데 가장 뛰어난 성과를 낸다. - 비정형 데이터 - 구조적이지 않은 데이터 저장에는 NoSQL 등이 있다. csv에 담기 어려운 텍스트나 JSON 데이터 저장에 용이하다.
신경망 알고리즘을 이용한다.
Ensemble learning
Random Forest, Extra Tree, Gradient Boosting, HistGradientBoosting
Random Forest 가 Decision Tree 보다 특성을 무작위 추출(중복)하므로 과대적합에 강하고, 강한 일반화 성능을 보인다.
Extra Tree과 Random Forest의 차이점
- 특성(노드) 분할이 무작위로 이뤄진다.
- 샘플로 전체 훈련 세트를 이용한다.
- Random Forest 보다 빠르고, 과대적합에 강하다.
Gradient Boosting은 깊이가 낮은 Tree를 여러 개 이용하는 것이다. 과대적합에 매우 강하고, 매우 강한 일반화성능을 보인다. Gradient 에서 유추하듯이 모델의 가중치와 절편을 조정해 경사를 조절하던 SGD와 유사하게, 트리를 추가하면서 손실 함수의 낮은 곳으로 천천히 이동한다. > 손실함수 최소화
- 천천히 이동하기 위해 학습률 매개변수(learning_rate)로 속도를 조절한다.
- SGD에서 손실함수의 낮은 곳으로 천천히 이동했다. loss function은 모델의 예측값과 실제값의 차이를 측정하는 함수로 작을 수록 좋다.
- 순서대로 트리를 추가하기에 속도가 느리나 성능이 좋다.
Gradient Boosting의 속도를 개선한 HistGradientBoosting이 있다.
랜덤 포레스트_RandomForest
샘플 추출: Bootstrap sample: 복원 추출로 샘플을 중복해서 뽑는 것을 허용한다. 샘플 추출로 사용되지 않은 특성은 OOB(Out of bag) 샘플이라고 하고 검증 세트의 역할로 사용한다.
- 분류 모델_RandomForestClassifier은 전체 특성 수의 제곱근한 수만큼만 특성을 이용한다.
- 각 트리의 클래스별 확률을 평균하여 가장 높은 확률을 가진 클래스를 예측으로 삼는다.
- 회귀 모델_RandomForestRegressor은 전체 특성을 사용한다.
- 각 트리의 예측을 평균한다.
랜덤 포레스트 모델과 Decision Tree를 비교해보면, 랜덤하게 샘플 추출한 결과, 특성 하나에 과도하게 집중하지 않기 때문에 다양한 특성이 훈련할 기회를 가진다. 이는 과대적합을 줄이고 일반화 성능을 높이는 결과를 낳는다.
oob sample 을 검증 세트처럼 사용하기 위해 RandomForestClassifier(oob_score = True)를 설정한다.
# 랜덤 포레스트
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)
rt.fit(train_input, train_target)
print(rf.oob_scores_)
- n_estimators 는 앙상블 구성할 트리의 개수, 기본 100개
- criterion 로 불순도 함수 설정
- max_depth
- min_samples_split 노드를 나누기 위한 최소 샘플 개수, 기본 2개
- max_features 최적의 분할을 위해 탐색할 특성 개수
Extra Tree
Random Forest 와 차이점은 샘플 추출법이다. Bootstrap을 사용하는 랜덤 포레스트와 달리 전체 훈련 세트를 사용하다. 노드 분할에도 최적 분할이 아닌 무작위 분할을 이용한다.
트리가 여러 개라서 random하게 특성을 분할해도 과대 적합을 막고 검증 세트의 점수를 높이는 효과가 있다. 또한 노드 분할이 랜덤하기에 계산 속도가 빠르다는 장점이 있다.
- DecisionTreeClassifier 의 splitter 매개변수 'random'과 같은 설정이다. (splitter = 'random')
- 결정 트리는 최적 분할 찾는 데 시간 소모가 길다. 특성이 많을 수록 더 길기 때문에 무작위로 노드 분할하면 트리 구성이 빨라진다.
# Extra Tree
from sklearn.ensemble import ExtraTreeClassifier
et = ExtraTreesClassifier(n_jobs = -1)
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_)
Gradient Boosting
subsample 은 트리 훈련에 사용할 훈련 세트의 비율을 정하는 매개변수다.
= 경사하강법 단계마다 일부 샘플을 랜덤하게 선택하는 SGD나 미니배치 경사하강법과 유사
- GradientBoostingClassifier
- GradientBoostingRegressor
# Gradient Boosting
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier()
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_)
- loss = log_loss = deviance
- learning_rate 트리가 앙상블에 기여하는 정도, 기본값 0.1
- n_estimators 부스팅 단계를 수행하는 트리의 개수, 기본 100개
- subsample로 사용할 훈련 세트의 샘플 비율 정한다.
Histogram-based Gradient Boosting
Gradient Boosting의 느린 속도를 보완하기 위한 방법으로 정형 데이터 머신러닝 알고리즘 중에 가장 인기가 높다.
- 훈련데이터(입력 특성)을 256 구간으로 나누고 시작하기에 노드 분할 시 최적 분할 찾는 속도가 매우 빠르다.
- LightGBM, XGBoost
# Histogram gradient boosting
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradeintBoostingClassifier
hgb = HistGradientBoostingClassifier()
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']))
hgb.fit(train_input, train_target)
print(hgb.feature_importances_)
hgb.score(test_input, test_target)
# XGBoost
from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method = 'hist')
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']))
# LightGBM
from lightgbm import LGBMClassifier
lgb = LGBMClassifier()
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']))
- learning_rate 학습률(감쇠율), 기본값 0.1이고 1.0이면 감쇠가 전혀 없다.
- max_iter 부스팅을 수행하는 트리의 개수
- max_bins 입력 데이터를 나눌 구간의 수, 기본 255(최대)