2 분 소요

[목적]

  • Anomaly Detection의 기초
  • Univariate variable (단변량)일 때 사용
  • 시각적으로 판단가능함

[Process]

  1. Define Data
  2. Modeling
  3. Plotting
    !pip install pyod
    
    • pyod에서 데이터 갖고 올꺼
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

import warnings
warnings.filterwarnings("ignore")

from pyod.utils.data import generate_data, get_outliers_inliers
# Data Loading
X, Y = generate_data(behaviour='new', n_features=10, 
                     train_only=True,
                     contamination=0.1,
                     random_state=2023)
  • 데이터 만드는거
    • feature 10개, 이상치 0.1
  • 데이터 만들 때마다 random_state 잊지 말기!
# Naming for columns
col_list = []
for i in range(X.shape[1]):
    a = 'X{}'.format(i+1)
    print(a)
    col_list.append(a)
  • 만들어진 X는 그냥 array로 나오는데, 이름이 없으니 이름 붙여줌
# Make DF
df = pd.DataFrame(X, columns = col_list)
df['Y'] = Y
# Data 분포 확인하기 X1, X2
sns.scatterplot(x='X1', y='X2', hue='Y', data=df);
plt.title('Ground Truth')

image

[3-Sigma Rule]

  • 사용방법
    # 데이터의 분포를 정규분포로 가정하고, 평균으로부터 (표준편차 x 시그마 계수σ)를 벗어나면 아웃라이어라고 판단함
    # 시그마 계수(σ)
    
  • 현업사례
    # 공정 센서 데이터 이상탐지
    # 검사 및 측정 데이터 이상탐지 
    
# ▶ UCL, LCL 생성
df['UCL_X1'] = df['X1'].mean() + 1*df['X1'].std()
df['LCL_X1'] = df['X1'].mean() - 1*df['X1'].std()

df['UCL_X2'] = df['X2'].mean() + 1*df['X2'].std()
df['LCL_X2'] = df['X2'].mean() - 1*df['X2'].std()
  • upper랑 lower 둘다 1σ로 일단 진행
sns.distplot(df['X1'], color = 'blue', label = 'X1')
sns.distplot(df['X2'], color = 'red', label = 'X2')

image

  • 근데 plot보니까 왼쪽으로 꼬리가 좀 긺, 이 경우는 늘어뜨려서 보는게 좋을 듯
# X1 Plotting
%matplotlib inline
plt.style.use(['dark_background'])

sns.scatterplot(x=list(df.index), y=df['X1']);
plt.axhline(y=df['UCL_X1'][0], color='r', linewidth=1)
plt.axhline(y=df['LCL_X1'][0], color='r', linewidth=1)
plt.gcf().set_size_inches(15, 5)

image

  • 위의 빨간선이 upper, 아래 빨간선이 lower
  • 아까 그림에서 파란색 값들은 다 라인 안(4~9)에 들어와 있는데..
  • 노란색 값들이 라인 밖을 벗어나고 세로로 점이 찍혀져 있는 걸 볼 수 있다-> abnormal
  • 가끔 선 넘어가는 것은 그냥 noise
  • 시간대 별로 산점도가 찍혀있음
# X2 Plotting
%matplotlib inline
plt.style.use(['dark_background'])

sns.scatterplot(x=list(df.index), y=df['X2']);
plt.axhline(y=df['UCL_X2'][0], color='r', linewidth=1)
plt.axhline(y=df['LCL_X2'][0], color='r', linewidth=1)
plt.gcf().set_size_inches(15, 5)

image

  • x2도 똑같음

[Box plot]

  • 사용방법
# 주어진 데이터에서 각 사분위수를 계산한다.
# 그래프에서 제 1사분위수와 제 3사분위수를 기준으로 박스를 그린다.
# 제 2사분위수에 해당하는 위치에 선을 긎는다.
# 제 3사분위수에서 1.5IQR을 더한 위치에 가로 선을 긎고 제 3사분위수부터 가로선까지 세로선을 긎는다.
# 제 1사분위수에서 1.5IQR을 뺀 위치에 가로 선을 긎고 제 1사분위수부터 가로선까지 세로선을 긎는다.
#4,5번에 그은 직선을 넘어서는 위치에 존재하는 값은 동그라미와 같은 기호로 표시한다.(이상치 의미) 
  • 용어
# median - 중앙값
# IQR : 25% ~ 75%에 해당한 부분 
# 75th Percentile : 제 3사분위수
# 25th Percentile : 제 1사분위수
# Whisker : 최댓값, 최솟값
# Outlier : 이상치 (Q3+1.5 IQR, Q1-1.5 IQR)
# ▶ Box plot 그려보기
plt.style.use(['default'])
labels = ['X1', 'X2', 'X3']

fig, ax = plt.subplots(figsize=(3,7)) ;
box = ax.boxplot([df['X1'], df['X2'], df['X3']], widths=0.7, sym='b*', showmeans=True);
ax.set_ylim(4.5, 10.0);
ax.set_xlabel("X's");
ax.set_ylabel('Value');

image

  • 주황색 선: 중앙값
  • 초록색 세모: 평균
  • 시간대 별로 나와 있지는 않음
  • 중앙값이 평균보다 높음으로 왼쪽으로 꼬리가 긴 분포임을 알 수 있음
  • 파란색 별은 outlier로 보면 될듯

카테고리:

업데이트:

댓글남기기