피처 엔지니어링
Feature Engineering
원시 데이터에서 ML 모델에 유용한 특성을 생성하는 과정. 모델 성능에 큰 영향.
Feature Engineering
원시 데이터에서 ML 모델에 유용한 특성을 생성하는 과정. 모델 성능에 큰 영향.
피처 엔지니어링(Feature Engineering)은 원시 데이터에서 머신러닝 모델의 예측 성능을 높이는 유의미한 특성(Feature)을 생성하는 과정입니다. "데이터와 알고리즘이 동일하다면, 피처가 승패를 가른다"는 격언이 있을 만큼 ML 성공의 핵심 요소입니다. 도메인 지식을 바탕으로 특성 변환, 조합, 집계를 수행하며, 모델 성능의 70% 이상이 데이터 품질과 피처에 의해 결정됩니다.
피처 엔지니어링의 주요 기법으로는 특성 생성(수학적 변환, 날짜 분해, 텍스트 임베딩, 집계 통계), 특성 조합(교차 특성, 다항 특성, 비율 특성), 인코딩(One-Hot, Target Encoding, Entity Embedding), 특성 선택(상관관계 분석, 중요도 기반 선택, Recursive Feature Elimination) 등이 있습니다. 시계열 데이터에서는 Lag 피처, 이동 평균, 변화율 등이 중요합니다.
최근에는 Feature Store(Feast, Tecton, Databricks Feature Store)가 피처의 중앙 관리와 재사용을 가능하게 합니다. Feature Store는 피처 정의를 코드로 관리하고, 학습(오프라인)과 추론(온라인)에서 동일한 피처를 일관되게 제공합니다. 피처 버전 관리, 리니지 추적, 실시간 서빙이 가능해져 MLOps의 핵심 인프라로 자리잡았습니다.
자동 피처 엔지니어링(AutoFE)도 발전하고 있습니다. Featuretools는 관계형 데이터에서 자동으로 수백 개의 피처를 생성하고, AutoML 도구들도 피처 선택과 변환을 자동화합니다. 하지만 도메인 지식을 반영한 수동 피처 엔지니어링이 여전히 중요하며, 자동화와 수동 작업의 균형이 필요합니다.
# 피처 엔지니어링 및 Feature Store 활용 예시
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from feast import FeatureStore, Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64, String
# 1. 기본 피처 엔지니어링 함수
def engineer_customer_features(df: pd.DataFrame) -> pd.DataFrame:
"""고객 데이터에서 ML 피처 생성"""
# 날짜/시간 분해
df['signup_dayofweek'] = df['signup_date'].dt.dayofweek
df['signup_month'] = df['signup_date'].dt.month
df['signup_is_weekend'] = df['signup_dayofweek'].isin([5, 6]).astype(int)
df['days_since_signup'] = (datetime.now() - df['signup_date']).dt.days
# 수치 변환 (정규분포화)
df['log_total_spend'] = np.log1p(df['total_spend'])
df['sqrt_order_count'] = np.sqrt(df['order_count'])
# 비율 피처 (Ratio Features)
df['avg_order_value'] = df['total_spend'] / (df['order_count'] + 1)
df['order_frequency'] = df['order_count'] / (df['days_since_signup'] + 1)
# 구간화 (Binning)
df['spend_tier'] = pd.cut(
df['total_spend'],
bins=[0, 100, 500, 2000, np.inf],
labels=['low', 'medium', 'high', 'vip']
)
# 그룹 대비 비율 (Relative Features)
df['spend_vs_segment_avg'] = df['total_spend'] / df.groupby('segment')['total_spend'].transform('mean')
return df
# 2. 시계열 집계 피처 (Rolling/Lag Features)
def create_time_features(df: pd.DataFrame, user_col: str, date_col: str) -> pd.DataFrame:
"""시계열 기반 피처 생성"""
df = df.sort_values([user_col, date_col])
# 이동 평균 (Rolling Mean)
df['revenue_ma_7d'] = df.groupby(user_col)['revenue'].transform(
lambda x: x.rolling(7, min_periods=1).mean()
)
df['revenue_ma_30d'] = df.groupby(user_col)['revenue'].transform(
lambda x: x.rolling(30, min_periods=1).mean()
)
# Lag 피처 (이전 값)
df['revenue_lag_1'] = df.groupby(user_col)['revenue'].shift(1)
df['revenue_lag_7'] = df.groupby(user_col)['revenue'].shift(7)
# 변화율
df['revenue_pct_change'] = df.groupby(user_col)['revenue'].pct_change()
# 누적 피처
df['cumulative_orders'] = df.groupby(user_col).cumcount() + 1
df['cumulative_revenue'] = df.groupby(user_col)['revenue'].cumsum()
return df
# 3. Feast Feature Store 정의
# feature_repo/features.py
# 엔티티 정의 (Primary Key)
customer = Entity(
name="customer_id",
description="고객 고유 식별자"
)
# 오프라인 데이터 소스
customer_source = FileSource(
path="s3://feature-store/customer_features.parquet",
timestamp_field="event_timestamp",
)
# 피처 뷰 정의
customer_features = FeatureView(
name="customer_features",
entities=[customer],
ttl=timedelta(days=1),
schema=[
Field(name="total_spend", dtype=Float32),
Field(name="order_count", dtype=Int64),
Field(name="avg_order_value", dtype=Float32),
Field(name="days_since_signup", dtype=Int64),
Field(name="spend_tier", dtype=String),
Field(name="revenue_ma_7d", dtype=Float32),
Field(name="revenue_ma_30d", dtype=Float32),
Field(name="order_frequency", dtype=Float32),
],
source=customer_source,
online=True, # 온라인 서빙 활성화
)
# 4. Feature Store 사용
fs = FeatureStore(repo_path="feature_repo/")
# 오프라인: 학습 데이터 생성 (Point-in-Time Join)
entity_df = pd.DataFrame({
"customer_id": ["C001", "C002", "C003"],
"event_timestamp": [datetime.now()] * 3,
})
training_df = fs.get_historical_features(
entity_df=entity_df,
features=[
"customer_features:total_spend",
"customer_features:avg_order_value",
"customer_features:revenue_ma_7d",
"customer_features:order_frequency"
]
).to_df()
print(f"학습 데이터: {training_df.shape}")
# 온라인: 실시간 추론용 피처 조회
online_features = fs.get_online_features(
features=[
"customer_features:total_spend",
"customer_features:avg_order_value",
],
entity_rows=[{"customer_id": "C001"}]
).to_dict()
print(f"실시간 피처: {online_features}")
# 5. 자동 피처 엔지니어링 (Featuretools)
import featuretools as ft
# EntitySet 생성
es = ft.EntitySet(id="customer_data")
es.add_dataframe(dataframe_name="customers", dataframe=customers_df, index="customer_id")
es.add_dataframe(dataframe_name="orders", dataframe=orders_df, index="order_id")
es.add_relationship("customers", "customer_id", "orders", "customer_id")
# 자동 피처 생성 (Deep Feature Synthesis)
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_dataframe_name="customers",
agg_primitives=["mean", "sum", "count", "max", "min", "std", "mode"],
trans_primitives=["month", "weekday", "is_weekend", "year"],
max_depth=2
)
print(f"자동 생성된 피처 수: {len(feature_defs)}")