[ML] 머신러닝 9강 - 데이터에서 이상치를 제거하려면, 이상탐지

- 이상 탐지 개념

- 주요 알고리즘 원리와 활용법

- 산업별 사례

 

 

이상 탐지(Anomaly Detection)

정상 패턴에서 크게 다른 행위를 보이는 특이한 패턴을 찾는 기법

 

  • 금융 사기 예방
  • 제조업 -> 기계 설비에서 발생하는 고장을 사전에 예측하여 보수 비용 절감
  • 보안 -> 네트워크 침입 시도나 데이터 탈취 등 빠르게 감지

이상치 탐지(Outlier Detection)와의 차이

통계적으로 극단값을 찾는 데 초점

 

vs 이상탐지는 단순 극단값 뿐 아니라, 맥락이나 시계열 상의 패턴을 함께 고려해서 '비정상'인지를 판단하는 것을 의미


주요 이상 탐지 알고리즘

두 가지 모두 비지도 학습

 

One-Class SVM

오로지 정상 데이터만 보고 그 특징에 따라서 결정 경계를 만들어 주고, 결정 경계를 벗어나면 이상으로 봄

✔️ 즉, 단 하나의 클레스(정상 클래스)만을 학습해 해당 클래스 영역을 정의

 

특징

  • 고차원 공간에서도 비교적 잘 동작 (커널 함수의 사용)
  • 데이터 스케일링과 커널 파라미터 선택이 중요 (예. RBF 커널일 때, γ값, nu(ν) 값 등)


Isolation Forest

 

원리

  • 랜덤 포레스트와 유사한 아이디어 기반
  • 이상 데이터는 전체 중 상대적으로 적고, 특정 속성값에서 극단적인 위치를 차지하는 경우가 많다는 가정 하에
  • 무작위로 특성과 분할값을 골라 데이터를 계속 나누어가는 과정에서 '쉽게 분리'되는 데이터는 이상일 가능성이 높다고 봄

특징

  • 여러 개의 무작위 트리를 구성하고, 각 트리에서 한 데이터가 분리되는 '깊이(depth)'를 측정하여 이상 점수를 부여
  • 대규모 데이터셋에서도 빠르게 동작, 구현이 간단하고 직관적

▼ 이상탐지 코드 예시

더보기
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 1. 데이터 로드: Iris 데이터셋
from sklearn.datasets import load_iris
data = load_iris()
X = data.data
y = data.target  # 여기서는 실제 라벨을 이용하지 않음

# 간단히 2개 특성만 사용 (예: 꽃받침 길이, 꽃받침 너비) --> 시각화 편의를 위해
X_2d = X[:, :2]  # shape: (150, 2)

# 2. One-Class SVM
from sklearn.svm import OneClassSVM

oc_svm = OneClassSVM(nu=0.05)  # 예시 파라미터
oc_svm.fit(X_2d)
# 예측: 1(정상), -1(이상치)
y_pred_oc = oc_svm.predict(X_2d)

# 3. Isolation Forest
from sklearn.ensemble import IsolationForest

iso_forest = IsolationForest(contamination=0.05, random_state=42)
iso_forest.fit(X_2d)
# 예측: 1(정상), -1(이상치)
y_pred_if = iso_forest.predict(X_2d)

# 4. 이상치로 예측된 샘플 인덱스 추출
outliers_oc = np.where(y_pred_oc == -1)[0]  # One-Class SVM이 예측한 이상치
outliers_if = np.where(y_pred_if == -1)[0]  # Isolation Forest가 예측한 이상치

print("=== One-Class SVM ===")
print("이상치로 탐지된 샘플 개수:", len(outliers_oc))
print("이상치 인덱스:", outliers_oc)

print("\n=== Isolation Forest ===")
print("이상치로 탐지된 샘플 개수:", len(outliers_if))
print("이상치 인덱스:", outliers_if)

# 5. 시각화
# 2차원 특성 공간에서 이상치로 판별된 점들을 빨간색으로 표시
fig, axes = plt.subplots(1, 2, figsize=(12, 5))

axes[0].scatter(X_2d[:, 0], X_2d[:, 1], label='Normal')
axes[0].scatter(X_2d[outliers_oc, 0], X_2d[outliers_oc, 1],
                color='red', edgecolors='k', label='Outliers')
axes[0].set_title("One-Class SVM")
axes[0].set_xlabel("Sepal Length")
axes[0].set_ylabel("Sepal Width")
axes[0].legend()

axes[1].scatter(X_2d[:, 0], X_2d[:, 1], label='Normal')
axes[1].scatter(X_2d[outliers_if, 0], X_2d[outliers_if, 1],
                color='red', edgecolors='k', label='Outliers')
axes[1].set_title("Isolation Forest")
axes[1].set_xlabel("Sepal Length")
axes[1].set_ylabel("Sepal Width")
axes[1].legend()

plt.tight_layout()
plt.show()

 

제조업 사례

  • 설비 고장 예측
  • 품질 이상 탐지

▼ Q&A

더보기

📚 Q1: 이상 탐지를 위해 라벨이 전혀 없는 데이터만 있어도 모델을 학습할 수 있나요?

A1: 네, 비지도학습 방식인 One-Class SVM, Isolation Forest 등은 기본적으로 정상 레이블만(혹은 완전히 라벨이 없는 데이터)으로도 이상 패턴을 학습할 수 있습니다. 그러나 정확도 향상을 위해 일부 라벨이 있거나, 정상 데이터만 정확히 확보할 수 있다면 훨씬 유리합니다.

 

📚 Q2: Isolation Forest에서 contamination 파라미터는 어떻게 결정하나요?

A2: contamination은 이상치(또는 이상 데이터) 비율을 의미합니다. 실제 데이터셋에서 예상되는 이상치 비율을 추정해 설정하는 것이 일반적이고, 도메인 지식이나 사전 샘플링을 통해 결정하는 경우가 많습니다. 예를 들어, 전체 거래의 1%가 사기일 것으로 가정한다면 contamination=0.01로 설정할 수 있습니다.

 

📚 Q3: 실무에서 임계값(threshold)은 어떻게 정하나요?

A3: 모델이 산출한 이상 스코어(복원 오차, 결정 함수 값 등)의 분포를 확인해 적절한 지점을 선택합니다. 일반적으로 정상 데이터에서의 분포를 기준으로, 허용 가능한 오탐(false positive)과 미탐(false negative)의 비율을 고려해 최적점을 찾습니다.

 

📚 Q4: 이상 탐지를 강화하기 위해 다른 방법들과 혼합해 쓸 수 있나요?

A4: 네, 가능합니다. 예를 들어, One-Class SVM과 Isolation Forest 결과를 앙상블로 합산하는 등의 방법으로 더 정교한 이상 탐지 시스템을 구축할 수 있습니다.