스파르타클럽 내일배움캠프 QA/QC 5기 04/20 TIL

2026. 4. 20. 20:15내일배움캠프 TIL

오늘은 머신러닝과 라이브러리 심화 강의를 들었다.

이상치

관측된 데이터 범위에서 크게 벗어난 값. 삭제 여부는 분석가의 판단이며, 도메인·비즈니스 맥락을 먼저 고려해야 한다.

탐지 방법 2가지

방법 기준 제한

ESD (표준편차 기반) 평균 ± 3σ를 벗어난 값 비대칭 분포, 샘플 적을 때 제한
IQR (사분위수 기반) Q3 + 1.5×IQR 초과 또는 Q1 - 1.5×IQR 미만 동일하게 비대칭·소규모 데이터에 제한
# ESD
upper = np.mean(data) + 3 * np.std(data)
lower = np.mean(data) - 3 * np.std(data)

# IQR
Q1 = df['col'].quantile(0.25)
Q3 = df['col'].quantile(0.75)
IQR = Q3 - Q1
upper = Q3 + 1.5 * IQR
lower = Q1 - 1.5 * IQR

# 조건 필터링으로 삭제
df = df[df['col'] < upper]

이상치는 주관적인 값이다. 삭제 시 데이터 품질은 좋아지지만 정보 손실이 따른다. 이상치 탐지를 발전시키면 사기 탐지, 사이버 보안 같은 이상 탐지(Anomaly Detection) 분야로 이어진다.

결측치

존재하지 않는 데이터. 이상치와 달리 값 자체가 없는 경우.

처리 방법

데이터 유형 대치 방법

수치형 평균값 대치 (기본), 이상치 많으면 중앙값 대치
범주형 최빈값 대치
# 간단한 삭제
df.dropna(axis=0)  # 행 삭제
df.dropna(axis=1)  # 열 삭제

# 값으로 대치
df.fillna(df['col'].mean())

# sklearn으로 대치
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean')  # 'median', 'most_frequent'
imputer.fit_transform(X)

평균값은 이상치에 흔들리기 때문에 이상치가 많은 데이터에서는 중앙값이 더 안정적이다. 더 정교한 방법으로는 IterativeImputer(회귀 대치)나 KNNImputer(K 최근접 이웃 대치)도 있다.

인코딩

머신러닝 모델은 숫자만 처리할 수 있어서 범주형 데이터를 수치로 변환하는 과정이 필요.

레이블 인코딩 (Label Encoding)

  • 각 범주에 고유 정수를 할당 (1등급→0, 2등급→1, 3등급→2)
  • 장점: 간단하고 처리가 쉬움
  • 단점: 순서가 없는 데이터에 쓰면 모델이 크기 차이에 의미를 부여해 잘못 해석할 수 있음
  • sklearn.preprocessing.LabelEncoder

원-핫 인코딩 (One-Hot Encoding)

  • 각 범주를 이진 벡터로 변환 (빨강→[1,0,0], 파랑→[0,1,0], 초록→[0,0,1])
  • 장점: 순서 오해 없이 명목형 데이터 표현 가능
  • 단점: 범주 수가 많을수록 차원이 폭발적으로 증가(차원의 저주), 과적합 유발 가능
  • pd.get_dummies 또는 sklearn.preprocessing.OneHotEncoder

순서가 있는 범주형(등급, 사이즈) → 레이블 인코딩, 순서 없는 범주형(혈액형, 지역) → 원-핫 인코딩

스케일링

수치형 데이터의 단위·범위가 서로 다를 때, 모델 학습에 미치는 영향을 보정하기 위해 수행.

방법 수식 특징 sklearn

표준화(Standardization) (x - mean) / std → 평균 0, 표준편차 1 이상치·비대칭 분포에 유용, 범위 미정 StandardScaler
정규화(Normalization) (x - min) / (max - min) → 0~1 범위 명확, 이상치에 민감 MinMaxScaler
로버스트 스케일링(Robust) (x - median) / IQR 이상치 영향 최소화 RobustScaler
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler

scaler = StandardScaler()
scaler.fit(X_train)         # 반드시 train 데이터로만 fit!
X_train_scaled = scaler.transform(X_train)
X_test_scaled  = scaler.transform(X_test)

스케일러는 train 데이터로만 fit하고 test 데이터에는 transform만 적용해야 데이터 누수(data leakage)를 방지할 수 있다.

데이터 분리

과적합(Overfitting)이란? 훈련 데이터에만 지나치게 최적화되어 새로운 데이터에서 성능이 떨어지는 현상. 수능 준비 비유: 3월 모의고사만 외우면 실전에서 틀린다.

