TIL
내일배움캠프 본캠프 23일차 - 이상치 처리
수현조
2024. 12. 26. 20:38
1. 이상치 탐지 및 분석
- 이상치 탐지 방법:
- IQR (Interquartile Range):
- Q1(1사분위수), Q3(3사분위수)를 기준으로 IQR 계산.
- 이상치 조건:
- 아래 경계: Q1 - 1.5 * IQR
- 위 경계: Q3 + 1.5 * IQR
- 코드:
Q1 = df[column].quantile(0.25) Q3 = df[column].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
- 박스플롯 시각화:
- sns.boxplot()을 활용하여 이상치 분포 확인.
- 로그 변환 전후, 스케일링 후 이상치가 어떻게 변하는지 비교.
- 변수별 이상치 개수 확인:
- 각 변수에서 이상치 개수를 계산.
- 예시 결과:
CRIM의 이상치 개수: 81 ZN의 이상치 개수: 126 RM의 이상치 개수: 30 ...
- IQR (Interquartile Range):
2. 이상치 처리 방법
- 대체:
- 이상치를 중앙값 또는 평균값으로 대체.
- 중앙값 대체 코드:
df[column] = df[column].apply( lambda x: median_value if x < lower_bound or x > upper_bound else x )
- 제거:
- 이상치를 데이터셋에서 완전히 삭제.
- 코드:
df = df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]
- 로그 변환:
- 극단적인 값을 완화하기 위해 log1p 변환 적용.
- 코드:
df[column] = np.log1p(df[column])
- 스케일링과 결합:
- 스케일링(정규화/표준화) 후 이상치 처리.
3. 처리 후 결과 확인
- 이상치 처리 후에도 여전히 이상치가 남아있었음.
- 추가적으로 다음 방법 시도:
- IQR 완화:
- 경계를 1.5IQR에서 2.5IQR로 변경.
- 클리핑:
- 값의 범위를 강제로 제한.
- 코드:
df[column] = np.clip(df[column], lower_limit, upper_limit)
- IQR 완화:
- 최종 결과:
- 이상치를 대부분 처리했으나, 일부 데이터는 특성상 극단적인 값이 정상일 가능성도 있었음.
4. 모델 성능 비교
이상치 처리 전후로 주요 모델의 성능을 평가:
- 이상치 처리 전:
- Linear Regression:
- MAE: 3.1487
- MSE: 24.9993
- R²: 0.6591
- Random Forest:
- MAE: 2.0639
- MSE: 8.2196
- R²: 0.8879
- Decision Tree:
- MAE: 2.8950
- MSE: 23.3930
- R²: 0.6810
- Linear Regression:
- 이상치 처리 후:
- Linear Regression:
- MAE: 2.3628
- MSE: 10.6851
- R²: 0.6267
- Random Forest & Decision Tree:
- 동일한 성능(MAE: 3.2395, MSE: 17.4723, R²: 0.3897).
- Linear Regression:
- 해석:
- 이상치 제거로 인해 일부 특성이 손실되었고, 이에 따라 모델 성능이 전반적으로 하락.
- 특히 Random Forest의 성능 하락이 두드러짐 → 이상치가 중요한 패턴일 가능성.
5. 주요 교훈
- 이상치는 무조건 제거하지 않고, 데이터의 특성과 상황에 따라 유지할지 완화할지 결정해야 함.
- 이상치 처리 후 반드시 모델 성능을 비교하여, 데이터 품질 개선이 실제로 예측 능력에 도움을 주었는지 확인.
- 처리 후에도 이상치가 남는 경우, 이를 인정하고 다음 단계로 넘어갈 수도 있음.
오늘의 한마디
이상치 처리란 단순히 "제거"가 아닌, 데이터의 특성을 이해하고 최적의 결정을 내리는 과정임을 배웠습니다. 😊