관리 메뉴

TEAM EDA

[Machine Learning Advanced] 3강. 머신러닝 강의 - 파생 변수 만들기 본문

EDA Study/Machine Learning Advanced

[Machine Learning Advanced] 3강. 머신러닝 강의 - 파생 변수 만들기

김현우 2023. 8. 14. 01:35

이번 강의에서는 파생 변수를 만드는 방법(Feature Engineering)에 대해 알아보겠습니다. 파생 변수를 만드는 것은 ML의 성능을 좌지우지하는 가장 중요한 부분 중 하나입니다. 대회에서 많은 사람들이 시간을 투자하는 부분이고, 많이 어렵기도 한 부분입니다. 도메인이나 데이터의 특성마다 적용하는 방법이 다르며, 데이터의 분석이 뒷받침이 되어야 의미가 있는 경우도 많습니다. 해당 강의에서는 일반적으로 적용할 수 있는 Feature Engineering 기법들에 대해 살펴보고, 몇몇 사례를 통해서 특정 데이터나 도메인에 대해 파생 변수를 어떻게 만들었는지 익혀보겠습니다. 

 

파생변수란 무엇이고, 왜 중요할까요? 

파생변수란 기존의 데이터를 통해서 새롭게 만들어 낸 변수를 의미합니다. 이전에 배웠던 연속형 변수에 log, exp 등의 스케일링을 취하거나 범주형 변수에 대해 인코딩을 하는 것 또한 파생변수의 하나라고 볼 수 있습니다. 파생변수를 만드는 것에 어떤 효능이 있을까요? 
 

  1. 성능적인 측면
  2. 해석적인 관점
  3. 메모리 관점 

크게는 3가지 방향이 있을 것 같습니다. 도메인 지식을 활용하거나, 변수들을 조합해 의미있는 변수를 추출하면 모델의 성능이 높아질 수 있습니다. 그리고, 이러한 변수들은 사람이나 모델이 해석하기도 좋습니다. 또한, 여러 변수들을 PCA등으로 축소해서 만들거나 변수 두개를 결합해서 한개로 변환하면 메모리 관점에서 변수들을 줄일 수 있는 효용도 있습니다. (단, 기존변수를 유지한채로 파생변수를 계속 늘려가면 메모리는 당연히 늘어납니다) 참고로, 이 과정에서 과적합 또한 방지할 수 있습니다.

 

이러한 파생변수는 어떻게 만들 수 있을까요? 

대회에서도 사람들이 가장 많은 시간을 쏟는 부분이 해당 부분이라고 할만큼 중요하지만 어려운 작업인 것 같습니다. 캐글의 그랜드마스터의 인터뷰에 따르면 대회 종료 3~4일전까지도 파생변수를 만드는 것에 집중한다고 합니다. 이러한, 파생변수를 잘 만들기 위해서는 먼저, 데이터와 도메인에 대한 이해가 있어야 합니다. 만약, 파생 변수를 만들 때 데이터와 도메인에 대한 이해가 부족하면 어떤 일이 발생할까요? 위의 3가지 장점의 반대라고 보시면 될 것 같습니다. 성능은 감소할 수 있고, 해석도 어렵고, 메모리 관점에서도 변수가 늘어나다보니 안좋을 수 있습니다. 그렇기에, 가장 먼저 데이터의 분석과 도메인에 대한 이해를 통해서 파생변수를 만들어야합니다. 그리고, 목적식이나 타겟 변수와의 관계를 생각해주면서 접근해도 좋습니다. 그렇다면, 이러한 분석이 되었다는 하에서 파생변수를 만드는 방법들에 대해 살펴보겠습니다. 
 
제가 생각했을때 파생변수를 만드는 방법은 크게 두가지로 나뉘는 것 같습니다. 변수 자체를 이용해서 변환하는 방법과 변수들간의 관계를 이용해서 새로운 변수를 만드는 방법입니다. 먼저, 변수 자체를 이용하는 방법에 대해 살펴보겠습니다. 
 

변수 자체를 이용한 방법

