정제로 데이터를 깨끗하게 만들었다면 이제 모델이 잘 학습할 수 있는 형태로 변형 할 차례다. 특성 공학은 흔히 "모델 성능의 80%를 좌우한다"고 말할 정도로 ML 파이프라인에서 비중이 크다.
많은 알고리즘이 피처의 스케일(크기) 에 민감하다. 나이(0~100)와 소득(0~1억)을 그대로 넣으면 거리·기울기 계산에서 소득이 압도한다.
기법 변환식 결과 범위 이상치 영향 언제 쓰나 Min-Max 정규화 (x − min) / (max − min) [0, 1] 매우 민감 범위를 딱 맞춰야 할 때(이미지 픽셀 등) 표준화 (Z-score) (x − μ) / σ 평균 0, 분산 1 민감 선형모델·신경망의 기본 RobustScaler (x − 중앙값) / IQR 가변 강건 이상치가 많을 때 MaxAbs x / |max| [−1, 1] 민감 희소 행렬에서 0을 유지해야 할 때 로그 변환 log(1+x) 가변 꼬리 압축 오른쪽으로 긴 꼬리 분포
스케일링이 필수 인 알고리즘: 거리 기반(KNN, K-means), 기울기 기반(선형/로지스틱 회귀, 신경망), 정규화 항이 있는 모델(Ridge/Lasso), SVM, PCA.
스케일링이 불필요 한 알고리즘: 트리 기반(Decision Tree, Random Forest, XGBoost, LightGBM). 트리는 한 피처 안에서의 분할 기준점만 보므로 단조 변환에 불변이다.
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
# 표준화: 신경망/선형모델 기본
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # fit 아님!
# 이상치가 많으면 RobustScaler
robust = RobustScaler()
X_train_robust = robust.fit_transform(X_train)
[스케일이 제각각일 때] [표준화 후]
손실 함수 등고선이 등고선이 원에 가까워짐
길쭉한 타원 ↓
╱╲ ╭─╮
╱ ╲ 지그재그 수렴 │ ●│ 최단 경로로 수렴
╲ ╱ ╰─╯
╲╱
경사 하강법이 스케일에 민감한 이유는 손실 함수의 등고선 모양 때문이다. 피처 스케일이 제각각이면 등고선이 길쭉한 타원이 되어, 기울기가 최솟값을 향해 지그재그로 느리게 수렴한다. 표준화로 모든 피처를 같은 스케일로 맞추면 등고선이 원에 가까워져 수렴이 빠르고 안정적이다. 거리 기반 모델(KNN, K-means)에서는 유클리드 거리가 큰 스케일 피처에 지배되는 것을 막는 효과가 있다.
⚠️ 함정 : 스케일러도 imputer와 똑같이 학습셋으로만 fit 해야 한다. 테스트셋의 min/max/평균을 쓰면 누수다. 또한 Min-Max는 이상치 하나가 max를 끌어올려 나머지 값을 0 근처로 압축해 버리므로, 이상치가 의심되면 RobustScaler가 안전하다.
대부분의 알고리즘은 숫자만 입력으로 받으므로 범주형(categorical) 변수를 숫자로 바꿔야 한다.
인코딩 방법 적합 주의 Label Encoding 범주 → 정수(0,1,2…) 순서형(ordinal), 트리 모델 명목형에 쓰면 가짜 순서 부여 One-Hot Encoding 범주마다 0/1 컬럼 생성 명목형(nominal), 저카디널리티 고카디널리티에서 차원 폭발 Ordinal Encoding 의미 있는 순서로 정수 매핑 등급(low/mid/high) 순서가 진짜일 때만 Target Encoding 범주를 타깃 평균으로 치환 고카디널리티 누수·과적합 위험 Frequency Encoding 범주를 빈도로 치환 고카디널리티 빈도 같으면 충돌 Feature Hashing 해시로 고정 차원에 매핑 미지의 범주·스트리밍 충돌 발생 Embedding 신경망이 저차원 밀집 벡터 학습 초고카디널리티, 딥러닝 학습 데이터·네트워크 필요
순서가 있는가?
├─ 예 → Ordinal / Label Encoding (low < mid < high)
└─ 아니오 → 고유값이 몇 개인가?
├─ 적다(수십 이하) → One-Hot
└─ 많다(수천 이상) → Target / Frequency / Hashing / Embedding
· 누수 주의(Target)
· 충돌 감수(Hashing)
· 딥러닝이면 Embedding
핵심 구분은 순서가 있는가 다. 등급(낮음<중간<높음)이면 Ordinal/Label이 자연스럽고, 색깔(빨강/파랑/초록)처럼 순서가 없으면 One-Hot이 맞다. 선형 모델에 색깔을 Label Encoding(빨강=0, 파랑=1, 초록=2)하면 "초록 > 파랑 > 빨강"이라는 거짓 순서가 생긴다.
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
# 명목형: 원핫
ohe = OneHotEncoder( handle_unknown = "ignore" , sparse_output = False )
X_color = ohe.fit_transform(df[[ "color" ]])
# 순서형: 명시적 순서로 ordinal
oe = OrdinalEncoder( categories = [[ "low" , "mid" , "high" ]])
df[ "level_enc" ] = oe.fit_transform(df[[ "level" ]])
타깃 인코딩은 강력하지만 위험하다.
# 타깃 인코딩 (누수 방지를 위해 학습셋 fold로만 통계 산출)
means = X_train.groupby( "city" )[ "target" ].mean()
X_train[ "city_te" ] = X_train[ "city" ].map(means)
X_test[ "city_te" ] = X_test[ "city" ].map(means) # 학습셋 통계 적용
타깃 인코딩은 고카디널리티(예: 우편번호 수천 개)에서 원핫의 차원 폭발을 피하면서 타깃과의 관계를 한 컬럼에 압축한다. 그러나 같은 데이터의 타깃으로 피처를 만들면 모델이 정답을 엿보는 타깃 누수 가 생긴다. 이를 막으려고 K-fold 타깃 인코딩(각 fold의 통계를 다른 fold로 산출)이나 스무딩(전체 평균과 범주 평균을 표본 수로 가중)을 쓴다. 시험에서는 "고카디널리티 → 원핫은 차원 폭발, 타깃 인코딩은 누수 주의"라는 트레이드오프가 핵심이다.
⚠️ 함정 : One-Hot 인코딩 시 테스트셋에 학습 때 못 본 새 범주가 나오면 에러가 난다. handle_unknown="ignore"로 미지의 범주를 모두 0 벡터로 처리하도록 설정해야 운영에서 안전하다.
표본이 극히 적은 범주(예: 그 도시의 데이터가 3건)에 타깃 인코딩을 그대로 적용하면 값이 극단적으로 튄다. 스무딩으로 전체 평균 쪽으로 끌어당겨야 한다.
비닝은 연속형 변수를 구간(bin)으로 나눠 범주형처럼 다루는 기법이다.
방식 설명 예시 주의 등폭(equal-width) 값 범위를 동일 폭으로 분할 0–10, 10–20, 20–30 치우친 분포면 한 구간에 몰림 등빈도(equal-frequency) 각 구간에 같은 수의 샘플 사분위수 기반 경계가 데이터에 의존 도메인 기반 의미 있는 경계로 분할 나이 → 미성년/청년/중년/노년 도메인 지식 필요
비닝의 효과:
비선형 관계 포착 : 선형 모델이 "나이가 30~40에서 구매율 급증" 같은 비선형 패턴을 구간 더미로 학습할 수 있다.
이상치·노이즈 완화 : 극단값이 같은 최상위 구간에 묶여 영향이 줄어든다.
해석 용이성 : "고소득 구간"이 연속 소득보다 설명하기 쉽다.
단점은 정보 손실 이다. 구간 내 미세한 차이가 사라진다.
import pandas as pd
# 등폭 비닝
df[ "age_bin" ] = pd.cut(df[ "age" ], bins = [ 0 , 18 , 35 , 60 , 120 ],
labels = [ "minor" , "young" , "middle" , "senior" ])
# 등빈도 비닝 (사분위)
df[ "income_q" ] = pd.qcut(df[ "income" ], q = 4 , labels = [ "Q1" , "Q2" , "Q3" , "Q4" ])
비닝은 모델의 편향-분산 트레이드오프를 조정하는 도구다. 연속값을 그대로 쓰면 선형 모델은 단조 직선 관계만 표현하지만(높은 편향), 구간 더미로 바꾸면 각 구간에서 독립적인 효과를 학습해 비선형성을 잡는다(편향 감소). 다만 구간을 너무 잘게 나누면 각 구간의 표본이 적어져 추정이 불안정해진다(분산 증가). 등빈도 비닝은 각 구간 표본 수를 균등하게 해 이 분산 문제를 완화한다.
트리·부스팅 모델에 비닝을 적용해도 얻는 것이 거의 없다. 트리는 이미 분할점을 스스로 찾아 비선형성을 표현하기 때문이다. "어떤 전처리가 효과가 작은가"를 묻는 문제에서는 모델 종류가 곧 단서 다.
스케일링·인코딩·비닝이 "형태를 바꾸는" 작업이라면, 파생 피처는 "없던 신호를 만드는" 작업이다.
비율 피처 : 금액 그 자체보다 금액 / 평균금액, 부채 / 소득이 더 강한 신호일 때가 많다.
상호작용 피처 : 두 피처의 곱(나이 × 소득)으로 "고소득 중년"처럼 조합 효과를 표현한다.
다항 피처 : x², x³를 추가해 선형 모델이 곡선 관계를 표현하게 한다.
집계 피처 : 사용자별 최근 30일 평균 구매액처럼 그룹 통계를 붙인다.
다항·상호작용은 차원을 빠르게 늘려 과적합을 부른다. 피처 3개에 2차 다항을 걸면 10개가 되고, 10개면 66개가 된다. 정규화(Ridge/Lasso)와 함께 쓰거나, 트리 모델이라면 애초에 필요 없는 경우가 많다.
집계 피처는 집계 시점 을 잘못 잡으면 누수가 된다. "이 사용자의 전체 기간 평균 구매액"은 예측 시점 이후 데이터를 포함할 수 있다. 반드시 예측 시점 이전 데이터만으로 집계해야 한다.
피처를 만들었으면 줄이는 일도 해야 한다. 불필요한 피처는 과적합·학습 시간·해석 난이도를 모두 키운다.
방식 방법 특징 필터(filter) 상관계수, 분산, 카이제곱 등 통계로 사전 선별 빠르지만 모델과 무관 래퍼(wrapper) 전진 선택·후진 제거로 실제 성능을 보며 선택 정확하지만 비용이 크다 임베디드(embedded) 모델 학습 중 자동 선택(Lasso, 트리 중요도) 실용적, 모델에 특화됨
다중공선성 : 서로 강하게 상관된 피처가 여럿이면 선형 모델의 계수 해석이 불안정해진다. 하나만 남기거나 PCA로 합친다.
상수·준상수 컬럼 : 값이 거의 하나뿐인 컬럼은 정보가 없으니 제거한다.
ID 컬럼 : 사용자 ID를 그대로 넣으면 모델이 개별 행을 외우는 과적합이 생긴다. 임베딩이나 집계로 바꿔야 한다.
모델 스케일링 원핫 비닝 결측 대치 선형/로지스틱 회귀 필수 필수(명목형) 도움 됨 필요 SVM 필수 필수 도움 됨 필요 KNN / K-means 필수 필수 보통 필요 신경망 필수 필요(또는 임베딩) 보통 필요 PCA 필수 필요 부적합 필요 Decision Tree / RF 불필요 필요(숫자 입력) 효과 작음 필요 XGBoost / LightGBM 불필요 필요(숫자 입력) 효과 작음 필요(일부 자체 처리)
다음 글에서는 날짜·텍스트 같은 특수 데이터의 특성 공학과 고차원 범주형 처리를 본다.
특성 공학(feature engineering) : 원시 데이터를 모델이 잘 학습할 수 있는 입력 피처로 바꾸는 작업.
정규화(Min-Max) : 값을 [0,1] 범위로 눌러 담는 스케일링. 이상치에 매우 민감하다.
표준화(Z-score) : 평균 0, 분산 1이 되도록 바꾸는 스케일링. 선형모델·신경망의 기본.
RobustScaler : 중앙값과 IQR을 써서 이상치에 강건하게 스케일을 맞추는 방법.
단조 변환에 불변 : 값의 크기 순서만 유지되면 결과가 같은 성질. 트리 모델이 여기에 해당한다.
명목형 / 순서형 : 순서가 없는 범주(색깔) / 순서가 있는 범주(등급).
카디널리티(cardinality) : 범주형 변수의 고유값 개수. 수천 개면 고카디널리티다.
Target Encoding : 범주를 그 범주의 타깃 평균으로 바꾸는 인코딩. 누수에 주의해야 한다.
타깃 누수 : 예측하려는 정답 정보가 피처에 섞여 들어가 성능이 부풀려지는 사고.
비닝(binning) : 연속값을 구간으로 묶어 범주처럼 다루는 기법. 비선형성을 얻고 정보를 잃는다.
📝 연습 문제 선택지를 클릭하면 정답·해설이 펼쳐집니다.
다음 중 입력 피처 스케일링이 필요 없는 알고리즘은?
A K-최근접 이웃(KNN) B 서포트 벡터 머신(SVM) C XGBoost (트리 부스팅) D 로지스틱 회귀 "색깔(빨강/파랑/초록)"처럼 순서가 없는 명목형 변수를 선형 회귀에 넣으려 한다. 가장 적절한 인코딩은?
A Label Encoding (빨강=0, 파랑=1, 초록=2) B One-Hot Encoding C 그대로 문자열 입력 D Min-Max 정규화 우편번호처럼 수천 개의 고유값을 가진 고카디널리티 범주형 변수를 인코딩할 때, 차원 폭발을 피하지만 데이터 누수에 주의해야 하는 기법은?
A One-Hot Encoding B Target Encoding C Ordinal Encoding (무작위 정수) D Standard Scaling Min-Max 정규화를 사용할 때 한 변수에 극단적 이상치가 존재한다. 이때 발생하는 문제와 대안으로 옳은 것은?
A 이상치가 max를 끌어올려 나머지 값이 0 근처로 압축됨 → RobustScaler 사용 B 정규화 결과 범위가 [0,1]을 벗어남 → 표준화 사용 C 이상치가 자동 제거됨 → 추가 처리 불필요 D 평균이 1이 됨 → Min-Max 재적용 선형 모델이 "나이가 특정 구간에서 구매율이 급변하는" 비선형 관계를 포착하도록 돕는 특성 공학 기법은?
A 표준화 B 비닝(구간화) C 행 삭제 D Label Encoding