- column 수가 2881개
- 결측치가 많다
- 정형 데이터
해당 데이터에 가장 적합한 ML 모델을 선정하기 위해 성능이 좋은 3가지 ML 모델들을 비교해보고자 한다.
그 전에 기본적인 트리기반 분류 알고리즘 먼저 짚고 넘어간다.
- 결정 트리 Decision Tree
- 랜덤 포레스트 Random Forest
- 그래디언트 부스팅 Gradient Boosting Machine GBM
결정 트리는 분류(Classification)와 회귀(Regression) 모두 가능한 지도 학습 모델이다. 이러한 결정 트리는 과적합될 가능성이 크다.
이러한 결정 트리를 앙상블의 한 종류인 배깅 방식으로 개선시킨 것이 랜덤 포레스트(Random Forest) 이다.
또한, 결정 트리를 앙상블의 한 종류인 부스팅 방식으로 개선시킨 것이 그래디언트 부스팅 (Gradient Boosting Machine)이라고 한다.
랜덤 포레스트와 다르게 그래디언트 부스팅 모델은 순차적으로 트리를 개선해나가는 모델이기 때문에 파라미터에 민감하지만, 잘 조정하면 랜덤 포레스트보다 더 높은 정확도를 제공할 수 있고, 변형된 최신 알고리즘들은 훨씬 빠른 속도를 보여준다.
이와 같은 그래디언트 부스팅을 변형한 최신 알고리즘은 대표적으로 XGBoost, lightGBM, CatBoost 등이 있다.
image나 text와 같은 비정형데이터에서는 인공 신경망(NN) 모델이 압도적인 성능을 보이고 있지만, 정를데이터에서는 XGBoost와 같은 트리 기반 알고리즘이 현재까지는 가장 좋은 알고리즘으로 평가받는다.
GBM을 발전시킨 트리 기반의 앙상블 모델이다.
아래와 같이 발전해왔다.
아래와 같은 기능을 통해 최적화된 GBM이라고 보면 된다.
- 시스템 최적화
- 병렬 처리 (Parallel Processing)
- 가지 치기 (Tree-Pruning)
- 하드웨어 최적화
- 알고리즘 강화
- 결측치 처리
- 과적합/편향을 피하기 위한 정규화
- 분산 가중치 분위수 스케치 알고리즘 (Weighted Quantile Sketch)
- built-in된 cross-validation
여러 개의 트리가 순차적으로 구축되어 최종 모델을 만드는데, 하나의 트리를 구축하기 위해서는 2개의 루프가 필요하다.
- 리프노드를 나열하는 바깥쪽 루프
- feature를 계산하는 안쪽 루프
안쪽 루프의 계산이 끝나지 않으면 바깥쪽 루프가 시작될 수 없는 구조였고, 이를 해결하기 위해 전체 데이터셋을 전역적으로 스캔하고, 이를 병렬 스레드를 사용하여 모든 트리의 안쪽 루프가 동시에 병렬로 실행될 수 있게 한다. 따라서 병렬화를 통해 모델의 학습 속도를 향상시킬 수 있다.
GBM 프레임워크 내에서 트리 분할의 중지 기준은 그리디하게(지금 당장의 최적의 해를 구한다는 의미) 동작하고, 현재 단계에서의 가장 높은 정보 획득(information gain)이나 가장 작은 손실을 가진 분할을 우선적으로 선택한다.
XGBoost는 손실함수의 값이 감소하지 않거나, 증가가 미미한 경우에 트리 성장을 중지시킨다.
XGBoost는 'max_depth' 파라미터를 지정해 트리의 최대 깊이를 제한한다. XGBoost에서는 max_depth 파라미터를 먼저 적용하고 나서, 그 이후에 가지치기할 때 노드에서 손실함수를 먼저 계산하고 그 값에 기반하여 가지치기 여부를 결정한다. 이 때 가지치기는 리프노드에서 루트노드로 역방향 진행된다. 이는 트리를 최대한 깊게 성장시켜 초기에 가능한 한 많은 규칙을 학습하고 다양한 패턴을 포착하기 위함이다.
이 알고리즘은 하드웨어 리소스를 효율적으로 활용하도록 설계되었다. 각 스레드에 할당된 내부 버퍼는 캐시 메모리에 적합한 크기로 조절되어 메모리 접근 속도를 향상시킬 수 있고, 서로 다른 스레드 간의 메모리 충돌이 최소화된다.(병렬처리에도 용이) 메모리에 맞지 않는 큰 데이터 프레임을 처리하면서 디스크의 공간을 활용하여 병렬처리를 수행하는 외부 코어 컴퓨팅 방식을 사용한다. 데이터를 메모리에 모두 로드하는 대신 필요한 부분만을 메모리에 유지하고 나머지는 디스크에 저장된 채로 둔다.
보다 복잡한 모델에 LASSO(L1)과 Ridge(L2) 정규화를 통해 페널티를 준다.
또한, XGBoost는 early stopping 기능으로 모델이 검증 데이터에서 일반화 성능이 향상되지 않을 때 학습을 중단시킬 수 있다.
XGBoost는 학습 손실에 따라 자동으로 최적의 결측값을 학습하며, 데이터의 다양한 희소성 패턴을 더 효과적으로 처리한다. 즉, 결측치가 많은 feature에 대해서도 뛰어난 성능을 보이도록 설계되어 있다.
가중치가 적용된 데이터셋에서 최적의 분할 지점을 효과적으로 찾기 위해 사용하는 알고리즘이다. 각 데이터 포인트에 가중치를 부여하여 데이터셋을 요약 표현하는데, 이 때 각 분위수(quantile)에 해당하는 값을 찾아내어 최적의 분할 지점을 결정한다.
각 iteration에서 내장된 교차 검증 방법을 제공하여 모델이 학습할 때 모델의 성능을 평가할 수 있고, 하이퍼 파라미터 튜닝을 보다 편리하게 할 수 있도록 지원한다.
과적합 방지를 위한 파라미터 조정 방법
- eta 낮추기 (반대로 num_boost_round/n_estimators는 높여주기)
- max_depth 낮추기
- min_child_weight 높이기
- gamma 높이기
- subs_ample, colsample_bytree 낮추기
params = {'max_depth':[6, 7, 8], #일반적으로 3~10
'subsample':[0.75, 0.8, 0.85], #일반적으로 0.5 ~ 1
'learning_rate':[0.12, 0.15], #일반적으로 0.01 ~ 0.2
'min_child_weight':[3, 4], #1보다 샘플수작으면 leaf node 너무 크게 설정하면 언더피팅
'reg_lambda': [1], #default 1, L2 규제
'reg_alpha' : [0], #default 0, L1 규제
'min_split_loss':[0.05, 0.1, 0.15], #범위 0~무한대
'colsample_bytree':[0.7,0.8]} #일반적으로 0~1
XGBoost는 이전 GBM보다 성능은 좋아졌지만, 여전히 학습 속도가 느리다는 단점이 있다.
LightGBM은 이러한 단점을 보완하기 위해 나왔다.
XGBoost 및 여러 다른 부스팅 모델들과 LightGBM의 차이점은 리프 노드(leaf node)를 중심으로 트리 분할을 한다는 점이다.
level-wise(균형 트리 분할) : 트리를 균형 있게 성장시키는 방식으로 한 번의 분할 마다 모든 리프 노드의 깊이가 동일하게 증가한다. 균형을 잡아주어야 하기에 트리의 깊이가 줄어들고 대규모 데이터셋에서는 계산 비용이 증가할 수 있다.
leaf-wise(리프 중심 트리 분할) : 가장 손실이 큰 리프 노드부터 성장시키는 방식으로, 더 나은 학습을 위해 더 깊은 트리를 생성한다. 전체 적인 트리 균형을 맞추지 않고, 손실 감소에 집중하여 계산 비용을 낮출 수 있다. 단, 데이터가 작을 경우에는 level-wise 방식보다 더 많은 과적합의 위험이 있을 수 있다.
또한, XGBoost에서는 범주형 변수를 처리하기 위해서 미리 one-hot 인코딩이나 정수 인코딩을 해주어야 하지만, LightGBM은 내장된 범주형 변수 지원 기능으로, 별도의 인코딩 없이도 효과적으로 다룰 수 있다.
이와 같은 특징들로 미루어 보아, 대규모 데이터셋을 학습시킬 때에는 LightGBM을 사용하고, 균형 잡힌 트리가 필요하거나 작은 데이터셋을 학습시킬 때에는 XGBoost를 사용하는 것이 좋다.
과적합을 해결하고 싶을 때
- 작은 max_bin 값 사용하기
- 작은 num_leaves 값 사용하기
- min_data_in_leaf 와 min_sum_hessian_in_leaf 파라미터 사용하기
- bagging_fraction 과 bagging_freq 을 사용하여 bagging 적용하기
- feature_fraction을 세팅하여 feature sub-sampling 하기
- lambda_l1, lambda_l2 그리고 min_gain_to_split 파라미터를 이용해 regularization (정규화) 적용하기
- max_depth 를 설정해 Deep Tree 가 만들어지는 것을 방지하기
[출처] https://nurilee.com/2020/04/03/lightgbm-definition-parameter-tuning/
[출처] https://dlforbi.tistory.com/3
[출처] https://velog.io/@lyndis20/Gradient-Boosting-ModelXGBoost-LightGBM-Catboost
CatBoost의 약자는 Categorical Boosting이다. 이름처럼 범주형 변수를 처리하는 데 중점을 둔 알고리즘이다.
CatBoost는 범주형 변수를 인코딩 하기 위해 Ordinal Encoding과 Target Encoding의 조합을 사용한다.
- Ordinal Encoding(순서형 인코딩):
범주형 변수의 각 카테고리에 대해 고유한 정수 값을 할당한다. 이는 각 카테고리 간에 상대적인 순서를 나타낸다. 예를 들어, 딸기 : 1, 사과 : 2, 바나나 : 3 으로 인코딩할 수 있다.
- Target Encoding:
범주형 변수를 인코딩할 때 해당 범주의 타겟 변수의 평균값을 사용한다. 해당 범주의 타겟에 대한 정보를 효과적으로 모델에 전달할 수 있다.
예시) 여기서 '성별' 변수를 타겟 인코딩으로 인코딩하려면 각 범주('남성', '여성')에 대해 해당 범주에 속하는 사람들의 타겟 변수의 평균값을 계산합니다.
'남성'의 경우: (1 + 0 + 1) / 3 = 0.67
'여성'의 경우: (0 + 1 + 0) / 3 = 0.33
따라서, '남성'은 0.67로, '여성'은 0.33으로 인코딩된다.
- 자동 규제 및 최적의 파라미터 선택
CatBoost에는 모델 훈련 시 학습률 등과 같은 여러 하이퍼파라미터를 자동으로 조절하는 기능이 내장되어 있다.
- 병렬처리 및 GPU 지원
대용량 데이터셋에서 빠른 학습을 지원하는 데 도움이 된다.
따라서, CatBoost 모델은 대규모 데이터셋을 사용하거나 범주형 변수가 많은 데이터셋에서 효과적으로 사용할 수 있다.
SmartFactory 제품 품질 분류 AI 경진대회에서 주어진 데이터에 적합한 모델로는 XGBoost라고 생각한다.
일반적으로 성능은 CatBoost, LightGBM, XGBoost 순으로 좋다고 알려져 있지만,
2881개의 column 수에 비해 데이터는 대략 500개 가량으로, 데이터 양이 부족한 상태이기 때문에 LightGBM보다는 XGBoost가 더 적합하다고 생각했고,
2881개의 feature중 2875개는 수치형 변수이기 때문에 범주형 변수 개수가 적고, 실제로 학습에 사용되는 범주형 변수는 2가지이기 때문에 CatBoost를 사용한다고 해서 XGBoost보다 성능이 크게 높아질 것 같지 않기 때문이다.
(추가)
CatBoost 또한 내부에서 결측치 처리를 해주기 때문에 결측치 처리하기 애매한 경우, 쓰기 용이하며, 굳이 대규모 데이터셋이 아니더라도 사용하기 좋다고 한다.
그래서 기대를 가지고 CatBoost로 학습시켰지만,,,아무래도 데이터가 많이 적은가보다,,,파라미터 튜닝을 많이 안해도 괜찮은 성능이 나올 것이라 생각했지만, 파라미터 튜닝을 열심히 했음에도 과적합이 계속 일어났다.