066 이상치 탐지의 이해
키워드: 이상치, anomaly
개요
이상치 탐지(Anomaly Detection)는 정상 패턴에서 벗어난 데이터를 찾는 비지도 학습 기법입니다. 사기 탐지, 설비 이상 감지, 네트워크 침입 탐지 등에 활용됩니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
pycaret[full]>=3.0
이상치란?
정상 데이터 (Normal):
대부분의 데이터가 따르는 패턴
이상치 (Anomaly/Outlier):
정상 패턴에서 크게 벗어난 데이터
●●●●●●●●●
●●●●●●●●●●●●
●●●●●●●●●●●●●● 정상 분포
●●●●●●●●●●●●
●●●●●●●●●
★ 이상치 (Outlier)
★
★
이상치의 유형
1. 점 이상치 (Point Anomaly)
단일 데이터 포인트가 이상한 경우:
import numpy as np
import matplotlib.pyplot as plt
# 066 정상 데이터
np.random.seed(42)
normal = np.random.normal(50, 5, 100)
# 066 점 이상치
outliers = np.array([10, 90, 95])
# 066 시각화
plt.figure(figsize=(10, 4))
plt.scatter(range(len(normal)), normal, label='Normal', alpha=0.7)
plt.scatter([100, 101, 102], outliers, color='red', s=100, label='Outliers')
plt.xlabel('Index')
plt.ylabel('Value')
plt.title('Point Anomaly')
plt.legend()
plt.savefig('point_anomaly.png', dpi=150)
2. 맥락 이상치 (Contextual Anomaly)
특정 상황에서만 이상한 경우:
import numpy as np
import matplotlib.pyplot as plt
# 066 시계열 데이터 (계절성)
t = np.arange(365)
seasonal = 20 * np.sin(2 * np.pi * t / 365) + 50 # 계절 패턴
noise = np.random.normal(0, 2, 365)
data = seasonal + noise
# 066 여름(중간)에 갑자기 낮은 값 = 맥락 이상치
data[180] = 20 # 여름인데 겨울 수준
plt.figure(figsize=(12, 4))
plt.plot(t, data, alpha=0.7)
plt.scatter([180], [20], color='red', s=100, zorder=5, label='Contextual Anomaly')
plt.xlabel('Day')
plt.ylabel('Temperature')
plt.title('Contextual Anomaly (Low value in summer)')
plt.legend()
plt.savefig('contextual_anomaly.png', dpi=150)
3. 집단 이상치 (Collective Anomaly)
개별로는 정상이나 집단으로 이상한 경우:
import numpy as np
import matplotlib.pyplot as plt
# 066 정상 심박수 패턴
t = np.arange(100)
heartbeat = 70 + 5 * np.sin(t * 0.5) + np.random.normal(0, 2, 100)
# 066 집단 이상치: 연속으로 낮은 값
heartbeat[40:50] = 50 + np.random.normal(0, 1, 10) # 갑자기 낮아짐
plt.figure(figsize=(12, 4))
plt.plot(t, heartbeat, alpha=0.7)
plt.axvspan(40, 50, alpha=0.3, color='red', label='Collective Anomaly')
plt.xlabel('Time')
plt.ylabel('Heart Rate')
plt.title('Collective Anomaly')
plt.legend()
plt.savefig('collective_anomaly.png', dpi=150)
이상치 탐지 활용 사례
| 분야 | 활용 사례 |
|---|---|
| 금융 | 신용카드 사기 탐지, 이상 거래 감지 |
| 의료 | 비정상 심전도, 질병 조기 발견 |
| 제조 | 설비 이상 감지, 품질 관리 |
| 보안 | 네트워크 침입 탐지, 이상 행동 감지 |
| IoT | 센서 오작동 탐지, 장비 모니터링 |
이상치 탐지 접근법
1. 통계적 방법
import numpy as np
data = np.array([10, 12, 11, 13, 12, 100, 11, 12])
# 066 Z-score 방법
mean = np.mean(data)
std = np.std(data)
z_scores = (data - mean) / std
outliers_z = np.abs(z_scores) > 2
print(f"Z-score 이상치: {data[outliers_z]}")
# 066 IQR 방법
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1
lower = q1 - 1.5 * iqr
upper = q3 + 1.5 * iqr
outliers_iqr = (data < lower) | (data > upper)
print(f"IQR 이상치: {data[outliers_iqr]}")
2. 거리 기반 방법
# 066 중심에서 먼 데이터를 이상치로
# 066 - K-NN 기반
# 066 - LOF (Local Outlier Factor)
3. 밀도 기반 방법
# 066 주변 밀도가 낮은 데이터를 이상치로
# 066 - DBSCAN
# 066 - LOF
4. 모델 기반 방법
# 066 모델이 재구성하기 어려운 데이터를 이상치로
# 066 - Isolation Forest
# 066 - One-Class SVM
# 066 - Autoencoder
간단한 이상치 탐지 예제
from sklearn.ensemble import IsolationForest
import numpy as np
import matplotlib.pyplot as plt
# 066 데이터 생성
np.random.seed(42)
X_normal = np.random.randn(200, 2) * 0.5 # 정상
X_outliers = np.random.uniform(-4, 4, (20, 2)) # 이상치
X = np.vstack([X_normal, X_outliers])
# 066 Isolation Forest
iso_forest = IsolationForest(contamination=0.1, random_state=42)
predictions = iso_forest.fit_predict(X)
# 066 시각화
plt.figure(figsize=(10, 6))
normal_mask = predictions == 1
outlier_mask = predictions == -1
plt.scatter(X[normal_mask, 0], X[normal_mask, 1],
c='blue', label='Normal', alpha=0.5)
plt.scatter(X[outlier_mask, 0], X[outlier_mask, 1],
c='red', label='Anomaly', s=100, marker='x')
plt.title('Isolation Forest Anomaly Detection')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('isolation_forest_intro.png', dpi=150)
print(f"정상: {normal_mask.sum()}, 이상치: {outlier_mask.sum()}")
이상치 탐지 vs 클러스터링
| 항목 | 이상치 탐지 | 클러스터링 |
|---|---|---|
| 목적 | 비정상 데이터 찾기 | 그룹으로 나누기 |
| 가정 | 대부분 정상 | 여러 그룹 존재 |
| 출력 | 정상/이상 | 그룹 레이블 |
| 비대칭 | 이상치는 희소 | 그룹 크기 유연 |
이상치 탐지의 어려움
1. 레이블 부족
대부분의 이상치 탐지는 비지도 학습
- 이상치 레이블이 없거나 매우 부족
- 모델 평가가 어려움
2. 클래스 불균형
이상치 비율: 보통 0.1% ~ 5%
- 정상: 99%+
- 이상: < 1%
3. 동적 패턴
정상의 정의가 시간에 따라 변함
- 계절성
- 트렌드 변화
- 새로운 정상 패턴
평가 지표
정답이 있는 경우:
from sklearn.metrics import precision_score, recall_score, f1_score
# 066 예시 (실제 레이블이 있을 때)
# 066 y_true: 실제 레이블 (1: 정상, -1: 이상)
# 066 y_pred: 예측 레이블
# 066 이상치 기준으로 평가
# 066 precision = 탐지된 이상치 중 실제 이상치 비율
# 066 recall = 실제 이상치 중 탐지된 비율
# 066 F1 = 조화 평균
정리
- 이상치 탐지는 정상 패턴에서 벗어난 데이터 탐지
- 점/맥락/집단 이상치 유형
- 통계, 거리, 밀도, 모델 기반 방법
- 사기 탐지, 설비 감시 등에 활용
- 레이블 부족과 불균형이 주요 과제
다음 글 예고
다음 글에서는 PyCaret 이상치 탐지 모듈을 다룹니다.
PyCaret 머신러닝 마스터 시리즈 #066