특성 공학

src/content/documents/machine-learning/feature-engineering-overview.json

한 줄 정의

특성(feature) 공학은 원시 데이터를 모델이 문제를 풀기 좋은 입력으로 선택·변환·생성하는 과정이다. 깨끗한 데이터라도 업무 의미가 약한 열만 있으면 예측에는 한계가 있다.

원문 PDF의 표현을 빌리면 흐름은 ‘나쁜 데이터 → 나쁜 예측’, ‘깨끗한 데이터 → 제한된 예측’, ‘더 나은 특성 → 더 나은 예측’이다. 여기서 더 나은 특성이란 답을 미리 알려 주는 열이 아니라, 예측 시점에도 얻을 수 있고 업무 의미가 있는 입력이다.

특성과 특성 공학을 구분하자

특성은 모델에 넣는 한 개의 입력 변수다. 고객의 가입일, 최근 30일 구매 횟수, 평균 결제액이 예다. 특성 공학은 기존 열을 그대로 쓰는 데서 멈추지 않고 분석 목적에 맞게 표현을 바꾸는 일 전체를 말한다.

  • 선택: 예측에 쓸 수 있고 의미 있는 열만 남긴다.

  • 변환: 로그 변환, 스케일링, 범주 인코딩처럼 모델이 다루기 쉬운 표현으로 바꾼다.

  • 생성: 주문일과 가입일로 가입 기간을 만들거나, 구매액을 방문 횟수로 나눠 객단가를 만든다.

  • 검증: 새 특성이 교차검증 성능과 운영 가능성을 실제로 높이는지 확인한다.

분석 과정에서 어디에 들어갈까

PDF는 분석 업무를 비즈니스 이해 → 가설 수립 → 데이터 준비 → 모델 정의 → 모델 평가 → 시스템 적용으로 정리한다. 특성 공학은 주로 데이터 준비 단계에 있지만, 실제로는 앞뒤 단계를 계속 왕복한다.

  • 비즈니스 이해: 무엇을 언제 예측해 어떤 행동으로 연결할지 정한다.

  • 가설 수립: 예를 들어 ‘최근 문의 증가가 이탈 신호일 것’처럼 검증 가능한 질문을 만든다.

  • 데이터 준비: 데이터 정의, 품질 점검, EDA, 전처리, 특성 선택·생성을 수행한다.

  • 모델 정의와 평가: 기준 모델과 비교해 새 특성이 보지 못한 데이터에서도 도움이 되는지 확인한다.

  • 시스템 적용: 예측 시점에 같은 특성을 계산할 수 있는지, 지연·주기·모니터링을 설계한다.

좋은 특성은 정확도만 높이는 열이 아니다. 운영 환경에서도 같은 정의로 재현할 수 있고, 개인정보·비용·지연 제약을 지키며, 시간이 흘러도 의미를 모니터링할 수 있어야 한다.

예측 시점을 먼저 고정하는 이유

‘고객이 다음 30일 안에 이탈하는가’를 매주 월요일 예측한다고 하자. 월요일 이후 발생한 해지 접수나 최종 해지 사유는 학습 데이터에 있더라도 실제 월요일 예측 때는 모른다. 이를 입력에 넣으면 데이터 누수(data leakage)가 생긴다.

특성 하나마다 ‘이 값은 실제 예측 시각에 알 수 있는가?’라고 묻는다. 대답이 아니면 성능이 아무리 좋아도 입력에서 제외한다.

누수 없는 작업 순서

  1. 예측 대상, 예측 시점, 관측 기간을 문장으로 고정한다.

  2. 원본 데이터에서 목표값 y와 입력 후보 X를 분리한다.

  3. 먼저 학습·검증(또는 테스트) 데이터로 나눈다. 시간 데이터라면 미래가 과거에 섞이지 않도록 시간 순서를 고려한다.

  4. 결측 대치, 스케일링, 인코딩, 특성 선택처럼 데이터에서 규칙을 배우는 단계는 학습 데이터에만 fit한다.

  5. 학습한 규칙으로 검증·테스트 데이터를 transform하고 성능을 평가한다.

  6. 최종 배포에는 동일한 전처리와 모델을 하나의 파이프라인으로 묶는다.

