이상 탐지에는 여러가지 알고리즘이 있는데 이번시간에는 Isolation Forest 라는 알고리즘으로 진행해보겠다.
데이터에서 비정상적인 패턴, 이상치, 또는 예외적인 사례를 탐지하는 과정
데이터에서 일반적으로 볼 수 있는 특성에서 많이 벗어난 데이터를 식별하는 과정에서 사용
보안, 금융, 의료 등의 분야에서 중요한 역할
예를 들어,
• 나의 계좌가 갑자기 외국 어딘가에서 로그인 하려는 시도가 포착되었거나
• 충격파 그래프를 이용해 물체 혹은 건물 내부의 균열을 찾아낸다거나
이전에 진행한 실습 과정에서도 이상치를 판단하고 제거 했음.
이는 전통적 이상 탐지 방법임.
전통적인 통계 기반 방법으로 대표적으로
IQR (Interquartile Range)[우리가 사용했던 것!]
• 1사분위수(Q1)와 3사분위수(Q3)간의 차이로
• Q1-1.5IQR 미만 혹은 Q3+1.5IQR 초과 데이터를 이상치로 간주
Z-Score
• 데이터 포인트가 평균으로부터 표준 편차의 몇 배만큼 떨어져 있는지를 나타내는 수치
• 이 수치가 3이상인 데이터를 이상치로 간주
전통적 이상 탐지 방법은 계산이 복잡하지 않고 해석이 직관적
• 하지만, 모든 데이터에 적용해 의미있는 결과를 얻기에는 어렵고
• 데이터가 대칭이 아니거나 복잡한 분포를 갖고 있다면 오인식이 늘어남
전통적 이상 탐지 방법의 단점을 극복하고자 머신러닝을 사용하기 시작했다.
고차원 & 대량의 데이터는 그 내부의 패턴을 갖고있다.
머신 러닝 모델로 데이터의 패턴을 익히고
그 패턴에서 벗어난 데이터를 이상치로 취급하는 과정!
정상 데이터는 그와 비슷한 특성 패턴을 갖는 비슷한 데이터와 밀도 있게 모여있을 것이다.

반면, 이상치 데이터는 밀도가 낮은 공간에 존재!

이때, 하나의 데이터를 ʻ고립ʼ하도록 어떤 특성과 그것의 분할 값을 기준으로 위의 점선과 같이 나눈다.
즉, 분할되는 횟수를 가지고 이상치를 잡아내는 개념!

각 서브 데이터는 트리라고 부름.


이후 이상치에 대해 점수를 계산한다.
평균 깊이를 바탕으로 각 데이터 포인트의 이상치 점수를 계산


아래와 같은 이상치 데이터가 있다고 해보자

딱 보기에 노란색이 정상, 붉은색이 이상치로 보인다.
정상데이터는 100개, 이상치는 20개로 만
contamination = 에는 0.15비율을 줌. ‘auto’로 해도 무방
# Isolation Forest 모델 생성을 위한 매개 변수
n_estimators = 100 # 사용할 트리의 수
max_samples = 'auto' # 각 트리당 최대 샘플 수
contamination = 0.15 # 전체 데이터셋에서 이상치가 차지하는 비율의 추정치
# 이 값을 이용해 추후 이상치를 찾아냄
# 이상치 점수가 이 임계값보다 높은 데이터 포인트는 이상치로 간주
# Isolation Forest 생성 및 학습
from sklearn.ensemble import IsolationForest
IForest = IsolationForest(n_estimators=n_estimators,
max_samples=max_samples,
contamination=contamination,
random_state=seed)
IForest.fit(X)
이를 점수화를 진행하면 아래와 같이 출력된다.
# 모든 데이터에 대한 이상치 점수 계산
# 이 값은 트리 내에서의 평균 경로 depth를 기반으로 계산됨
# 정규화 된 값으로,
# 점수가 낮으면 평균 길이가 짧다고 보면 되며 이상치일 가능성이 ↑
scores_pred = IForest.decision_function(X)
print(scores_pred)

각 데이터 포인트 120 별로 평균값을 구한 뒤 이상치 값과 비교를 한 결과를 점수로 매긴것이다.
점수가 낮을 수록 이상치!
여기서 이상치를 시각화한다면 아래와 같이 할 수 있다.
# 이상치 점수를 바탕으로 시각화
plt.figure(figsize=(15, 9))
plt.scatter(X_normal[:, 0], X_normal[:, 1], c='yellow', edgecolor='k', s=20, label="Normal data")
plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='red', edgecolor='k', s=20, label="Outliers")
# 이상치 점수에 따라 점의 크기를 조정
# 파란색 원이 클 수록 이상치일 확률이 큰 것을 의미
sizes = (scores_pred.max() - scores_pred) * 500
plt.scatter(X[:, 0], X[:, 1], s=sizes, edgecolor='b', facecolors='none', label="Anomaly scores")
plt.title("Isolation Forest Anomaly Detection")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.legend()
plt.show()

점수가 낮을 수록 원이 작아지기 때문에 가운데 모인 데이터들은 정상으로 볼 수 있다.
임계치 15%를(120개 중 15%니까.. 18개!) 기준으로 이상치다 아니다를 predict로 구분해보자
# 이상치 여부 결정
IForest.predict(X)

1은 정상, -1은 비정상!
-1은 True값으로 바꿔줌.
is_outlier = IForest.predict(X) == -1
is_outlier

이걸 토대로 정상 데이터와 비정상 데이터를 분리!
# 정상 데이터와 이상치 데이터 분리
X_normal_detected = X[~is_outlier]
X_outliers_detected = X[is_outlier]
이걸 시각화 하면 모델이 이상치를 분류해줌.
# 시각화
plt.figure(figsize=(15, 9))
plt.scatter(X_normal_detected[:, 0], X_normal_detected[:, 1], c='white', edgecolor='k', s=20, label="Detected Normal Data")
plt.scatter(X_outliers_detected[:, 0], X_outliers_detected[:, 1], c='red', edgecolor='k', s=20, label="Detected Outliers")
plt.title("Detected Anomaly Data using Isolation Forest")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.legend()
plt.show()

이상치 데이터 정답을 알고 있다면
이상 데이터를 양성으로 놓고 분류 형태의 문제로 평가 가능
# 성능 평가
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
accuracy = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)
print(f'정확도 Accuracy : {accuracy*100:.2f} %')
print(f'정밀도 Precision : {precision*100:.2f} %')
print(f'재현율 Recall : {recall*100:.2f} %')
print(f'F1 : {f1*100:.2f} %')
출력값:
정확도 Accuracy : 98.33 %
정밀도 Precision : 100.00 %
재현율 Recall : 90.00 %
F1 : 94.74 %