1. 연속형 변수의 처리 
해당 부분은 [Machine Learning Advanced] 2강. 머신러닝 강의 - 데이터 전처리 (연속형 변수)를 참고하시기 바랍니다. 


2. 범주형 변수의 처리 
2강에서 살펴본 [Machine Learning Advanced] 2강. 머신러닝 강의 - 데이터 전처리 (변수의 인코딩, 임베딩 방법) 내용이 해당 부분과 연관이 있습니다. 해당 글에서는 범주형 변수를 처리하는 방법으로 One Hot Encoding, Label Encoding, Frequency Encoding, Mean Encoding에 대해 살펴봤습니다. 

 

이런식으로, 범주형 변수를 변환해주는 파생변수 생성 방법이 있습니다. 


 
3. 시간 변수의 처리 
시간과 관련된 변수를 파생변수로 만드는 방법 또한 존재합니다. 예를들어, 아래의 데이터를 생각해보겠습니다. 

카드사의 거래내용을 기반으로 지불 여부를 예측하는 데이터

이러한 시간 변수(거래일, 첫 거래일)는 컴퓨터가 바로 인식할 수 없기에 인식할 수 있는 형태로 변환해줄 필요성이 있습니다. 가장 간단한 방법으로는 년도, 월, 일, 시간, 분, 초, 주중, 주말, 공휴일 등과 같은 변수를 만들 수도 있습니다. 
 

 
특정 시점을 기준으로 해당 시점과의 차이를 만들 수도 있습니다. 예를들어, 위에서는 거래일을 인식해주기 위해서 '1900-01-01'과 같은 특정 시점으로부터의 차이 (거래일 - '1900-01-01')로 변수를 만들 수 있고 혹은 첫 거래일이라는 고객명에 종속되는 변수를 이용해서 거래일 - 첫 거래일로 변수를 만들 수도 있습니다. 

 

비슷하게 특정 시점을 "연휴", "명절", "주말" 등과 같이 의미있는 시점을 기반으로 만들 수도 있습니다. 예를들어, 명절같은 경우 선물세트를 사거나 여행을 갈 준비를 하게 되니 이러한 피처를 통해서 연휴때 잘 팔리는 상품들을 모델이 주목할 수 있게 도와주는 역할을 합니다. 혹은, 온라인 쇼핑몰에서는 고객별로 개인화 추천을 해주기 위해, 고객의 방문주기 혹은 반복구매하는 상품의 주기를 기억했다가 해당 기간이 얼마나 남았는지를 피처로 만들어 사용하기도 합니다. 

 

4. Geometric (지리정보)
 여기 만들어야함 
 
5. 그 외 (공통적인 부분)
위의 부분에 공통적으로 사용할 수 있는 부분으로 결측치의 유무를 파생변수로 만드는 방법이 있습니다. 예를들어, 결측치가 있으면 1 없으면 0의 값을 부여하는 새로운 변수를 만드는 것입니다. 그 외에 많이 사용하는 방법으로는 통계적인 의미를 만드는 변수를 추가할 수도 있습니다. 예를들어, 위의 카드사의 거래내용 데이터에서 가격 변수를 기반으로 통계적 변수인 평균, 편차, 중앙값 등의 변수를 만들 수 있습니다. (평균 = (3+7000+7000)/3)

전체 인스턴스가 같은 값이라 해당 변수 자체는 큰 의미는 없지만, 이러한 통계 값은 뒤에나올 변수들간의 관계를 파악한 상호작용 변수를 만들때 의미가 큽니다. 예를들어, 가격 / 가격_평균 혹은 가격 / 가격_중앙값 등으로 변수를 만들면 평균 가격 대비 얼마나 가격이 낮은지에 대해 모델이 인식하기 용이한 장점이 있습니다. 

 

