본문 바로가기
딥러닝

[딥러닝 논문 리뷰] Entity Embeddings of Categorical Variables

by 미스터탁 2018. 4. 8.

이번에 포스팅할 논문은 Entity Embeddings of Categorical Variables 이라는 논문인데 2016년 4월에 Arxiv에 올라왔습니다. 아직까지는 인용수 7회에 그치고있지만, 개인적인 생각이지만 조만간 뜰 것(??) 같은 논문입니다. 

최근 수년간 계속 딥러닝이 발전해오고 있다는 사실은 누구도 부정할 수 없습니다. Classification, Detection, Captioning, Generation, 강화학습까지 딥러닝이 많은 분야에서 활용 되고 있습니다. 그러나 Classification 분야에서 이미지 또는 텍스트를 제외한 일반적인  분야에서는 딥러닝이 엄청 잘 먹히는 것은 아닙니다. 이는 Kaggle대회의 수상자들의 알고리즘만 봐도 알 수 있죠. 대부분 Xgboost, LightGBM등 Gradient Boosting계열 알고리즘들이 수상하였습니다. (빅콘테스트와 같은 국내 데이터 분석 대회도 마찬가지 입니다.). 딥러닝이 일반적인 classification 문제에 잘 맞지 않다라는 것은, 경험적으로 알고 있었지만 그 이유에 대해서는 잘 알지 못했습니다. 본 논문에서는 그 이유에 대해서 Neural Network (NN)는 기본적으로 Input node들의 연속성을 가정한다로 얘기하고 있습니다. 즉 일반적인 Classification에 들어간느 범주형(Categorical) 변수들이 NN에서는 학습이 잘 되지 않는 다는 것이죠. 반면 Tree모델을 기본으로 사용하는 Boosting이나 Randomforest의 같은 경우, 범주형에 대해서 잘 분리(split)하기 때문에 범주형 변수가 들어갔을 경우 NN에 비해 성능이 더 잘 나온다는 것입니다. 논문의 저자들은 Kaggle의 Rossman대회 (https://www.kaggle.com/c/rossmann-store-sales) 에서 이 기법을 적용하여 3위를 기록 했다고합니다.

 

 

본 논문에서 이 Categorical 변수 들을 Embedding 시켜 NN의 Input으로 사용 (또는 다른 Boosting등과 같은 모델에 사용)하여 더 좋은 성능을 내도록 하고 싶은것입니다. 일반적으로 Categorical 변수들을 data의 input으로 넣기 위해서는 아래 그림처럼 One-hot encoding 방식으로 바꿔주어야 합니다. 하지만 이럴경우, input data의 dimension이 과하게 커질 수 있고, 학습속도와 효율성 또한 저하될 수가 있습니다. 논문에서는 Categorical 변수들을 embedding 시켜 차원 축소 효과를 볼 수 있다고 서술하고 있습니다. 또한, "월요일"과 "화요일"은 가깝고 "월요일"과 "목요일"은 "화요일"에 비해 조금 더 멀다는 것을 알 수 있습니다. 그러나 Categorical 변수들을 embedding 시키면 마치 word2vec space에서 단어들의 거리를 구할 수 있듯이 여기서도 embedding된 범주들의 유사성을 파악할 수 있습니다. 즉 그 유사성을 학습모델에 반영시킬수 있다는 장점이 있습니다.

 

 

 

 

 

논문에서 제안하는 NN의 구조는 매우 간단합니다. 우선 각 범주형 변수들을 One-hot encoding으로 변환 시킨다음에, NN의 input으로 독립적으로 들어가게 됩니다. 아래 그림에서 볼 수 있듯이, encoding된 input들이 NN에 독립적으로 들어가게 되고 Hidden layer를 통해 나온 값들을 concat시켜 Fully connected layer에 들어가게 됩니다. 이 concat 시킨 값들이 일반적인 DNN의 input으로 들어간다고 이해하시면 됩니다. 그리고 Ouput은 1 또는 0이 됩니다. 어떤 특정 데이터의 encoding 값들이 들어가서 그 해당 데이터의 Y값을 예측하는 NN라고 이해하시면 됩니다. rossman데이터의 경우 Y값이 sales양이지만 저자들은 log-scale을 통해서 1-0으로 변환시켰고, output layer의 activation function은 sigmoid를 사용 하였습니다. 저자의 코드는 git에서 확인 할 수 있습니다.(https://github.com/entron/entity-embedding-rossmann)

 

 

 

사실 학습하는 구조는 Word2vec과 비슷합니다. word2vec또 input이 one-hot encoding vector입니다. 그리고 그 wor에 해당하는 Weight Matrix 의 vector값이 그 word를 representation하는 vector로서 사용 되죠. 여기서도 마찬가지 입니다. 각 one-hot encoding vector와 matching되는 Weight Matrix의 vector가 그 범주(예를들어가 월화수목금토일 중 월요일)를 representation 하는 vector가 되는 것입니다. word2vec은 주변 단어로 target(CBOW의 경우) word를 잘 설명할 수 있게 끔 학습을 하는 것이라면, 이 논문의 경우 각 범주들이 Target 데이터를 잘 구별 할 수 있게 끔 학습시키는 것입니다. 

 

학습이 완료된 이후, Embedding 된 vector들을 독립변수로 사용할때에는 해당 범주에 해당하는 Weigt matrix의 vector를 사용하시면 됩니다.

 

Rossman데이터의 범주형 변수들을 embedding 시킬 때, 그 embedding의 차원 수는 아래와 같습니다. embedding의 차원수를 구하는 적절한 공식은 따로 있지는 않습니다. 

 

 

 

 

categorical 변수들을 embedding시킨 것과 그렇지 않은 (one-hot encoding을 사용한) 변수들을 여러 모델에 실험 한 결과 아래와 같은 결과가 나왔다고 합니다. 위/아래 두 table의 차이는 데이터를 random하게 섞었는냐, 시간 순서대로 분리했느냐의 차이입니다. 대부분의 실험결과에서 embedding 시킨 모델이 더 좋은 결과를 보이고 있습니다. 특이한 건 embedding 시킨 다 하더라도 Neural network에 대해서는 성능 향상이 그리 크지는 않네요. 여기서도 Tree기반 알고리즘은 randomforest나 Gradient boosting알고리즘이 높은 성능을 기록하고 있습니다. 

 

 

 

여기서 매우 놀라운 점은, 지역변수들을 embedding 시킨 이후, t-sne로 차원축소 후 plotting시킨 결과 실제 지역과 유사한 관계가 나왔다는 것입니다. (사실 이부분에서는 조금 의문이 남긴합니다. t-sne자체가 일반적으로 할때마다 조금씩 다른 결가 나오기 때문에 저자들이 잘 된다는 것을 보이기 위해 여러번 돌리고 가장 그럴듯 한 걸 논문에 실은 건 아닐까 싶습니다. 어쨌든 매우 흥미로운 결과가 나온건 부정할 수 없는 사실이죠 )

 

 

 

 

 

 

본 논문에서는 사실 rossman데이터에 대해서만 실험한 것 이기 때문에, 좀 더 다양한 실험 결과가 필요할것 같습니다. 이 알고리즘을 R로 구현하여 2017 빅콘테스트 데이터에 대해서 적용해봤는데. 조금 애매한 결과가 나왔습니다. One-hot encoding feature로 했을 때 보다 F-measure가 2% 정도 높게 나왔습니다. (Class Imbalanced 상황의 데이터라 성능지표를 F-measure로 가져갔습니다). 그런데 overfitting이 되면(epoch기준 3이상) 오히려 성능이 더 떨어지는 결과가 나왔고, embedding 된 데이터들을 oversampling시킨다면 성능이 그닥 좋지 않게 나왔습니다. 앞서 서술한 것과 같이 class imbalance상황 이다 보니, SMOTE나 DBSMOTE와 같은 oversampling 기법들을 적용하면 성능 향상을 가져올 수 있습니다. 그런데 Embedding 된 데이터들을 oversampling시키면 오히려 성능이 떨어지게 됩니다. 즉 one-hot encoding + SMOTE > Entitiy Embedding > Entitiy Embedding +SMOTE 인 상황 입니다. Oversampling의 특성상 Minority 데이터들의 거리를 구해 그 거리 사이에 random하게 데이터를 채워 넣게 되는데, embedding된 데이터들은 채우는게 아니라 그대로 가져가야하지 않나 싶습니다. 좀더 실험과 연구가 필요할 것 같습니다.

 

 

 

 

[PyTorch] 쉽고 빠르게 배우는 딥러닝(할인쿠폰코드) 369-7c698142f82e

https://www.inflearn.com/course/PyTorch-%EB%94%A5%EB%9F%AC%EB%8B%9D

 

 

 

반응형

댓글