
머신러닝 프로젝트의 성패는 모델 알고리즘 선택만큼이나 범주형 데이터(Categorical Data)를 어떻게 수치로 변환하느냐에 달려 있습니다. 단순히 '텍스트를 숫자로 바꾼다'는 개념을 넘어, 우리가 선택한 인코딩 방식은 모델이 데이터 간의 관계를 해석하는 방식 자체를 결정합니다. 본 포스팅에서는 Label Encoding과 One-hot Encoding이 트리 기반 모델(XGBoost, LightGBM 등)과 선형 모델(Logistic Regression, SVM 등)에 미치는 치명적인 영향력을 분석하고, 실무에서 마주하는 성능 저하 문제를 해결하기 위한 7가지 핵심 전략을 전문적인 관점에서 제시합니다.
1. 인코딩 방식에 따른 메커니즘 차이 및 모델별 적합성 비교
인코딩 방식은 데이터의 차원과 '순서(Ordinality)' 정보의 유무를 결정합니다. 이 차이가 모델의 손실 함수(Loss Function) 최적화에 직간접적인 영향을 줍니다.
| 비교 항목 | Label Encoding | One-hot Encoding |
|---|---|---|
| 수학적 특징 | 단일 컬럼에 정수(0, 1, 2...) 할당 | N개의 카테고리를 N개의 이진 컬럼으로 확장 |
| 차원의 변화 | 차원 유지 (1개 컬럼) | 차원 급증 (High Cardinality 시 저주 발생) |
| 가중치 해석 | 숫자 크기에 따른 가중치 오인 가능성 | 각 범주가 독립적인 가중치를 가짐 |
| 선형 모델 영향 | 위험함: 존재하지 않는 순위 관계 학습 | 적합함: 범주 간 독립성 보장 |
| 트리 모델 영향 | 효율적: 분할(Split) 시 메모리 이점 | 주의: 희소성(Sparsity)으로 인한 성능 저하 |
2. 실무 해결을 위한 Python 인코딩 전략 Sample Example 7가지
개발자가 현업 데이터 파이프라인에서 즉시 복사하여 사용할 수 있는 모델 맞춤형 인코딩 구현 예제입니다.
Example 1: Scikit-learn LabelEncoder를 이용한 트리 모델 전처리
의사결정 나무 기반 모델에서는 범주형 변수의 순서 정보가 크게 왜곡되지 않으므로 메모리 효율을 위해 사용합니다.
from sklearn.preprocessing import LabelEncoder
import pandas as pd
df = pd.DataFrame({'Target': ['High', 'Low', 'Medium', 'Low', 'High']})
# [해결] 트리 모델용 정수 인코딩
le = LabelEncoder()
df['Encoded'] = le.fit_transform(df['Target'])
# 클래스 확인: ['High', 'Low', 'Medium'] -> [0, 1, 2]
print(df)
Example 2: Pandas get_dummies를 활용한 선형 모델용 원-핫 인코딩
범주 간에 우열이 없는 명목형 데이터를 선형 회귀나 로지스틱 회귀에 넣을 때 필수적인 해결 방법입니다.
# [방법] drop_first=True 옵션을 통해 다중공선성(Multicollinearity) 문제 방지
df_oh = pd.get_dummies(df['Target'], drop_first=True)
# n-1개의 컬럼만 생성하여 선형 모델의 독립 변수 간 상관관계 제거
print(df_oh)
Example 3: ColumnTransformer를 이용한 하이브리드 인코딩 파이프라인
실무 데이터셋은 수치형과 다양한 범주형이 섞여 있습니다. 이를 한 번에 처리하는 자동화 해결책입니다.
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
# 수치형은 스케일링, 범주형은 원핫 인코딩 적용
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), ['age', 'income']),
('cat', OneHotEncoder(handle_unknown='ignore'), ['city', 'gender'])
])
# X_train_processed = preprocessor.fit_transform(X_train)
Example 4: High Cardinality 해결을 위한 Target Encoding (차원 감소)
범주 종류가 수천 개일 때 원-핫 인코딩의 차원 저주를 피하기 위해 타겟 변수의 평균값을 활용합니다.
# category_encoders 라이브러리 사용 권장
# pip install category_encoders
from category_encoders import TargetEncoder
encoder = TargetEncoder(cols=['zip_code'])
# 타겟값(y)과의 상관관계를 반영하여 수치화 (트리 모델 성능 극대화)
X_target_encoded = encoder.fit_transform(X, y)
Example 5: 순서 정보가 뚜렷한 경우의 Ordinal Encoding 구현
'상-중-하'처럼 명확한 서열이 있는 경우, 모델에 의도적으로 순위를 주입하는 방법입니다.
from sklearn.preprocessing import OrdinalEncoder
# 순서를 직접 명시하여 인코딩 (매우 중요)
order_categories = [['Low', 'Medium', 'High']]
oe = OrdinalEncoder(categories=order_categories)
df['Rank'] = oe.fit_transform(df[['Target']])
Example 6: Sparse Matrix를 활용한 원-핫 인코딩 메모리 최적화
데이터가 클 경우 원-핫 인코딩 결과물은 대부분 0입니다. 이를 압축하여 저장하는 기법입니다.
# sparse=True 설정을 통해 메모리 점유율을 1/100 이하로 절감
ohe_sparse = OneHotEncoder(sparse_output=True)
sparse_results = ohe_sparse.fit_transform(df[['Target']])
Example 7: LightGBM 전용 Categorical Feature 지정 활용
최신 트리 모델은 인코딩을 직접 하기보다 모델 자체 엔진에 맡기는 것이 가장 빠릅니다.
import lightgbm as lgb
# 범주형 컬럼을 정수로 바꾼 뒤, 모델 학습 시 지정
train_data = lgb.Dataset(X, label=y, categorical_feature=['city_code'])
# [해결] 내부 최적 알고리즘이 Optimal Split을 계산함
3. 전문가의 시각: 왜 선형 모델에서 Label Encoding은 금기인가?
선형 모델(Linear Models)은 입력 피처 $x$에 대해 $y = wx + b$의 수식을 최적화합니다. 만약 '서울', '부산', '제주'를 Label Encoding을 통해 0, 1, 2로 변환했다면, 모델은 수학적으로 '제주(2)는 서울(0)의 2배 가치가 있다'거나 '서울과 부산의 거리는 부산과 제주의 거리와 같다'는 가정을 강제받게 됩니다. 반면, 트리 모델(Tree-based Models)은 변수의 값의 크기(Magnitude)가 아니라 분할 지점(Split Point)을 찾습니다. "값이 1보다 작은가?"라는 질문으로 '서울'을 분리해낼 수 있기 때문에 비선형적인 관계를 가진 Label Encoding 데이터에서도 훌륭하게 작동하는 성능 차이를 보입니다.
4. 결론: 올바른 인코딩 선택 로드맵
프로젝트 초기 단계에서 다음 기준에 따라 인코딩 전략을 수립하십시오.
- 선형 모델 / 신경망 / 거리 기반(KNN): 무조건 One-hot Encoding을 사용하십시오.
- 트리 기반 모델 (RF, XGB, LGBM): Label Encoding이나 Target Encoding이 효율적입니다.
- 범주가 너무 많을 때 (High Cardinality): One-hot은 피하고 Binary Encoding이나 Hash Encoding을 검토하십시오.
- 순서가 의미 있을 때: 반드시 Ordinal Encoding으로 서열을 보존하십시오.
정보 출처 및 참고 문헌
- Scikit-learn User Guide: "Encoding categorical features" (v1.4)
- Hands-On Machine Learning with Scikit-Learn - Aurélien Géron
- CatBoost Documentation: "Transforming categorical features to numerical"
- Journal of Machine Learning Research: "A Survey of Categorical Data Encoding"