본문 바로가기

머신러닝/[기타]

비-수학적 특성 공학(Non-Mathematical Feature Engineering )

앞서 특성 선택(Feature Selection)에 대한 글을 적은 적이 있는데, 막상 특성 선택 방법론 몇 가지 아는 것으로는 모델을 개선하는데 드라마틱한 결과를 얻어내는 것이 쉽지 않았습니다. 더군다나 RNN처럼 복잡한 모델의 경우에는 더더욱 앞의 방법론 대부분이 무의미합니다. 그렇다고 더이상 데이터를 정제할 방법이 없는 것이 아니겠지요. 특성을 다듬고, 선택(Selection)하고, 스케일링(Scaling)하고, 추출(Extraction)하는 것이 결국 특성 공학(Feature Engineering)의 완성입니다. 이번에는 특성을 비수학적인 방법으로 다듬는 방법에 대해 소개합니다.

특성 공학이란?

 사실 대부분의 경우에 있어서, 그저 존재하던 날 것의 데이터를 그대로 모델에 주입시켜 학습한다고 좋은 정확도가 나오는 경우는 없습니다. 적어도 최고의 정확도는 아니죠. 우리는 항상 모델을 저능아 정도로 바라봐야합니다. 데이터 좀 던져주고 알아서 배워라 하는 것이 아니라, 잘 이해할 수 있게끔 최대한 깔끔한 학습자료를 줘야한단거죠. 그러기 위해서는 모델이 데이터를 읽기전, 우리가 먼저 데이터를 보고(EDA), 파악한 결과를 바탕으로 데이터를 정제하는 것이 필요하고, 이게 바로 특성 공학입니다. 머신러닝 분야에서는 Representation이라는 표현을 자주 사용합니다. 한국말로는 데이터에서 어떤 결과를 도출할 수 있을 법한, 다른 차원의 포인트를 지칭하는 것 정도로 생각하는데요. 대놓고 봤을 때는 타겟과 관련이 없어보이는 인풋이지만, Represntation을 뽑아보면, 아 관련이 있구나하는거죠. 쨋든 특성 공학은 결국 데이터를 Represent하는 행위의 일종입니다. 그리고 이는 (사실 딥러닝의 많은 부분들이 그러하다 생각합니다.) 어느 정도 예술(Art)의 영역라고 칭합니다. 왜냐면, 멋진 특성 공학에는 도메인 지식와 직관, 수학적 분석 모든 것이 녹아들어야하기 때문입니다. 누구나 시작할 수 있지만, 의미있는 특성 공학을 해내는 것은 그런면에서 굉장히 어렵습니다. 그럼에도 불구하고, 많은 Kaggle 우승자들이 Data Engineering의 중요성을 언급할 정도니, 어렵다고 안할수도없습니다.

시간의 쓸모

 시간 특성은 굉장히 다양히 요리될 수 있는 특성 중 하나입니다. 많은 경우에 있어 유의미하기도하구요. 우리에게 연도,월,일,시,분,초라는 데이터가 주어졌다고 가정해봅시다. 이 경우, 우리는 우리가 예측하고자하는 타겟에 따라 분해하거나, 묶어내야할 필요가 있습니다. 가령 어떤 지역의 유동인구 수를 예측하고자 하는데, 정말 초 라는 단위가 필요할까요? 유동인구가 매 초별로 바뀌는 것은 맞지만, 그것은 시간별 변화에 비해서는 굉장히 작습니다. 이런 세세한 부분까지 모델에게 학습을 시키려하면, 오히려 메인 트렌드를 학습하는 것에 실패할 수 있습니다. 이런 상황에 맞춰  시간의 어떤 부분을 제거하는 것이 가능합니다. 이런 관점에서는 시분초를 하나의 시간대로 묶는 행위도 충분히 유효할 것입니다. [0-1시], [1-2시]이런 식으로 말이죠. 당연히 오전, 오후, 점심시간 따위의 분류도 가능할 겁니다. 다만 시간대를 0,1,2,3,...,23 정도의 정수형 자료로 저장한다면, 선형 모델을 학습시킬 경우 모델이 오해할 소지가 있습니다. 시간대값이 커짐에 따라 타겟도 커지는지를 확인하는데 그게 아니면 당황하는거죠. 이런 경우는 비선형 모델(결정 트리 기반 등)을 사용하는게 나으며, 선형 모델에 학습시키기 위해서는 참거짓특성으로 분해하는 것이 낫습니다.

 다음으로는 주식 가격을 예측한다고 가정해봅시다. 이 경우, 우리는 단순히 연월일시분을 바라볼 것이 아니라, 해당 날짜로 부터 주말, 공휴일, 기념일, 장마감 시간 등의 특성을 이끌어낼 수 있습니다. 

