๐ ์ด๋ฒ ํฌ์คํ
์ ์ด์ ํฌ์คํธ์ฒ๋ผ ๊ณ ๋ ค๋ํ๊ต ๊น์ฑ๋ฒ ๊ต์๋์ ๊ฐ์์์์ ์ฐธ๊ณ ํ์ฌ ๋ชจ๋ธ ๊ธฐ๋ฐ ์ด์์น ํ์ง ์๊ณ ๋ฆฌ์ฆ ์ค Isolation Forest์ ๋ํด ๋ค๋ฃจ๊ณ ์ ํฉ๋๋ค.
Isolation Forest
Notion
- ์ ์ ๋ฐ์ดํฐ๋ก๋ถํฐ ํ์ตํ ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ ๊ฐ์ฒด์ ์ ์/์ด์ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ๋ฐฉ๋ฒ๋ก ์
๋๋ค.
- ์ฌ๋ฌ ๊ฐ์ ์์ฌ๊ฒฐ์ ๋๋ฌด๋ฅผ ์ข
ํฉํ ์์๋ธ ๊ธฐ๋ฐ์ ์ด์ํ์ง ๊ธฐ๋ฒ์ผ๋ก ์์ฌ๊ฒฐ์ ๋๋ฌด๋ฅผ ์ง์์ ์ผ๋ก ๋ถ๊ธฐ์ํค๋ฉด์ ๋ชจ๋ ๋ฐ์ดํฐ ๊ด์ธก์น์ ๊ณ ๋ฆฝ ์ ๋ ์ฌ๋ถ์ ๋ฐ๋ผ ์ด์์น๋ฅผ ํ๋ณํฉ๋๋ค.
- ์ ์ ๊ด์ธก์น๋ ๊ณ ๋ฆฝ๋๊ธฐ ์ด๋ ค์ธ ๊ฒ์ด๋ค๋ผ๋ ๊ฐ์ ์ ํฉ๋๋ค. ์ด๋ ์ ์ ๊ด์ธก์น๋ฅผ ๊ณ ๋ฆฝ์ํค๊ธฐ ์ํด์๋ 2์ง ๋ถํ ์ ์ฌ๋ฌ ๋ฒ ์ํํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค.
- ์ด์์น๋ ์ฝ๊ฒ ๊ณ ๋ฆฝ๋ ๊ฒ์ด๋ค๋ผ๋ ๊ฐ์ ์ ํฉ๋๋ค. ์ด๋, ์ด์์น๋ฅผ ๊ณ ๋ฆฝ์ํค๊ธฐ ์ํด์๋ 2์ง ๋ถํ ์ ์ ๊ฒ ์ํํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค.
- ์ง๊ด์ ์ผ๋ก ๋น์ ์ ๋ฐ์ดํฐ๋ผ๋ฉด ์์ฌ๊ฒฐ์ ๋๋ฌด์ ๋ฃจํธ ๋
ธ๋์์ ๊ฐ๊น์ด ๊น์ด์์ ๊ณ ๋ฆฝ๋ ๊ฒ์ด๊ณ , ์ ์ ๋ฐ์ดํฐ๋ผ๋ฉด ๋ฃจํธ ๋
ธ๋์์ ๋จผ ๊น์ด์์ ๊ณ ๋ฆฝ๋ ๊ฒ์
๋๋ค.
- ๊ฐ ๊ด์ธก์น์ Path length(๊ด์ธก์น x๊ฐ ๊ณ ๋ฆฝ๋ ๋๊น์ง ํ์ํ ๋ถํ ํ์)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Anomaly score๋ฅผ ์ ์ํ์ฌ ๋ถ์ฌํฉ๋๋ค.
- 2008๋
์ ๋ฐํ๋ ๋ชจ๋ธ์ด์ง๋ง ์์ง๊น์ง๋ ์ด์์น ํ์ง๋ฅผ ํ๋๋ฐ ์์ด ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ฉ๋๋ค.
Algorithm
1. ์ ์ฒด ๋ฐ์ดํฐ์์ ์ผ๋ถ ๊ด์ธก์น๋ฅผ ๋๋คํ๊ฒ ์ ํ
2. ๋๋คํ๊ฒ ์ ํ๋ ๊ด์ธก์น์ ๋ํด ์์์ ๋ณ์(splitting variable)์ ๋ถํ ์ (splitting point)์ ์ฌ์ฉํ์ฌ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํ ๋๊น์ง ์ด์ง๋ถํ ์งํ
- ์์ฌ๊ฒฐ์ ๋๋ฌด๋ชจ๋ธ์ด ์ฌ์ ์ ์๋ ๊น์ด์ ๋๋ฌ
- ๋ชจ๋ ํฐ๋ฏธ๋ ๋
ธ๋์ ์กด์ฌํ๋ ๊ด์ธก์น๊ฐ 1๊ฐ์ฉ ์กด์ฌ
- ๋ชจ๋ ํฐ๋ฏธ๋ ๋
ธ๋์ ์กด์ฌํ๋ ๊ด์ธก์น๋ค์ด ๊ฐ์ ์
๋ ฅ๋ณ์
3. ์์ ๊ฐ์ ๊ณผ์ ์ผ๋ก ์ฌ๋ฌ ๊ฐ์ ITree๋ฅผ ๊ตฌ์ถ
4. ITree๋ง๋ค ๊ฐ ๊ด์ธก์น์ Path length(๋ถ๋ฆฌ ํ์)๋ฅผ ์ ์ฅ
5. ๊ฐ ๊ด์ธก์น์ ํ๊ท Path length๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Anomaly score(์ด์์น ์ค์ฝ์ด)๋ฅผ ๊ณ์ฐ ๋ฐ ์ด์์น ํ๋ณ
Anomaly score ์ ์
-
Path length๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ์
-
Path length (=h(x))
-
Normalized h(x):c(n)=2H(nโ1)โ{n2(nโ1)โ} (๋ชจ๋ ๊ด์ธก์น๋ค์ ํ๊ท Path length)
- H(i)=ln(i)+0.5772156649(์ค์ผ๋ฌ์์)
-
Anomaly score : s(x,n)=2โc(n)E(h(x))โ,E(h(x))istheaverageofh(x)
- = ๋ชจ๋ ๊ด์ธก์น๋ค์ ํ๊ท Path length ๋๋น ๋ด๊ฐ ๊ด์ฌ์๋ ๊ด์ธก์น ํ๊ท Path length ๋์ถ
- E(h(x))โ0,s(x,n)โ20โ1
(Path length์ ํ๊ท ๊ฐ์ด 0์ ๊ฐ๊น์์ผ๋ก ์ด์ ๋ฐ์ดํฐ)
- E(h(x))โnโ1(=๊ด์ธก์น์๊ฐ์โ1=์ต๋๋ถ๋ฆฌํ์),s(x,n)โ2โๅคงโ0์๊ฐ๊น์ด์
(Path length์ ํ๊ท ๊ฐ์ด n์ ๊ฐ๊น์์ผ๋ก ์ ์ ๋ฐ์ดํฐ)
- E(h(x))โc(n),s(x,n)โ2โ1โ0.5
(Path length์ ํ๊ท ๊ฐ์ด normalized h(x)์ ๋น์ทํจ์ผ๋ก ์ ์ ๋ฐ์ดํฐ)
- Anomaly score์ ๋ฒ์๋ 0~1์ด๋ฉฐ, 1์ ๊ฐ๊น์ฐ๋ฉด ์ด์ ๋ฐ์ดํฐ, 0.5์ดํ๋ฉด ์ ์ ๋ฐ์ดํฐ๋ผ๊ณ ํ ์ ์์ต๋๋ค.
Code
- ํ์ด์ฌ์์ sklearn.ensemble ๋ชจ๋์ IsolationForestํจ์๊ฐ ํด๋น ์๊ณ ๋ฆฌ์ฆ์ ์ง์ํฉ๋๋ค.
- ์ผ๋ฐ์ ์ธ sklearn์ ๋ค๋ฅธ ํจ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฐ์ดํฐ์ 'fit()', 'predict()'๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ์ ์ ์์ผ๋ฉฐ, 'predict()'์ ๊ฒฐ๊ณผ๋ ์ ์(1), ์ด์(-1)๋ก ํํ๋ฉ๋๋ค.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set_style("darkgrid")
from sklearn.ensemble import IsolationForest
rng = np.random.RandomState(42)
X_train = 0.2 * rng.randn(1000, 2)
X_train = np.r_[X_train + 3, X_train]
X_train = pd.DataFrame(X_train, columns = ['x1', 'x2'])
X_test = 0.2 * rng.randn(200, 2)
X_test = np.r_[X_test + 3, X_test]
X_test = pd.DataFrame(X_test, columns = ['x1', 'x2'])
X_outliers = rng.uniform(low=-1, high=5, size=(50, 2))
X_outliers = pd.DataFrame(X_outliers, columns = ['x1', 'x2'])
plt.rcParams['figure.figsize'] = [10, 10]
p1 = plt.scatter(X_train.x1, X_train.x2, c='white', s=20*4, edgecolor='k', label='training observations')
p3 = plt.scatter(X_outliers.x1, X_outliers.x2, c='red', s=20*4, edgecolor='k', label='new abnormal obs.')
plt.legend()
clf = IsolationForest(max_samples=100, contamination = 0.1, random_state=42)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
X_outliers2 = X_outliers.assign(y = y_pred_outliers)
X_outliers2
plt.figure(figsize = (12,10))
p1 = plt.scatter(X_train.x1, X_train.x2, c='white',
s=20*4, edgecolor='k', label="training observations")
p2 = plt.scatter(X_outliers2.loc[X_outliers2.y == -1, ['x1']],
X_outliers2.loc[X_outliers2.y == -1, ['x2']],
c='red', s=20*4, edgecolor='k', label="detected outliers")
p3 = plt.scatter(X_outliers2.loc[X_outliers2.y == 1, ['x1']],
X_outliers2.loc[X_outliers2.y == 1, ['x2']],
c='green', s=20*4, edgecolor='k', label="detected regular obs")
plt.legend()
print("ํ
์คํธ ๋ฐ์ดํฐ์
(normal data)์์ ์ ํ๋:", list(y_pred_test).count(1)/y_pred_test.shape[0])
print("์ด์์น ๋ฐ์ดํฐ์
์์ ์ ํ๋:", list(y_pred_outliers).count(-1)/y_pred_outliers.shape[0])
๊ธฐ์กด ๋ฐ์ดํฐ์์ ๊ทธ ๋ฐ์ดํฐ๊ฐ ์ง์ง ์ด์์น์ธ์ง๋ฅผ ์ ์๊ฐ ์๋๋ฐ ์ด๋ป๊ฒ ์ ํ๋๋ฅผ ๊ตฌํ ์ ์๋ ๊ฑด๊ฐ์? list(y_pred_test).count(1)/y_pred_test.shape[0]) ์ด๊ฒ ์ ์ ํ๋์ธ๊ฑด์ง ๊ถ๊ธํฉ๋๋ค.