모델 학습에서 데이터 과학자가 시간의 70~80%를 쓰는 곳은 화려한 알고리즘 튜닝이 아니라 특성 공학(feature engineering)이다. raw 데이터는 결측치가 뚫려 있고, 단위가 제각각이며, "서울/부산/대구" 같은 문자열이 섞여 있다. 모델은 이걸 그대로 못 읽는다.
MLA-C01 시험은 "이 데이터에 어떤 변환을 적용해야 하는가"를 시나리오로 끊임없이 묻는다. 알고리즘 이름보다 언제 어떤 변환을 고르는가가 핵심이다.
[raw 데이터]
│ 숫자 단위가 제각각 → ① 스케일링
│ 문자열 범주가 섞임 → ② 인코딩
│ 빈 칸이 뚫려 있음 → ③ 결측치 처리
│ 극단값이 튀어 있음 → ④ 이상치 처리
│ 분포가 한쪽으로 치우침 → ⑤ 수치 변환·구간화
v
[모델이 읽을 수 있는 수치 행렬]
연봉(예: 50,000,000)과 나이(예: 35)를 같은 모델에 넣으면, 거리 기반 알고리즘(KNN, K-Means)이나 경사하강법 기반 모델(선형회귀, 신경망)은 단위가 큰 연봉에 압도된다. 두 점 사이 유클리드 거리를 계산하면 나이 차이는 무시되고 연봉 차이만 반영된다.
from sklearn.preprocessing import StandardScaler, MinMaxScaler# 표준화(Standardization): 평균 0, 표준편차 1로 변환# z = (x - mean) / stdscaler = StandardScaler()X_std = scaler.fit_transform(X_train)# 정규화(Normalization): [0, 1] 범위로 변환# x' = (x - min) / (max - min)minmax = MinMaxScaler()X_norm = minmax.fit_transform(X_train)
스케일러 선택표
스케일러
변환
이상치 영향
결과 범위
언제
StandardScaler
(x−평균)/표준편차
받음
대체로 −3~3
정규분포에 가까울 때, 일반적 기본값
MinMaxScaler
(x−최소)/(최대−최소)
크게 받음
정확히 0~1
범위가 명확할 때(픽셀 0~255), 신경망 입력
RobustScaler
(x−중앙값)/IQR
적게 받음
가변
이상치가 많을 때
알고리즘별 스케일링 필요 여부 — 시험에서 바로 갈리는 지점이다.
알고리즘 계열
스케일링
이유
KNN, K-Means
필수
거리 계산이 단위에 지배됨
선형/로지스틱 회귀, SVM
필수
경사하강 수렴 속도, 정규화 항의 공정성
신경망
필수
활성화 포화·수렴 불안정 방지
결정트리, Random Forest, XGBoost
불필요
분할 기준이 "임계값 비교"라 단위와 무관
경사하강법은 손실 함수 표면을 따라 내려가는데, 특성 스케일이 제각각이면 손실 표면이 길쭉한 타원(elongated contour)이 된다. 이러면 gradient가 최저점을 향해 직선으로 못 가고 지그재그로 진동하며 수렴이 느려진다. 스케일링으로 모든 축을 비슷한 범위로 맞추면 손실 표면이 동심원에 가까워져 수렴이 빨라진다.
⚠️ 함정: 스케일러는 반드시 train 데이터로만 fit하고, 그 통계량으로 validation/test를 transform해야 한다. test 데이터까지 포함해 fit하면 test 정보가 학습에 새어 들어가는 데이터 누수(data leakage)가 발생한다. scaler.fit_transform(X_train) 후 scaler.transform(X_test)가 정답이다.
"색상: 빨강/파랑/초록" 같은 범주형 데이터는 숫자로 바꿔야 한다. 방법 선택이 모델 성능을 크게 가른다.
import pandas as pdfrom sklearn.preprocessing import OneHotEncoder, LabelEncoder# One-Hot Encoding: 각 범주를 별도 이진 열로# 빨강 -> [1,0,0], 파랑 -> [0,1,0], 초록 -> [0,0,1]ohe = pd.get_dummies(df['color'])# Label Encoding: 각 범주에 정수 부여# 빨강 -> 0, 파랑 -> 1, 초록 -> 2le = LabelEncoder()df['color_encoded'] = le.fit_transform(df['color'])
인코딩 선택표
방법
적합한 범주
차원 증가
위험
One-Hot
명목형(순서 없음), 저카디널리티
범주 수만큼
고카디널리티에서 차원 폭발
Ordinal/Label
서열형(저/중/고, S/M/L)
없음
명목형에 쓰면 가짜 순서를 학습
타깃 인코딩
고카디널리티 명목형
없음
데이터 누수에 취약
빈도 인코딩
고카디널리티 명목형
없음
빈도가 같은 범주를 구분 못 함
임베딩(딥러닝)
초고카디널리티
지정 차원
학습 데이터·시간이 필요
One-Hot 인코딩은 순서가 없는 명목형(nominal) 범주에 쓴다. 빨강·파랑·초록 사이엔 크기 관계가 없으므로, Label 인코딩으로 0/1/2를 주면 모델이 "초록(2) > 파랑(1)"이라는 잘못된 순서를 학습한다. Label/Ordinal 인코딩은 순서가 있는 서열형(ordinal) 범주에 적합하다.
범주가 수천 개일 때(우편번호, 상품 ID)는 One-Hot으로 펼치면 차원이 폭발(curse of dimensionality)한다. 이럴 땐 타깃 인코딩·빈도 인코딩·임베딩을 쓴다.
타깃 인코딩은 강력하지만 데이터 누수에 취약하다. "범주 A의 타깃 평균"을 계산할 때 그 행 자신의 타깃을 포함하면 정답을 미리 본 셈이 된다. 이를 막으려면 K-fold 방식으로 다른 fold의 통계만 쓰거나, 스무딩(smoothing)을 적용해 표본이 적은 범주는 전체 평균 쪽으로 끌어당긴다.
결측 메커니즘은 통계학에서 3가지로 나뉜다. MCAR(Missing Completely At Random, 완전 무작위), MAR(Missing At Random, 다른 관측 변수에 의존), MNAR(Missing Not At Random, 결측값 자체에 의존). MCAR이면 단순 삭제도 편향을 안 만들지만, MNAR(예: 고소득자가 소득을 안 적는 경향)이면 단순 대치가 심각한 편향을 만든다. 평균 대치는 분산을 인위적으로 줄여 상관관계를 약화시킨다.
부동산 가격 예측 모델에서 "면적" 열에 99999가 들어 있었다. 이는 결측을 99999로 코딩한 sentinel value였는데, 팀이 모르고 그대로 학습시켜 모델이 모든 집을 초고가로 예측했다. raw 데이터의 코딩 규약(데이터 사전, data dictionary)을 먼저 확인하는 것이 특성 공학의 0단계다.
⚠️ 함정: 사기 탐지·이상 탐지에서 이상치는 노이즈가 아니라 정답 신호다. IQR로 걸러 제거하면 양성 클래스가 통째로 사라진다. 이상치 처리는 항상 "이 값이 오류인가, 의미 있는 사건인가"를 도메인 맥락에서 먼저 판단해야 한다.
치우친(skewed) 분포는 로그 변환으로 정규분포에 가깝게 만들면 선형 모델 성능이 오른다. 연속형을 구간(bin)으로 나누는 binning은 나이를 "10대/20대/30대"로 묶어 비선형 관계를 단순화하거나 이상치 영향을 줄인다.
import numpy as npimport pandas as pd# 로그 변환: 오른쪽으로 긴 꼬리(소득, 가격)를 압축df['log_income'] = np.log1p(df['income']) # log(1+x), 0 처리 안전# 구간화(binning): 연속형 -> 범주형df['age_group'] = pd.cut(df['age'], bins=[0, 18, 35, 60, 100], labels=['청소년', '청년', '중년', '노년'])
변환
목적
대가
로그 변환
오른쪽 긴 꼬리를 압축해 정규에 가깝게
해석이 로그 단위로 바뀜
제곱근 변환
로그보다 약한 압축
위와 동일
구간화(binning)
비선형 관계 단순화, 이상치 완화
구간 내 정보 손실
다항 특성
곡선 관계를 선형 모델이 잡게 함
차원 증가, 과적합 위험
SageMaker 빌트인 알고리즘 중 일부는 특정 입력 형식을 요구한다. Linear Learner나 XGBoost는 보통 CSV/libsvm/RecordIO-protobuf를 받는데, 대규모 학습에서는 RecordIO-protobuf가 효율적이다. 또 XGBoost는 결측치를 내부적으로 학습 가능한 기본 방향으로 처리하므로 사전 대치가 항상 필요하진 않다. 알고리즘별 입력 요구사항을 아는 것도 특성 공학의 일부다.