Doby's Lab

Kaggle - Learn Feature Engineering : Target Encoding 본문

Data Science/Feature Engineering

Kaggle - Learn Feature Engineering : Target Encoding

도비(Doby) 2022. 10. 22. 15:39

[이 글은 Kaggle의 Learn을 토대로 작성되었습니다. 문제가 될 시 삭제 조치하겠습니다.]
(오역되어 잘못 설명된 부분이 있을 수 있습니다.)

 

https://www.kaggle.com/code/ryanholbrook/target-encoding

 

Target Encoding

Explore and run machine learning code with Kaggle Notebooks | Using data from FE Course Data

www.kaggle.com

 

Category

  • Introduction
  • Target Encoding
  • Smoothing
  • Example - MovieLens1M

Introduction

이전까지의 대부분의 Feature Engineering 기술은 Numerical feature에 관련된 것이었습니다. 이번엔 Categorical Feature와 관련된 기술 Target Encoding을 배워봅시다. Categorical Featrue를 처리한다는 점에서 One-hot Encoding 혹은 Label Encoding을 떠올릴 수 있지만, 이 기술은 Target을 이용한다는 점에서 다릅니다. 그래서 이 기술은 Supervised Feature Engineering으로 불리기도 합니다.


Target Encoding

Target Encoding은 Categorical Feature를 Target으로부터 숫자를 끌어와서 Encoding 하여 대체하는 기술입니다.

 

간단하게 Creating Feature에서 배운 Group Aggregation을 통해 예를 들어봅시다. Automobile Dataset을 사용하여 봅시다.

'make'라는 Categorical Feature를 기준으로 그룹화하여 'price'라는 target의 평균을 새로운 인코딩으로 Numerical Feature로 가져와서 인코딩을 합니다.

autos["make_encoded"] = autos.groupby("make")["price"].transform("mean")

autos[["make", "price", "make_encoded"]].head(10)

때때로, 이러한 인코딩은 mean encoding으로 불리기도 합니다. binary target에 적용할 경우, bin counting이라 불리기도 합니다. (자료에서는 다루진 않지만, target을 카운트하여 feature로 사용하는 듯합니다.)


Smoothing

 하지만, Target Encoding에는 크게 두 가지 문제가 존재합니다.

 

1) Unknown Categories

데이터를 학습하다가 처음 보는 Category가 나오면 Pandas는 Missing Value로 처리해버립니다. 우리는 이런 Value를 어떻게든 처리해야 합니다.

 

2) Rare Categories

데이터셋에서 드물게 등장하는 Category라면, 해당 Category의 통계적인 연산(예를 들어 평균)을 통해 나온 통계 값은 정확하지 않을 것입니다. 이러한 Rare Categories는 Overfitting을 초래할 수도 있습니다.

 

이러한 문제를 해결하기 위해서는 Smoothing을 이용하면 됩니다. Smoothing의 아이디어는 in-category(category의 내부)의 평균과 overall 평균을 섞는 것입니다. Rare Category라면 Category Average에서 비중을 줄이고, Overall Average의 비중을 높입니다. Unknown Category라면 Overall Average를 사용하여 Encoding 값을 도출하는 것입니다.

 

식으로는 아래와 같이 정리할 수 있습니다.

encoding = weight * in_category + (1 - weight) * overall

 

weight는 0과 1 사이의 값으로 정해집니다.

weight = n / (n + m)

n: 데이터에서 category가 나온 총 횟수

m: Smoothing Factor, 이 값이 높을수록 Overall Average의 비중이 더 높아집니다.

위 figure는 Category Count에 따른 Category Weight를 m값 별로 정리해둔 것입니다.

Category Count가 0일 때는 Overall Average를 사용해야 하기 때문에 m이 0이 되어 Encoding = 1 * overall이 됩니다.

m값이 높아질수록 in_category의 억제가 높아지는 것을 확인할 수 있습니다.

 

[m값을 결정할 때 고려해야 하는 것]

1) 그룹별 target의 차이가 큰가? or 활용되는 데이터의 크기가 큰가? -> m값이 커져도 좋다.

2) 그룹별 target의 차이가 안정적인가? -> m값이 작아져도 좋다.

 

왜냐하면 평균값과의 차이가 클수록 Encoding 되는 Value는 Category를 나타내기에 정확하지 않기 때문에 in_category의 비중을 m값을 높여버림으로써 줄이는 것이기 때문입니다.

 

[Target Encoding이 활용되는 좋은 사례]

1) High-cardinality features

너무 많은 종류의 Category를 가진 데이터라면 One-hot Encoding을 했을 때, 엄청 많은 Feature를 생성시키고, Label Encoding의 경우 Featrue로 사용하기에 큰 연관관계가 생기지 않을 수도 있어 염려됩니다. 이러한 경우에 Target과 연관된 정보를 포함하며 많은 Feature를 생성시키지도 않으므로 Target Encoding이 적합합니다.

 

2) Domain-motivated features

이전 경험들로 미루어보았을 때, Categorical Feature를 사용하면 좋은 점수를 얻지는 못하지만 Categorical Feature가 중요하다는 것은 알고 있습니다. 그러한 경우에 Target Encoding을 사용하여 점수를 높일 수 있습니다.


Example - MovieLens1M

MovieLens1M 데이터셋의 'Zipcode'라는 feature는 3,000개 이상의 Category가 들어있습니다. 이 데이터셋을 가지고 실습을 해봅시다.

 

사이킷런에서 제공하는 MEstimateEncoder를 가지고 Encoding 할 수 있습니다. cols에는 그룹별 묶을 Feature를 넘겨주고, m 값을 지정해줍니다. 그리고, encoder를 학습시켜 pretrain 된 X_pretrain에 encoder를 통해 Encoding 시켜줍니다.

from category_encoders import MEstimateEncoder

# Create the encoder instance. Choose m to control noise.
encoder = MEstimateEncoder(cols=["Zipcode"], m=5.0)

# Fit the encoder on the encoding split.
encoder.fit(X_encode, y_encode)

# Encode the Zipcode column to create the final training data
X_train = encoder.transform(X_pretrain)

이제 Encoding 된 값들이 얼마나 informative한지 시각화를 통해 알아봅시다.

plt.figure(dpi=90)
ax = sns.distplot(y, kde=False, norm_hist=True)
ax = sns.kdeplot(X_train.Zipcode, color='r', ax=ax)
ax.set_xlabel("Rating")
ax.legend(labels=['Zipcode', 'Rating']);

Encoding 된 'Zipcode'의 분포가 실제 target('Rating')과의 분포와 유사한 것을 보아 'Zipcode'에 따라 'Rating'이 연관되어 informative한 것을 볼 수 있습니다.

728x90