scikit-learn 공식 가이드는 테스트 데이터에 fit을 호출하지 말고, 전처리 규칙도 학습 데이터에서만 배우라고 설명한다. Pipeline은 이 순서를 코드로 고정해 누수 가능성을 줄인다.

최소 실습: 기준 모델부터 비교하기

아래 예제는 연령과 최근 30일 구매액으로 구매 여부를 예측한다. 먼저 데이터를 나눈 뒤 전처기와 모델을 Pipeline으로 묶는다. 이 작은 구조가 앞으로의 모든 특성 실험 기준점이다.

from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
import pandas as pd

df = pd.DataFrame({
    "age": [22, 35, 41, 29, 52, 46, 31, 27, 38, 49],
    "spend_30d": [10, 80, 120, 30, 200, 160, 55, 20, 95, 180],
    "channel": ["app", "web", "web", "app", "store",
                "store", "app", "web", "app", "store"],
    "purchased": [0, 0, 1, 0, 1, 1, 0, 0, 1, 1],
})
X = df.drop(columns="purchased")
y = df["purchased"]
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)

prep = ColumnTransformer([
    ("num", Pipeline([
        ("impute", SimpleImputer(strategy="median")),
        ("scale", StandardScaler()),
    ]), ["age", "spend_30d"]),
    ("cat", OneHotEncoder(handle_unknown="ignore"), ["channel"]),
])
model = Pipeline([("prep", prep), ("clf", LogisticRegression())])
model.fit(X_train, y_train)
print("train rows:", len(X_train), "test rows:", len(X_test))
print("test predictions:", model.predict(X_test).tolist())
train rows: 7 test rows: 3
test predictions: [1, 0, 0]

이 데이터는 설명용으로 너무 작으므로 점수 자체에는 의미를 두지 않는다. 핵심은 분할 이후 model.fit(X_train, y_train) 한 번으로 전처기의 통계량과 모델을 학습했다는 점이다. 실제 실험에서는 교차검증과 업무 지표를 함께 본다.

특성 아이디어를 업무 질문으로 바꾸기

  • 원시 열: order_amount, visit_count → 질문: 방문 한 번당 얼마를 쓰는가? → 특성: order_amount / visit_count

  • 원시 열: signup_date, prediction_date → 질문: 고객 관계가 얼마나 오래됐는가? → 특성: 가입 경과일

  • 원시 열: 최근 문의 시각들 → 질문: 문의가 갑자기 늘었는가? → 특성: 최근 7일 문의 수 - 이전 7일 문의 수

  • 원시 열: 장비 센서값 → 질문: 평소 수준에서 얼마나 벗어났는가? → 특성: 장비별 이동 평균 대비 편차

아이디어마다 정의, 계산 시점, 단위, 결측 처리, 예상 방향을 기록한다. 그 뒤 기준 모델과 비교해 검증한다. EDA는 이 질문을 발견하는 단계이지, 예쁜 그래프를 많이 만드는 대회가 아니다.

자주 하는 실수

  • 전체 데이터로 결측값 중앙값이나 스케일을 계산한 뒤 분할한다.

  • 고객 ID처럼 거의 고유한 값을 의미 있는 숫자로 오해한다.

  • 예측 이후에만 생기는 상태·처리 결과를 입력으로 쓴다.

  • 테스트 점수를 반복해서 보며 특성을 고르고, 사실상 테스트 세트에 과적합한다.

  • 운영에서는 계산할 수 없는 고비용 집계나 외부 데이터를 쓴다.

  • 새 특성이 성능을 올렸다는 이유만으로 안정성·공정성·설명 가능성 검토를 생략한다.

마지막 점검

  • 문제를 ‘누가, 언제, 무엇을 예측해, 어떤 행동을 하는가’로 설명할 수 있다.

  • 각 특성이 예측 시점에 사용 가능한지 확인했다.

  • 분할 전에 전체 데이터에서 학습한 전처리 규칙이 없다.

  • 같은 분할·지표에서 기준 모델과 새 특성 모델을 비교했다.

  • 배포 환경에서 특성 계산 정의와 주기를 재현할 수 있다.

참고 자료

박병선, 『실전 Feature Engineering』 강의 PDF, 4~9쪽 (2026-08-05 확인)

댓글 0

댓글을 불러오는 중…