본문으로 건너뛰기

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