Isolation Forest를 통한 이상탐지

John
7 min readJan 31, 2020

Anomaly Detection(이상 탐지)

말 그대로 “이상한 것을 찾는 행위"이다.
즉 일반적인 데이터의 정상 패턴에서 벗어난 개체를 식별하기 위한 것이 Anomaly Detection이다.

현재 내가 진행하고 있는 업무상 식별되어 있는 정답 label이 없기 때문에 supervised learning을 통해 이상 탐지를 할 수 없었고, 대신 비지도 학습을 통해 이상 탐지를 할 수 있는 알고리즘을 활용해야 했다.

비지도 학습을 통해 가능한 anomaly detection의 종류

  • Mahalanobis 거리를 통해 outlier 색출
  • K-Means를 통한 군집화
  • DBSCAN
  • Isolation Forest

위 네 가지 방법이 가장 먼저 떠올랐는데, 내가 이론적으로 학습이 필요하다고 생각되고 현재 많은 feature set을 가지고 있는 상황이기에 isolation forest가 가장 적합하다고 생각이 들었고 이를 통해 이상 탐지를 진행했다.

Isolation Forest

isolation forest
  • 다차원 데이터셋에서 효율적으로 작동하는 아웃라이어 제거 방법
  • 의사결정 트리기반 이상탐지 기법
  • 랜덤하게 칼럼을 선택하고, 선택된 칼럼의 최대값과 최소값을 분리하는 값을 랜덤으로 선택하는 방법

내가 가지고 있는 feature set은 13393개의 행과 22개의 칼럼으로 이루어져 있었고, isolation forest에 내가 가지고 있는 feature를 넣기 전에 상관계수가 지나치게 높은 feature들은 제거했다.

코드

isolaton forest 알고리즘은 sklearn에서 현재 제공을 하고 있다.

from sklearn.ensemble import IsolationForestclf=IsolationForest(n_estimators=50, max_samples=50, contamination=float(0.004), 
max_features=1.0, bootstrap=False, n_jobs=-1, random_state=None, verbose=0,behaviour="new")
# 50개의 노드 수, 최대 50개의 샘플
# 0.04%의 outlier 색출.
clf.fit(feature_set)
pred = clf.predict(feature_set)
feature_set['anomaly']=pred
outliers=feature_set.loc[feature_set['anomaly']==-1]
outlier_index=list(outliers.index)
#print(outlier_index)
#Find the number of anomalies and normal points here points classified -1 are anomalous
print(feature_set['anomaly'].value_counts())

이런 식으로 코드를 작성하면, 정상치(1)와 이상치(-1)가 구분되어 나타나게 된다.

output 예시

그리고 측정 지표를 정규화하고 PCA에 적합시켜 차원의 수를 줄인 후 3D로 표시를 했다.

import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from mpl_toolkits.mplot3d import Axes3D
pca = PCA(n_components=3)
scaler = StandardScaler()
#normalize the metrics
X = scaler.fit_transform(feature_set)
X_reduce = pca.fit_transform(X)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_zlabel("x_composite_3")
# Plot the compressed data points
ax.scatter(X_reduce[:, 0], X_reduce[:, 1], zs=X_reduce[:, 2], s=4, lw=1, label="inliers",c="green")
# Plot x's for the ground truth outliers
ax.scatter(X_reduce[outlier_index,0],X_reduce[outlier_index,1], X_reduce[outlier_index,2],
lw=2, s=60, marker="x", c="red", label="outliers")
ax.legend()
plt.show()
PCA 3차원 축소 결과
import numpy as np
from sklearn.decomposition import PCA
pca = PCA(2)
pca.fit(feature_set)
res=pd.DataFrame(pca.transform(feature_set))
Z = np.array(res)
plt.title("IsolationForest")
# plt.contourf( Z, cmap=plt.cm.Blues_r)
b1 = plt.scatter(res[0], res[1], c='green',
s=20,label="normal points")
b1 =plt.scatter(res.iloc[outlier_index,0],res.iloc[outlier_index,1], c='green',s=20, edgecolor="red",label="predicted outliers")
plt.legend(loc="upper right")
plt.show()
2차원 축소

이 결과를 통해 어떠한 부분이 ‘anomaly’ 한 특성을 가지고 있는지 확인을 할 수 있었고, 이 결과로 어떠한 feature가 정상 데이터에 비해 패턴에서 많이 벗어났는지 확인할 수 있었다.

실제 정답 Label이 있을 시에 예측 성능도 측정할 수 있었겠지만, 아쉽게도 label이 존재하지 않는 데이터라서 측정하기 어려운 부분이 있었다.

하지만 실제 label이 있을 경우 Accurancy,Recall,Precision,F1-score 등을 통해 확인해볼 수 있을 것이다.

참고

--

--