본문 바로가기

머신러닝

LightGBM에서의 범주형 처리 변수(Categorical feature in LightGBM)

 

LightGBM은 2016년 12월 1일에 공개된 머신러닝 기법이다.
 
https://github.com/Microsoft/LightGBM 와

 

https://lightgbm.readthedocs.io/en/latest/ 

 

를 참고하면 대부분의 코딩은 할 수 있을 것이다.
 
LightGBM의 장점으로는 성능도 있지만 무엇보다 빠르다! 

 

Xgboost만 사용하다가 LightGBM을 처음 사용했을때는 속도면에서 무척 놀랐다.
 

 

또 하나의 특징으로는 Xgboost를 R에서 사용할때는 상관 없지만 Python에서 사용할때는 

 

범주형 변수들을 (Object나 Category로 되어 있는 변수) 숫자형 변수로 바꿔줘야 한다.

 

그 방법으로 가장 많이 사용하는 것이 원핫인코딩이다. 
 
트리 모델에서 high cardinality categorical features(범주의 갯수가 많은 변수)를 원핫인코딩하여 넣게 되면 트리가 언밸런스 해지고, 좋은 성능을 내기 위해 트리가 더 깊어진다고 한다. 즉 훈련시키는데도 시간이 더 소요되고, 과적합될 위험도 있다는 의미이다.
 
이 경우 원핫인코딩보다 더 유용한 방법이, 범주형 변수를 2개의 subset으로 잘 나누는것이라고 한다. 클래스를 분류하는데 가장 이득을 많이 줄 수 있는 방법으로 이분화를 시킨다는 는 의미이다. 이렇게 되면 속도도 빨라지고 성능도 더 좋아진다고 한다.

(참고 : https://github.com/Microsoft/LightGBM/blob/master/docs/Features.rst#optimal-split-for-categorical-features)

 

어쨌든 python에서 코딩하는 방법은, 범주형 변수의 type을 category로 지정만 해주면 모델이 알아서 처리해준다. 

 

실제로 원핫인코딩을 했을때 보다 단순히 카테고리 변수로 모델을 훈련시켰을때 성능이

더 좋아지는지를 확인해보았다.

 

 

연습으로 사용한 데이터는 Kaggle의 Titanic 데이터 이다.

이미 다른 전처리나 변수 만들기는 끝난 상태이다.

모델링은 5-fold cross validation을 통해서 했고,

모델의 성능 지표는 정확도 였다.

 

먼저 원핫인코딩을 통해 처리했을때의 경우이다.

cat_features에 범주형 변수들의 이름을 넣고 원핫인코딩 했다.

 


cat_features = ['Sex','Cabin','Embarked','Title']

for column in cat_features:
	temp = pd.get_dummies(pd.Series(Train[column]))
	Train = pd.concat([Train,temp],axis=1)
	Train = Train.drop([column],axis=1)
    
for column in cat_features:
	temp = pd.get_dummies(pd.Series(Test[column]))
	Test = pd.concat([Test,temp],axis=1)
	Test = Test.drop([column],axis=1)

 

 


#one-hot encoding
Lgb = LGBMClassifier(boosting_type='gbdt',random_state =94,colsample_bytree=0.9,max_depth=5,subsample=0.9,n_estimators=80)
Accuracy for full training set:
0.82379349046
Lgb = LGBMClassifier(boosting_type='gbdt',random_state =94,n_estimators=80)
Accuracy for full training set:
0.829405162738

 

결과에서 위는 Hyperparameter Tuning을 통해 파라메터 몇개를 지정해준것이고 

아래의 결과는 기본 파라메터로 나온 결과 값이다.

 

다음은 LightGBM에서 알아서 처리하도록 원핫인코딩을 하지 않았을때의 경우이다.

type이 기존엔 object였으나 category로 만들어주었다.

 


cat_features = ['Sex','Cabin','Embarked','Title']

for i in enumerate (cat_features) :
    ca = i[1]
    Train[ca] = Train[ca].astype('category')
    Test[ca] = Test[ca].astype('category')

 

 


#no one-hot encoding
Lgb = LGBMClassifier(boosting_type='gbdt',random_state =94,colsample_bytree=0.9,max_depth=5,subsample=0.9,n_estimators=80)
Accuracy for full training set:
0.835016835017
Lgb = LGBMClassifier(boosting_type='gbdt',random_state =94,n_estimators=80)
Accuracy for full training set:
0.833894500561

 

원핫인코딩을 했을때보다 안했을때의 정확도가 두모델 다 높다

 

실제 Kaggle에서 결과제출을 했을때도 원핫인코딩을 안한 모델의 정확도가 더 높게 나왔다

 

물론 모든 경우에 위와 같은 결과가 나오라는 보장은 없다. 규모가 훨씬 크거나 

종류가 다른 데이터에서는 다른 결과가 나올 수도 있긴 하지만, 

high cardinality categorical features를 처리할때는 

LightGBM 알고리즘을 사용하는 것이 괜찮은 방법일 듯 하다.