범주형 속성 다루기

 당연히 데이터 중에는 범주형, 카테고리컬 특성이 존재합니다. 가령 성별이 남성, 여성으로 주어진 경우가 있겠죠. 이런 String type은 바로 모델이 읽을 수 없을 테니 일단 숫자로 치환하긴 할 텐데, 여기서 또 2가지가 나눠질것입니다. 단순히 남성:0, 여성:1로 대치할 것인가, 남성:[0,1], 여성[1,0]으로 대치할 것인가. 앞서 시간의 예시에서 말씀드린것처럼, 0과 1로 바꿀 경우, 모델이 1>0 이니까 여성이 더 좋구나. 착각할 상황이 생깁니다. 때문에 대부분의 경우 후자의 방법이 더 나으며, 이를 One-Hot encoding이라 합니다. (사실, 2개 범주밖에 없는 경우는 단순 정수 치환을 하나 One-Hot encoding을 처리하나 똑같습니다. 범주의 개수가 3이상일 경우에만 One-Hot encoding을 적용하면 충분합니다.)

데이터 구간 분할(Binning)

 어떤 데이터는 구간으로 분할되었을 때 더 유용할 수 있습니다. 나이라는 특성을 생각해보죠. 이 경우 타겟에 따라 다르겠지만, 10대, 20대 등으로 이산화하거나, 5세 단위로 분할하는 것이 학습에 더 용이할 수 있습니다. 전체 특성을 깔끔히 정립해서 작은 에러는 무시할 수 있게 해주는거죠. 다만 최소 최대값을 정할 수 없거나, 정하는 것이 무의미할 때는 사용할 수 없으며, 모델의 정밀도가 매우 중요한 상황에서는, 학습을 빠르게할 수는 있지만, 최고 정확도를 개선할 수는 없습니다.

피쳐 크로싱(Feature Crossing)

 간단히 말하자면, 2개 데이터를 합치는 것입니다. 아래 그림은 x축에은 특성 X1을, y축에는 특성 X2를, 파란색과 빨간색은 타겟의 클래스를 시각화한 것입니다. X1이 클수록 어떤 클래스에 속하는 것도아니고, 그렇다고 작을수록 어떤 클래스에 속하는 것도 아닙니다. X1과 X2의 조합, 그러니까 두 개 특성이 같이 크거나 작으면 빨간색, 서로 반대의 경향이면 파란색 이런식이죠. 

이런 경우 X1 X2 특성을 따로 활용하기보다는, X1X2라는 새로운 특성을 만드는 것이 낫습니다. 단순한 연산으로 구현할 수 있겠죠. 결국 이런 문제는 XOR문제와 비슷한것으로 생각되는데, 요즘 MLP야 빠른 속도로 XOR문제를 풀 수 있지만, 초기 Perceptron이 XOR문제를 풀지못했던 것을 생각하면, 피쳐 크로싱의 적용이 모델의 학습 속도 개선에 꽤나 영향을 끼칠 수 있을 것 같습니다.