코딩하는 해맑은 거북이
[머신러닝] 범주형 변수의 인코딩(Encoding) 방법 4가지 본문
해당 글은 아래의 3가지를 다룬다.
📌 범주형 변수란?
📌 인코딩과 사용하는 이유
📌 인코딩 방법
🔷 One-Hot Encoding
🔷 Label Encoding
🔷 Target Encoding
🔷 Ordinal Encoding
📌 범주형 변수란?
(연속적이거나 순서가 있는 값을 가지는 변수인 수치형 변수(Numerical Variable)와 달리)
범주형 변수(Categorical Variable)란 유한한 범주 혹은 그룹 중 하나에 속하는 값을 가지는 변수를 의미한다.
범주형 변수는 다시 명목형 변수와 순서형 변수로 나눌 수 있다.
- 명목형 변수(Nominal Variable)
- 범주 간에 순서나 등간격이 없는 변수
- 예시: 성별, 혈액형
- 순서형 변수(Ordinal Variable)
- 범주 간에 상대적인 순서 또는 등간격이 있는 변수
- 예시: 학점, 만족도조사
📌 인코딩과 사용하는 이유
인코딩(Encoding)이란 데이터를 특정 형식으로 표현하거나 변환하는 과정을 의미한다. 주로 머신러닝이나 데이터 분석에서 범주형 변수를 수치형으로 변환하는데 사용된다.
Q. 그럼 범주형 변수는 왜 인코딩 해야할까?
머신러닝 모델은 수치형 데이터만 다룰 수 있기 때문에 String 형태로 된 범주형 변수는 모델이 인식할 수 있도록 적절한 수치형으로 변환하는 인코딩 과정을 거쳐야 한다.
📌 인코딩 방법
해당 글에서 주요 인코딩 방법 4가지에 대해서 설명한다. 이 외에도 다양한 인코딩 방법도 존재한다.
각 범주를 새로운 피쳐인 이진 열로 변환하는 방법으로, 각 열에 해당 범주가 속하면 1, 아니라면 0을 가지게 된다.
- 장점: 범주 간의 순서를 부여하지 않고, 각 범주가 모델에 독립적으로 고려되기 때문에 해석에 용이하다. (명목형 변수에 적합)
- 단점: 범주의 수 만큼 새로운 열을 생성하기 때문에 너무 많은 범주를 가진 변수에 적용할 때 차원이 크게 증가하고, 메모리 사용이 증가할 수 있다. 또한, 새로운 열 간에 상관관계가 발생할 수 있어 다중공선성 문제가 발생할 수 있다.
*예시 데이터
import pandas as pd
# 예시 데이터 - 각 도시에 대한 주택 가격 평균 (인코딩 결과 비교를 위해 중복 포함)
data = {'City': ['Seoul', 'Busan', 'Seoul', 'Busan', 'Seoul', 'Incheon', 'Incheon', 'Daegu'],
'Price': [500, 300, 450, 250, 550, 400, 420, 350]}
df = pd.DataFrame(data)
df
1) sklearn의 OneHotEncoder 사용
from sklearn.preprocessing import OneHotEncoder
# One-Hot Encoder 생성
# sparse=True : 희소 행렬 반환 / sparse=False : 밀집 행렬 반환
ohe = OneHotEncoder(sparse=False)
# 'City' 변수에 대해 One-Hot Encoding 적용
encoded_data = ohe.fit_transform(df[['City']])
# 생성된 열의 이름을 가져오기
feature_names = ohe.get_feature_names_out(['City'])
# 인코딩된 새로운 데이터프레임 생성
encoded_df = pd.DataFrame(encoded_data, columns=feature_names)
# 기존 'City' 열 제거
new_df = df.drop(['City'], axis=1).copy()
# 인코딩된 열 추가
onehot_encoded_df2 = pd.concat([new_df, encoded_df], axis=1)
display(ohe.categories_)
display(onehot_encoded_df2)
2) pandas의 get_dummies 사용
# 'City' 변수에 대해 One-Hot Encoding 적용
# prefix - 생성된 열의 이름의 접두사
onehot_encoded_df = pd.get_dummies(df, columns=['City'], prefix='City')
display(onehot_encoded_df)
각 범주를 고유한 정수로 변환하는 방법으로, 0~(범주의 수-1)까지 연속적인 정수를 가지게 된다.
- 장점: 각 범주를 단순히 정수로 바꿔주어 구현이 간단하고, 새로운 열을 생성하지 않기 때문에 메모리 사용이 효율적이다.
- 단점: 연속적인 정수로 범주 간의 순서를 부여하므로 모델이 해당 순서를 인식할 수 있어 예측에 영향을 미칠 수 있다. 또한, 해당 순서 및 수치적인 차이가 범주 간의 순서 정보가 아닐뿐더러 범주 간의 순서 정보를 고려하지 않고 부여된 정수이기에 순서 정보가 중요한 경우에 유용하지 않다.
- 이러한 특성 때문에 선형 회귀와 같은 머신러닝 알고리즘에서는 적용하지 않는다. 단, 트리계열은 이러한 특성을 반영하지 않기 때문에 문제없다.
from sklearn.preprocessing import LabelEncoder
label_encoded_df = df.copy()
# Label Encoder 생성
le = LabelEncoder()
# 'City' 변수에 대해 Label Encoding 적용
label_encoded_df['City'] = le.fit_transform(df['City'])
display(f'{dict(zip(le.classes_, le.transform(le.classes_)))}')
display(label_encoded_df)
범주의 타켓 변수(종속 변수)의 특정 통계량(주로 평균값)으로 변환하는 방법이다.
- 장점: 범주가 타켓 변수와의 어떤 관계를 반영하여 예측을 수행할 수 있고, 새로운 열을 생성하지 않기 때문에 메모리 사용이 효율적이다. (명목형 변수에 적합)
- 단점: 범주의 타켓 변수의 통계량을 사용하므로 인코딩 결과가 동일하게 되면 과적합의 원인이 될 수 있다.
!pip install category_encoders
from category_encoders import TargetEncoder
target_encoded_df = df.copy()
# Target Encoder 생성
te = TargetEncoder()
# 'City' 변수에 대해 Target Encoding 적용
target_encoded_df['City'] = te.fit_transform(df['City'], df['Price'])
display(te.mapping['City'][:-2])
display(target_encoded_df)
각 범주에 순서 또는 순위를 부여하여 고유한 정수로 변환하는 방법으로, 사용자가 범주 간의 순서를 정의해 주어야 한다.
- 장점: 각 범주에 순서를 부여하여 모델의 순서 정보를 전달할 수 있고, 새로운 열을 생성하지 않기 때문에 메모리 사용이 효율적이다. (순서형 변수에 적합)
- 단점: 범주 간의 순서 및 중요도가 동일하지 않은 경우 예측에 영향이 미칠 수 있다.
*예시 데이터
data = {'Grade': ['B', 'C', 'A', 'A+', 'B+']}
df = pd.DataFrame(data)
df
1) sklearn의 OrdinalEncoder 사용
from sklearn.preprocessing import OrdinalEncoder
ordinal_encoded_df = df.copy()
# Ordinal Encoding에 사용할 순서 정의
oe = OrdinalEncoder(categories=[['C', 'C+', 'B', 'B+', 'A', 'A+']])
# Ordinal Encoding 적용
ordinal_encoded_df['Grade'] = oe.fit_transform(df[['Grade']])
display(oe.categories_)
display(ordinal_encoded_df)
2) dataframe의 map 함수 사용
ordinal_encoded_df2 = df.copy()
# Ordinal Encoding에 사용할 순서 정의
ordinal_mapping = {'C': 0, 'C+': 1, 'B': 2, 'B+': 3, 'A': 4, 'A+': 5}
# Ordinal Encoding 적용
ordinal_encoded_df2['Grade'] = df['Grade'].map(ordinal_mapping)
display(ordinal_encoded_df2)
'AI' 카테고리의 다른 글
[Google ML Bootcamp 2023 4기] 수료 및 졸업식 후기 (0) | 2023.12.01 |
---|---|
[딥러닝] 얕은 신경망, 심층 신경망 네트워크 (0) | 2023.09.07 |
[딥러닝] 신경망과 로지스틱 회귀, 벡터화 (0) | 2023.09.04 |
[컴퓨터비전] Semantic Segmentation - FCN 한계를 극복한 Model (0) | 2023.06.13 |
[컴퓨터비전] Semantic Segmentation - FCN (0) | 2023.06.13 |