과적합의 원인: 모델 복잡도 과다, 데이터 양 부족, 학습 반복 과다, 데이터 불균형

해결책: 학습/테스트 데이터 분리

  • 학습 데이터(Train Data): 모델 학습용 (보통 70%)
  • 테스트 데이터(Test Data): 모델 평가용 (보통 30%)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.3,      # 테스트 비율
    shuffle=True,       # 섞기
    random_state=42     # 재현 가능하도록 고정
)

과적합 판단 기준: Train F1 Score 0.97 / Test F1 Score 0.4 → 과적합 / Train 0.98 / Test 0.95 → 정상

전처리 순서 정리

이상치 탐지 및 처리
    ↓
결측치 처리 (수치형: 평균/중앙값, 범주형: 최빈값)
    ↓
인코딩 (범주형 → 수치형)
    ↓
스케일링 (수치형 범위 보정)
    ↓
데이터 분리 (train / test split)
    ↓
모델 학습 & 평가

타이타닉 전체 실습 흐름

이론으로 배운 전처리 파이프라인을 실제 데이터에 end-to-end로 적용하는 실습이다.

전체 실습 파이프라인

1. 데이터 로드 & train/test 분리
2. EDA (분포 확인 & 이상치 확인)
3. 결측치 처리
   - Age (수치형) → 평균값 대치
   - Embarked (범주형) → 최빈값 대치
   - Cabin, Name → 불필요 컬럼 삭제
4. 인코딩
   - Pclass, Sex → 레이블 인코딩
   - Embarked → 원-핫 인코딩
5. 스케일링
   - Age, Fare, SibSp+Parch (수치형) → StandardScaler
6. 모델 수립 (LogisticRegression)
7. 평가 (accuracy, f1_score)

변수 처리 요약

변수 유형 처리

Age 수치형, 결측 있음 평균값 대치 후 스케일링
Fare 수치형 스케일링
SibSp + Parch 수치형 Family로 합산 후 스케일링
Pclass 순서 있는 범주형 레이블 인코딩
Sex 순서 없는 범주형 (2개) 레이블 인코딩
Embarked 순서 없는 범주형 (3개+) 원-핫 인코딩
Cabin, Name 불필요 삭제

교차 검증

고정된 테스트 데이터로만 평가하면 그 테스트 셋에 과적합될 수 있다는 문제를 해결하기 위한 방법.

교차 검증(Cross Validation)이란? 데이터셋을 여러 하위 집합으로 나눠 돌아가며 검증 데이터로 사용하는 방법.

K-Fold Validation

Train 데이터를 K개 Fold로 나누고, 매 split마다 1개 Fold를 검증용으로, 나머지를 학습용으로 사용. K번 반복 후 평균 성능을 최종 평가로 삼음.

예시 (K=5): Split 1에서 Fold1 검증 / Split 2에서 Fold2 검증 / ... / Split 5까지 반복 → 최종 Test data로 평가

from sklearn.model_selection import KFold, StratifiedKFold

# 일반 K-Fold
kf = KFold(n_splits=5, shuffle=True, random_state=42)

# 클래스 불균형 데이터일 때
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

for train_idx, val_idx in kf.split(X):
    X_train, X_val = X[train_idx], X[val_idx]
    y_train, y_val = y[train_idx], y[val_idx]
    model.fit(X_train, y_train)
    print(model.score(X_val, y_val))
  • KFold: 일반 교차 검증
  • StratifiedKFold: Y 레이블이 불균형할 때 사용 (각 Fold에서 클래스 비율 유지)
  • 데이터가 부족할 때 반복 학습으로 더 신뢰할 수 있는 성능 평가 가능

GridSearch

하이퍼 파라미터(Hyper Parameter)란? 모델을 구성하는 입력 값 중 사람이 직접 설정할 수 있는 값. 예: 로지스틱회귀의 C, 결정 트리의 max_depth 등.

GridSearch는 지정한 하이퍼 파라미터 조합을 모두 시도해서 가장 좋은 조합을 자동으로 찾아주는 방법이다.


전체 데이터 분석 프로세스 정리

Raw Data (전체)
├── Train Data (70%)
│   ├── (1) 데이터 전처리 (이상치, 결측치, 인코딩, 스케일링)
│   ├── train-train data (70%) → 모델 학습
│   └── train-validation data (30%) → 피드백 & K-Fold 교차 검증
└── Test Data (30%)
    ├── (1) 동일한 전처리 적용 (fit은 train으로만!)
    └── 예측 → 평가 (True Y와 비교)

핵심 포인트: 스케일러·인코더를 train 데이터로만 fit하고, test에는 transform만 적용해야 데이터 누수를 방지할 수 있다.