시계열 데이터에서 주로 사용되는 Moving Average (이동 평균)이라는 파생변수 생성방법도 있습니다. 

 


 
보통 주식 시장에서 주가의 흐름을 부드럽게 표현하거나 주가의 추세를 파악하는 데 일반적으로 사용되는 방법입니다. 예를 들어, 3일 이동평균은 최근 3일 동안의 종가를 평균한 값입니다. 마찬가지로, 5일 이동평균은 최근 5일 동안의 종가를 평균해서 계산합니다. 

 

변수들 간의 관계를 이용한 방법

변수 하나만 이용하여 파생변수를 만드는 것이 아닌, 여러개의 변수의 상호작용을 통해 변수를 만들 수도 있습니다. 이러한 관계를 만들때는 데이터의 상관관계라든지 도메인지식 등을 활용해서 만들어 볼수도 있고, 가설을 세워서 접근을 해볼 수도 있습니다. 
 
1. 상호작용 변수 

 

[왼쪽] 쇼핑몰 데이터를 기반으로 팔릴 확률 예측 데이터 / 수치형 변수의 상호작용

대표적으로 더하거나, 빼거나, 곱하거나, 나누는 등의 방식을 이용해서 서로 다른 변수를 결합할 수 있습니다. 이전의 예시에서 가격 / 가격_평균 혹은 가격 / 가격_중앙값과 같은 부분이 여기에 속합니다. 서로 다른 변수들의 의미를 모두 담기에 해당 부분이 두 개 변수가 설명하는 부분을 어느정도 포함하고 있고, 상호작용을 직접적으로 표현해서 모델이나 분석하는 입장에서 해석하기도 용이합니다. 위의 경우는 쇼핑몰 데이터를 기반으로 각 상품의 카테고리와 가격, 카테고리의 평균 가격을 통해 팔릴 확률을 예측하는 문제입니다. 왼쪽의 경우만 보면 선형회귀 모델은 가격과 평균 가격을 서로 떼어놓고 판단하거나 트리모형은 박스형태로 둘의 관계(카테고리 내에서 상품의 비싼 정도)를 학습하려고 할 것입니다. 트리모형은 물론 그렇게 학습해도 되지만 효과적이지는 않습니다. (선형모델은 다중공선성때매 결과해석이 불안정해지는 문제가 있습니다) 그러기보다 [오른쪽] 표처럼 상품의 비싼 정도 = 가격 / 카테고리_가격_평균를 직접적으로 만들면 훨씬 관계를 파악하기 쉽습니다. 그로인해, 트리는 깊이를 더 깊게 할 필요가 없어서 과적합도 막을 수 있고 성능측면에서나 해석적인 측면에서 모두 좋은 모습을 보입니다. 

 

카드사의 거래내용을 기반으로 지불 여부를 예측하는 데이터 / 날짜형 변수의 상호작용

 

수치형 변수의 상호작용이 아닌, 날짜형 변수의 상호작용을 보겠습니다. 이전에 봤던 예시 데이터인 카드사의 거래내용을 기반으로 지불 여부를 예측하는 데이터를 다시 보겠습니다. 실제 해당 고객이 카드값을 지불할 능력이 있는지 거래일과 첫 거래일을 따로따로 보면 모델을 이를 판단하기 어렵습니다. 이런경우, 거래일에서 첫 거래일을 빼서만든 "거래한 기간"을 보면 유재석의 경우 8626일 동안 거래를 지속함에도 지불을 안한 경우가 없다면 모델을 지불할 능력이 충분하다라고 판단하기 쉽습니다. 반대로, 김종국의 경우 0일 동안 거래를 한 사람이니 모델입장에서는 이를 지불할 능력이 있다고 판단하기 어려울 것입니다. 

 

카테고리 변수의 상호작용

혹은 카테고리 변수들을 결합 시켜서 새로운 의미를 부여할 수도 있습니다.  이러면, 상품 카테고리만 봤을때는 옷이었지만 색상 카테고리와 결합해서 빨간색 옷이라는 의미를 부여해줄 수 있습니다. 
 
 
2. 그룹 활용 (Groupby)
 
+) Groupby Statistics (sum, mean, max, min, std, cumsum, cummax ...) 
 
+) Groupby Time Diff  
 
 여기 만들어야함