범주형 변수 인코딩

src/content/documents/machine-learning/categorical-encoding-guide.json

문자열을 숫자로 바꾸기 전에 물어볼 질문

범주형 변수는 도시·등급·상품군처럼 값이 그룹을 뜻하는 변수다. 모델은 보통 숫자를 입력으로 받지만, 아무 숫자나 붙이면 모델이 그 숫자의 크기와 간격까지 의미로 받아들일 수 있다.

첫 질문은 “범주 사이에 실제 순서가 있는가?”다. 순서가 있으면 Ordinal, 순서가 없으면 대개 OneHot을 출발점으로 삼는다.

Ordinal과 OneHot의 차이

  • Ordinal encoding: 낮음 < 보통 < 높음처럼 업무적으로 합의된 순서를 한 열의 정수로 표현한다. 단, 0→1과 1→2의 간격이 같다는 뜻까지 자동으로 생기므로 모델과 해석에 주의한다.

  • One-hot encoding: 서울·부산·대구처럼 순서 없는 각 범주를 별도 0/1 열로 만든다. 숫자 크기에 따른 거짓 순서를 피하지만 범주가 많으면 열과 메모리가 늘어난다.

  • LabelEncoder는 목표값 y의 라벨을 인코딩하는 도구다. 입력 특성 X의 여러 범주형 열에는 OrdinalEncoder나 OneHotEncoder를 사용한다.

실습: 미지 범주까지 안전하게 변환하기

아래 예제는 학습 데이터에만 인코더를 맞춘 뒤 새 데이터의 부산을 처리한다. handle_unknown="ignore"이면 미지 범주의 one-hot 행은 모두 0이 된다.

import numpy as np
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder

train_city = np.array([["서울"], ["대구"], ["서울"]])
test_city = np.array([["부산"], ["대구"]])

onehot = OneHotEncoder(handle_unknown="ignore", sparse_output=False)
onehot.fit(train_city)
print(onehot.categories_[0].tolist())
print(onehot.transform(test_city).astype(int).tolist())

level = np.array([["낮음"], ["높음"], ["보통"]])
ordinal = OrdinalEncoder(
    categories=[["낮음", "보통", "높음"]],
    handle_unknown="use_encoded_value",
    unknown_value=-1,
)
ordinal.fit(level)
print(ordinal.transform([["매우 높음"], ["보통"]]).astype(int).ravel().tolist())
['대구', '서울']
[[0, 0], [1, 0]]
[-1, 1]

모두 0 또는 -1은 “범주가 없다”가 아니라 “학습 때 보지 못했다”는 약속이다. 운영 로그에서 미지 범주 비율을 따로 감시해야 데이터 변화가 조용히 숨지 않는다.

희소 범주와 고카디널리티

범주 수가 많은 우편번호·상품 ID를 그대로 one-hot하면 열이 폭증하고, 아주 드문 범주는 우연한 패턴을 학습하기 쉽다. scikit-learn의 min_frequency 또는 max_categories는 학습 데이터에서 드문 범주를 하나의 infrequent 그룹으로 묶는다. 기본 출력은 희소 행렬이므로 대규모 데이터에서 함부로 dense 배열로 바꾸지 않는다.

  • 의미가 같은 철자·공백·대소문자를 먼저 정규화한다.

  • 업무상 같은 상위 그룹이 있으면 상품→상품군처럼 도메인 매핑한다.

  • 빈도 임계값은 전체 데이터가 아니라 학습 폴드에서 결정한다.

  • 식별자에 가까운 고유값은 삭제·해싱·집계 특성 등 다른 표현을 검토한다.

더미 변수 함정은 언제 문제인가

절편이 있는 비정규화 선형모델에서는 모든 one-hot 열의 합이 1이어서 완전한 다중공선성이 생길 수 있다. 한 열을 기준 범주로 빼는 drop="first"가 이를 피하지만, 범주 표현의 대칭을 깨뜨려 규제가 있는 모델에서 편향을 만들 수도 있다. 트리 모델이나 규제가 있는 예측 문제에서 기계적으로 한 열을 버릴 필요는 없다.

누수 없는 프로젝트 적용 순서

  • 먼저 train/test를 나눈다. 분할 기준은 시간·사용자·그룹 구조까지 반영한다.

  • 인코더의 범주, 희소 범주 임계값, 타깃 기반 통계는 train에서만 학습한다.

  • ColumnTransformer와 Pipeline에 전처리를 넣어 각 교차검증 학습 폴드에서만 fit되게 한다.

  • 검증·테스트·운영 데이터에는 transform만 적용하고 미지 범주율을 기록한다.

특히 target encoding은 범주별 목표값 평균을 사용하므로 같은 행의 정답이 인코딩에 섞이지 않도록 교차 적합(cross-fitting)이 필요하다. 단순 one-hot보다 누수 위험이 크다.

핵심 체크리스트

  • 범주의 순서가 실제 업무 의미인지 확인했다.

  • unknown과 missing의 표현을 구분했다.

  • 희소 범주 규칙을 학습 데이터에서만 정했다.

  • 인코더와 모델을 하나의 Pipeline으로 묶었다.

참고 자료

댓글 0

댓글을 불러오는 중…