AI/머신러닝
실무에 쓰는 머신러닝 기초 1주차 (이상 탐지)
edcrfv458
2025. 3. 24. 13:40
목표
- 이상 탐지
- 주요 알고리즘의 원리 및 활용 방법
- 산업별 사례
1. 이상 탐지(Anomaly Detection)
- 데이터에서 정상 패턴과 크게 다른 행위 보이는 특이한 패턴을 찾는 기법
필요한 이유
- 금융 사기: 카드 사기, 계좌 해킹 등으로 인한 금전적 손실을 미리 막기 위해
- 제조업: 생산 라인이나 기계 설비에서 발생하는 고장을 사전에 예측하여 유지보수 비용 절감, 다운 타임 최소화
- 보안: 네트워크 침입 시도나 데이터 탈취 등을 빠르게 감지
이상치 탐지(Outlier Detection)와의 차이
- 이상치 탐지는 단순히 통계적으로 극단값을 찾는데 초점을 둔다
- 평균에서 크게 벗어난 데이터 포인트
- 이상 탐지는 단순 극단값 뿐만이 아닌, 맥락이나 시계열 상의 패턴을 함께 고려해 비정상 인지를 판단
- 시간적 흐름이나 주변 맥락, 다른 변수들과의 상관관계까지 고려하는 경우
2. 주요 이상 탐지 알고리즘
- 비지도 학습에서 데이터의 분포/패턴을 학습하고, 그로부터 크게 벗어나는 포인트를 이상으로 간주
One-Class SVM
- 알고리즘 원리
- SVM(Support Vector Machine)은 원래 이진 분류를 위해 고안된 알고리즘
- One-Class SVM은 단 하나의 클래스(정상) 만을 학습해 해당 클래스 영역을 정의
- 정상 데이터가 분포하는 공간에 경계를 형성(decision boundary)하고, 경계 밖에 있는 데이터는 비정상으로 분류
- 특징
- 고차원 공간에서도 비교적 잘 동작할 수 있음 (커널 함수의 사용)
- 데이터 스케일링과 커널 파라미터 선택이 중요 (RBF 커널일 때 y값, nu(v) 값 등)
- nu(v)는 데이터의 이상치가 몇 퍼센트 정도 있을 거라 생각하는지 예상 값 (가정)
Isolation Forest
- 알고리즘 원리
- 랜덤 포레스트와 유사한 아이디어에 기반
- 이상 데이터는 전체 데이터 중 상대적으로 적고, 특정 속성값에서 극단적인 위치를 차지하는 경우가 많다고 가정
- 무작위로 특성과 분할값을 골라 데이터를 계속 나누어가는 과정에서 쉽게 분리되는 데이터는 이상치라고 생각
- 특징
- 랜덤 포레스트 방식으로 여러 개의 무작위 트리를 구성
- 각 트리에서 한 데이터가 분리되는 깊이(depth)를 측정해 이상 점수를 부여
- 대규모 데이터셋에서도 빠르게 동작하는 편
- 구현이 간단하고 직관적
코드
- OneClassSVM은 nu 값 설정
- IsolationForest는 contamintation 값 설정
- 둘 다 이상치의 비율을 가정하는 파라미터
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()
4. 산업별 사례
금융 분야
- 카드 사기 거래(Fraud Detection)
- 수많은 정상 거래 데이터를 토대로 이상 탐지 모델 학습
- 갑작스러운 해외 거래나 큰 금액의 작은 이체 등의 패턴이 감지되면 사기 가능성이 높은 것으로 표시
- 돈 세탁 의심 거래(Money Laundering)
- 고객의 거래 패턴을 종합적으로 분석해 비정상적으로 복잡한 자금 흐름을 포착
제조업 분야
- 설비 고장 예측
- 온도, 압력, 진동 센서 데이터를 장기간 축적해 정상 범위 학습
- 특정 시점부터 갑작스럽게 진동 값이 크게 변한다면, 실제 고장 가능성이 있는 설비로 판단해 미리 점검
- 품질 이상 탐지
- 생산 공정 중 수집되는 다양한 품질 지표를 통해 갑작스러운 편차가 발생하는 제품 빠르게 걸러내어 불량률 줄임
실습
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import OneClassSVM
from sklearn.ensemble import IsolationForest
# 1. Wine 데이터셋 로드
from sklearn.datasets import load_wine
wine = load_wine()
X = wine.data
y = wine.target
# 변수 2개만 선택 (예: 컬럼 0, 1)
X_2d = X[:, :2] # shape: (178, 2)
feature_names = [wine.feature_names[0], wine.feature_names[1]]
# 2. One-Class SVM
oc_svm = OneClassSVM(nu=0.05) # 예시 파라미터
oc_svm.fit(X_2d)
# 예측: 1(정상), -1(이상치)
y_pred_oc = oc_svm.predict(X_2d)
# 3. Isolation Forest
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()
팁
- 알고리즘
- One-Class SVM: 정상 데이터 기준으로 경계 형성
- Isolation Forest: 무작위 분할을 통해 쉽게 분리되는 데이터를 이상으로 간주
- 위 두 개의 결과를 앙상블로 합산하는 등 정교한 이상 탐지 시스템 구축 가능
- 또는 딥러닝의 Autoencoder와 GAN 등이 있음