Sign In

[데이터 전처리] 범주형 변수 전처리

Y
Yerim
  1. ML
  2. DataAnalysis

변주형 변수 전처리

변주형 변수는 보통 문자열로 되어 있어 머신러닝 모델의 입력 데이터로 사용할 수 없다.
수치형 변수로 인코딩 encoding 해주는 과정이 필요하다.

인코딩 방법

Label Encoding
One-Hot Encoding
Frequency Encoding
Target Encoding
Embeding

Label Encoding

알파벳 순서로 숫자를 할당해주는 방법
문자열 값을 숫자형 카테고리 값으로 변환한다.
ex) ‘Bangul’: 1, ‘Bonn’: 2, …
순서형 데이터에는 적합할 수 있으나, 명목형 데이터에는 적합하지 않다.
숫자의 순서가 특징으로 여겨질 수 있다.
몇몇 ML 알고리즘에서는 예측 성능이 떨어지는 경우가 발생한다.
숫자형 카테고리 값이 중요도로 인식될 수 있으므로 선형회귀와 같은 ML 알고리즘에는 적용하지 않아야 한다.
트리 계열의 ML 알고리즘은 숫자의 이러한 특성을 반영하지 않으므로 레이블 인코딩이 문제 없다.

LabelEncoder

from sklearn.preprocessing import LabelEncoder

city = ['Bonn', 'Zomba', 'Paris', 'Tokyo', 'Seoul', 'Lagos', 'Bangul']

# 레이블 인코딩 수
encoder = LabelEncoder()
encoder.fit(city)
labels = encoder.transform(city)
print('인코딩 변환값:',labels)
# 데이터가 많은 경우
print('인코딩 클래스: ', encoder.classes_)
# 디코딩
print('디코딩 원본값: ', encoder.inverse_transform([4, 6, 0, 3, 5, 4, 4, 2, 4, 6, 0]))
# 타이타닉 데이터 실습
from sklearn.preprocessing import LabelEncoder
import seaborn as sns

df = sns.load_dataset('titanic')
df_sns = df[['sex', 'embarked', 'class']]
df_encoded = pd.DataFrame()

for col in df_sns.columns:
  encoder = LabelEncoder()
  encoder = encoder.fit(df_sns[col])
  labels = encoder.transform(df_sns[col].values.ravel())

  df_temp = pd.DataFrame(labels, columns=[col])
  df_encoded = pd.concat([df_encoded, df_temp], axis=1)

df_encoded
df_tt = pd.concat([df, df_encoded], axis=1)
df_tt.head()

One-Hot Encoding

피처 값마다 변수를 추가해 이진값으로 만드는 방법
피처 값의 유형에 따라 새로운 피처를 추가해 피처 값에 해당하는 컬럼만 1을 표시, 나머지 컬럼에는 0을 표시한다.
레이블 인코딩의 문제점을 해결하기 위한 인코딩 방법이다.
장점: 변수의 의미가 명확하다.
단점:
변수의 종류가 많아질수록 변수의 개수가 종류만큼 늘어나게 되거 Parse한 행렬이 많들어지게 된다. (차원의 저주)
다중 공선성 문제, 메모리 문제가 발생할 수 있다.

One-Hot Encoder

from sklearn.preprocessing import OneHotEncoder
import numpy as np

city = ['Bonn', 'Zomba', 'Paris', 'Tokyo', 'Seoul', 'Lagos', 'Bangul']

# 2차원 ndarray로 변환
city = np.array(city).reshape(-1, 1)

# 원핫인코딩
oh_encoder = OneHotEncoder()
oh_encoder.fit(city)
oh_labels = oh_encoder.transform(city)

print('원-핫 인코딩 데이터')
print(oh_labels.toarray())
print('원-핫 인코딩 데이터 차원')
print(oh_labels.shape)
# 타이타닉 데이터 실습
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder

df = sns.load_dataset('titanic')
df_sns = df[['sex', 'embarked', 'class']]
df_encoded = pd.DataFrame()

