최종 프로젝트

Chapter.9 최종 실전 자동화 프로젝트 (12)

devjjun 2026. 7. 13. 20:54

TIL(Today I Learned)


1️⃣최종 프로젝트(10)

908 샘플 × 2,881 컬럼짜리 초고차원 제조 데이터를 누수 없이 2,876 → 549/334개 피처로 줄이고, 최종적으로 18~75개 피처만으로 성능의 99%를 확보한 과정을 정리한다.

1. 왜 전처리가 필요했나

 

데이터는 908 샘플 × 2,881 컬럼(센서 피처 2,876개 + 제품 코드 T·A·O). 타깃(Y_Class)은 정상 640 vs 불량 124/144로 편중된 3-클래스다.

전처리가 필수였던 이유는 다섯 가지다.

  1. 고차원 — 피처(2,876) ≫ 샘플(908)이라 과적합 위험이 구조적으로 크다.
  2. 위장 결측999, -9999 같은 placeholder가 실제 결측을 숫자로 은폐하고 있다. 이를 NaN으로 통일하는 작업을 최우선으로 해야 이후의 결측률·분산 계산이 왜곡되지 않는다.
  3. 무정보 컬럼 — 완전결측·상수·저분산 센서가 다수.
  4. 다중공선성 — 센서 간 상관이 높아 정보가 중복된다.
  5. 클래스 불균형 — macro-F1 평가와 층화 추출이 필요해지는 이유.

2. 10단계 전처리 파이프라인

전처리는 준비 → 정제(Cleaning) → 차원 축소(Reduction) → 인코딩·결측 정책 흐름으로 구성했다.

국면 단계 내용
준비 1–2 제품별 분리(A_31 / T·O_31 두 트랙), 타깃·ID·시간 등 누수 컬럼 제거
정제 3–5 위장 결측 → NaN 통일(최우선), 완전결측 제거, 결측 60%↑ 제거
차원 축소 6–8 상수·제로분산 제거, 저분산(정규화 분산 < 0.01) 제거, 고상관(|corr| > 0.95) 제거
인코딩·결측 정책 9–10 LINE 원-핫 인코딩(drop_first), 남은 NaN은 대체하지 않음

 

핵심 설계 결정 두 가지.

  • 제품별 분리: 결측 구조의 원인이 '제품'이다. A 계열과 T·O 계열은 측정하는 센서 구성 자체가 다르므로, 하나의 글로벌 파이프라인으로 처리하면 안 된다.
  • 결측 유지: 결측이 MNAR(Missing Not At Random)이므로 평균/중앙값 대치는 정보를 왜곡한다. 대신 XGBoost·LightGBM 같은 NaN-native 트리 모델에 결측을 그대로 넘긴다.

3. 전처리 결과 — 제품마다 제거 분포가 다르다

  • T·O_31: 완전결측이 2,195개로 압도적 → 제품별 센서 구성 차이의 직접 증거
  • A_31: 고상관(764)·결측 60%↑(612)에서 집중 제거
  • 결과: A_31 2,876 → 549 (81%↓), T·O_31 2,876 → 334 (88%↓)

제거 분포가 제품마다 다르다는 사실 자체가, 개별 파이프라인 적용이 타당하다는 사후 근거가 된다.

4. 피처선택 파이프라인 — 4단계 + Nested CV

피처선택은 싼 필터 → 통계적 검증 → 개수 확정 순서로, 계산 비용이 낮은 것부터 배치했다.

  1. 값 기반 필터 — 중복·상수·저분산 피처 저비용 제거
  2. 상관 클러스터링 — 다중공선성 피처를 클러스터 대표 1개로 압축
  3. 기여도 산출 — permutation + SHAP, 3개 모델 교차 확인
  4. 성능곡선 + 1-SE rule — 최종 피처 개수를 데이터로 확정

검증 뼈대는 Nested 3×3 CV다. 바깥 3-fold는 채점만, 안쪽 3-fold는 선택만 담당한다. 선택과 채점을 물리적으로 분리하고 모든 단계를 각 fold의 train에서만 fit하기 때문에 성능 추정이 부풀려지지 않는다.

4-1. 상관 클러스터링

거리 = 1 − |상관계수|로 계층적 클러스터링을 하고, 상관 0.9 컷에서 클러스터 대표만 남긴다. 상관된 피처를 방치하면 뒤의 기여도 측정에서 중요도가 서로 나뉘어 과소평가되기 때문에, 기여도 산출보다 먼저 수행해야 한다. 결과: A 계열 1,175 → 1,099개.

4-2. 기여도 — permutation + SHAP

관점이 다른 두 지표를 함께 본다.

  • Permutation importance: 그 피처를 섞으면 macro-F1이 얼마나 떨어지나 → 전역 성능 기여
  • SHAP mean |contribution|: 각 예측을 평균에서 얼마나 밀어냈나 → 예측 단위 기여

X318 · X1152 · X1560처럼 두 지표 모두 상위인 피처는 확실한 신호, 한쪽만 상위인 피처는 추가 검토 대상으로 분류한다.

4-3. 성능곡선 + 1-SE rule

 

"몇 개 남길까"를 감이 아니라 데이터로 확정하는 단계다. 피처 개수를 늘려가며 3-fold macro-F1을 측정하고, 최고 성능 − 1 표준오차를 임계선으로 삼아 그 위로 올라오는 가장 적은 피처 개수를 선택한다. 성능이 통계적으로 동급이면 더 단순한 모델을 고른다 

 

실측 결과가 흥미롭다. 18~75개면 성능의 99%를 확보하고, 1,099개를 전부 쓰면 오히려 0.64로 하락한다. "피처는 많을수록 좋다"는 이 데이터에서 명확히 틀렸다.

6. 정리

# 원칙 내용
01 제품군별 독립 결측 구조의 원인이 제품 → A / T·O 분리, LINE은 피처로
02 결측 유지 MNAR이므로 대치는 정보 왜곡 → NaN-native 트리 모델
03 단계적 피처선택 싼 필터 → 상관 압축 → 기여도 → 성능곡선(1-SE)
04 정직한 검증 Nested 3×3 CV로 선택·채점 분리, 위장 결측 정규화는 최우선

 

7. 튜터링 피드백 

  • 차원축소 없이 그대로 진행 => 축소 더 해보면 좋은데 이건 나중에.
  • 퀄리티 예측 후 임계치 설정은 어쩔 수 없이 하드코딩 해야 한다.
  • 실제로 회귀 예측보다 다이렉트 분류가 더 잘됨 = 근데 그렇게 하면 안된다.
  • 내일 추가 컬럼 정보 나가니 내일 설명 예정

💡 느낀점

결측을 무작정 채우기 전에 왜 비어 있나 생각했다. 그래서 대치 대신 NaN을 그대로 두는 게 맞다는 결론에 도달했다. 제품군을 나눈 것도 데이터를 뜯어보니 애초에 센서 구성이 다른 두 집단이었기 때문이다. 성능곡선을 그려보니 피처를 다 쓰면 오히려 성능이 떨어졌다. 많을수록 좋다는 게 착각이었다는 걸 숫자로 확인한 순간이 가장 기억에 남는다. 마지막으로 Nested CV로 선택과 채점을 분리하면서, 성능을 부풀리지 않고 정직하게 검증하는 게 중요하다고 생각되어 채택하였다.