for col in df_sns.columns:
  encoder = OneHotEncoder()
  encoder = encoder.fit(df_sns[[col]])
  labels = encoder.transform(df_sns[[col]])
  labels_dense = labels.toarray().astype(int)

  col_names = [f"{col}_{value}" for value in encoder.categories_[0]]
  df_temp = pd.DataFrame(labels_dense, columns=col_names)

  df_encoded = pd.concat([df_encoded, df_temp], axis=1)

df_encoded
df_tt = pd.concat([df, df_encoded], axis=1)
df_tt.head()

get_dummies

pandas.get_dummies(data, prefix=None, prefix_sep='_', dummy_na=False, columns=None, sparse=False, drop_first=False, dtype=None)
drop_fist=True로 설정하면 컬럼 중 하나가 삭제된다.
하나의 컬럼이 없어도 다른 컬럼들에 속하지 않는 값들로 구분 가능하다.
→ 불필요한 피처의 수를 줄일 수 있다.
2개 카테고리를 갖는 피처의 경우 label encoding을 get_dummies로 구현 가능하다.
import pandas as pd

df = pd.DataFrame({'수도': ['Bonn', 'Zomba', 'Paris', 'Tokyo', 'Seoul', 'Lagos', 'Bangul']})
pd.get_dummies(df)
# 타이타닉 데이터 실습
import pandas as pd
import seaborn as sns

df = sns.load_dataset('titanic')
df_sns = df[['sex', 'embarked', 'class']]

df_encoded = pd.get_dummies(df_sns)
df_tt = pd.concat([df, df_encoded], axis=1)

df_tt.head()

Frequency Encoding

SVD 잠재 의미 분석하는 인코딩

Target Encoding

각각의 변수 종류가 가지는 Target 변수의 평균으로 인코딩
ex) "개"는 사료의 비용이 평균값 2000원 ((1000 + 1500 + 3500)/3 )
단점: 1, 3, 4, 5 ID처럼 다른 종이 같은 Target Encoding을 갖게 될 수 있다.

Embedding

Entity Embedding이라고도 하는 이 방법은 Word2Vec과 같은 모델을 이용해 Text 데이터를 더 낮은 차원으로 임베딩하는 방법

데이터 구간화 Binning

변수구간화: 연속형 변수를 구간 또는 범주로 나누는 것
연속형 변수를 다룰 때
→ 나이와 같은 데이터의 경우 구간으로 나누어 새로운 변수를 만들 수 있다
모델의 복잡도를 줄이고 특정 패턴이나 추세를 확인할 때 유용하다
binning을 통해 해당 변수의 스케일이나 분포가 모델에 미치는 영향을 줄일 수 있다
구간화 순서
1.
구간 설정: 연속형 변수를 나눌 구간 설정 → 개수나 도메인 지식으로 결정
2.
구간 경계 설정: 어디까지 어떤 값으로 할때 구간을 정하는 경계값 필요
3.
데이터 비닝: 설정 구간에 따라 연속형 변수들을 구간 또는 범주에K 할당
scikit-learn 라이브러리에서 제공하는 패키지
연속형 변수를 구간으로 나누어 범주형 변수로 변환하는 작업 수행
sklearn.preprocessing.KBinsDiscretizer(n_bins=5, *, encode='onehot', 
                strategy='quantile', dtype=None, subsample=200000, random_state=None) 
encode : onehot(원핫인코딩) ordinal(레이블인코딩)
strategy : 구간 나누는 전략, uniform - 데이터를 균일하게 나누기, quantile 데이터 분포 분위수 기반, 'kmeans' - K means 방법으로 진행
예시
from sklearn.preprocessing import KBinsDiscretizer

data = [[1, 2, 3, 4],
        [11, 12, 13, 14],
        [21, 22, 23, 24],
        [31, 32, 33, 34]]

est=KBinsDiscretizer(n_bins= 15, encode='ordinal', strategy ='uniform')
est.fit(data)
est.transform(data)
Yerim-DevNote
Subscribe to 'Yerim-DevNote'
Subscribe to my site to be the first to receive notifications and emails about the latest updates, including new posts.
Join Slashpage and subscribe to 'Yerim-DevNote'!
Subscribe
👍