본문 바로가기
DeepLearning Framework & Coding/Pytorch

[Pytorch-10] One Class SVM(Support Vector Machine, OCSVM), SVDD

by 노마드공학자 2021. 8. 11.

[pytorch 따라하기-1] 구글 Colab에 pytorch 세팅하기 https://limitsinx.tistory.com/136

[pytorch 따라하기-2] Tensor생성 및 Backward https://limitsinx.tistory.com/137 

[pytorch 따라하기-3] 경사하강법을 통한 선형회귀 구현 https://limitsinx.tistory.com/138

[pytorch 따라하기-4] 인공신경망(ANN) 구현 https://limitsinx.tistory.com/139

[pytorch 따라하기-5] 합성곱신경망(CNN) 구현 https://limitsinx.tistory.com/140

[pytorch 따라하기-6] Neural Style Transfer 구현 https://limitsinx.tistory.com/141

[pytorch 따라하기-7] pix2pix 구현 https://limitsinx.tistory.com/142

[pytorch 따라하기-8] DC-GAN(Deep Convolutional GAN) 구현 https://limitsinx.tistory.com/143 

[pytorch 따라하기-9] LSTM을 통한 시계열데이터 예측모델 구현 https://limitsinx.tistory.com/144

 

※이 전글에서 정리한 코드/문법은 재설명하지 않으므로, 참고부탁드립니다

※해당 글은 PC에서 보기에 최적화 되어있습니다.


Data - Imbalanced ?

 

최근 비정상 데이터 검출을 위한 Anomaly Detection Algorithm들을 공부하고 있습니다.

Anomaly detection을 할때 가장 큰 문제점은 Data-imbalanced 입니다.

즉, 공장에서 물건을 100만개 생산한다고하면, 이중 문제가있는 제품은 10개정도라고 해보시죠

 

그럼, 99만 9990개의 정상데이터와 10개의 비정상데이터를 가지고 학습을 하게되면.. 클래스간 불균형이 일어나서

제대로된 의사결정을 내리기가 쉽지않게됩니다.

 

출처 : Knowledge Engineering

 

제가 사용하는 데이터는 더욱심각한데요, Time-Series 데이터로 100만개의 데이터중 현재까지 비정상데이터는 1개입니다. 이런 경우에는 어떻게 할까?를 고민하며 나온 연구 카테고리가 "Anomaly Detection"입니다.

 

Anomaly Detection도 여러가지 항목으로 구분되는데요 (Supervised,Un-supervised,Semi-supervised....) 

그중, 가장 기본적으로 사용되는 알고리즘인 "One Class SVM"에 대해 정리해보고자 합니다.

 

 

One class SVM

출처 : Research gate

One Class SVM(이하 OC-SVM)의 원리는 간단합니다.

데이터들을 N차원의 좌표축으로 뿌린 후 , 원점과의 거리를 기준으로 선(Hyper Plane)을 그어 Classification하는 것입니다.

 

여기서 유의하셔야할점은, 일반 SVM과는 분명한 차이를 가지고 있다는 점입니다.

Binary-Classification에 많이 쓰이는 SVM은 각 데이터들 속 Support Vector 간의 Margin을 기준으로 Hyper plane을 나누지만, OCSVM은 원점을 기준으로하기에, 조건에 따라 데이터가 아무리 많아도 Class가 1개일 수 있습니다.

 

출처 : https://kr.mathworks.com/discovery/support-vector-machine.html

 

Support Vector 계열서 가장 중요한것은 바로 이것입니다.

 

그래서 판단의 기준이 되는 Hyper Plane을 어떻게 구할껀데?

 

OC-SVM은 하기와 같은 수식에 의해 Hyper Plane이 얻어집니다. (Nu-OC SVM기준)

 

위 수식(Loss 식, 목적함수 라고도함)에서 w, v(nu), p(lo)는 미지수 이며, n은 전체 데이터 샘플 수입니다.

① 1/2*llwll^2 : 각 데이터들에 따라 모델의 변동성이 최소화 되도록 보정해주는 텀

② 1/vn * sigma(psi) : 여기서 psi는 데이터와 hyper plane간의 거리를 의미합니다. 추후 보정텀이 추가되어, Hyper plane 바깥(비정상)에 있는 점들의 거리의 SUM만 남게됩니다. (비정상일수록 Loss커짐)

③ p(lo) : 원점과 Hyper plane간의 거리, 이 값을 빼줆으로써 최소화 문제를 만족할 때 p가 최대가 되도록 합니다.(원점에서 Hyper plane이 최대한 멀어지도록)

 

손으로 직접 쓴 유도식 및 OC-SVM 정리

 

OC-SVM 목적함수

조금더 디테일하게 정리를 해보자면, 기존 목적함수에서 제약식 2가지 텀을 추가해줌으로써, Abnormal(Hyper plane 바깥 데이터)과 Hyper plane간의 거리만 구합니다.

 

즉, 간단하게보면 Loss 함수 = min(Abnormal 데이터들과 Hyperplane사이의 거리) 가 되는것이죠

 

이렇게 만들어진 수식을, 라그랑쥬 승수법을 통해 재 전개를 합니다.

그리고 변수인 w,psi,lo에 대해 편미분을 하게되면 아래와 같이 나오는데요

 

여기서 얻어진 오른쪽 세가지 조건과 라그랑주 승수법에 따른 조건(beta*psi = 0)을 조합하여 OCSVM hyperplane을 얻어내게 됩니다.

scikitlearn으로 구현한 코드에서는 Nu(v)와 gamma가 변수로 들어가는데요

gamma는 hyper plane구성시 참조하는 데이터의 거리로, gamma가 클수록 주변데이터를 Support Vector로 보고

gamma가 작을수록 먼거리에 있는 데이터도 Support Vector로 보고 계산하는것입니다.

 

Nu는 라그랑주 수식에 의해 해석하면, Hyper plane 밖에 있는 데이터의 최대 비율이라고 보시면됩니다.

즉, 엄밀한 의미는 아니지만 러프하게  "Nu가 10%이다. = 최대 10%정도를 전체 데이터중 Abnormal이라고 가정하고 Hyperplane을 나누겠다" 라고 이해하시면 될것 같습니다.

 

 

코드

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.font_manager

from sklearn import svm

 

X_train = np.loadtxt("/dir", delimiter=",")

X_train = X_train

x_test = np.loadtxt("/dir",delimiter = ",")

X_test = x_test

 

#Generate some abnormal novel observations

X_outliers = np.random.randn(20,5)

print("X_train_shape : ",X_train.shape)

print("X_outliers : ",X_outliers.shape)

 

#Fit the model

clf = svm.OneClassSVM(nu = 0.01, kernel = "rbf", gamma = 0.00001)

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)

n_error_train = y_pred_train[y_pred_train == -1].size

n_error_test = y_pred_test[y_pred_test == -1].size

n_error_outliers = y_pred_outliers[y_pred_outliers == -1].size

 

print("n_error_train : ", n_error_train)

print("n_error_test : ", n_error_test)

print("y_pred_outliers : ",y_pred_outliers)

print("n error outliers : ", n_error_outliers)

 

 

결과

원본과 전혀 다른 데이터를 20개주고 테스트를해서, 20개모두 비정상으로 검출하게 나왔습니다.

OC-SVM을 돌려보니 nu와 gamma값을 잘 조정해주는게 중요하고, 정상데이터의 갯수도 엄청나게 많아야 제대로된 boundary를 그릴 수 있을것이라고 생각되네요

여러 차원의 비선형 데이터를 적용할때는 Powerful하다고 보기는 힘들것 같습니다.

 


 

SVDD(Support Vector Data Discription)

출처 : Deep One-Class Classificationm, Ruff (Deep-SVDD paper)

 

OC-SVM은 원점으로부터의 거리에 존재하는 Hyper plane, 즉 평면을 Boundary로 두고 정상/비정상을 판단했는데요

SVDD는 이게 평면이 아니라 Hypersphere(초구)형태로 boundary를 나누는것을 의미합니다.

 

즉, 원 밖은 비정상/ 안은 정상 Support Vector로 보는것이죠!

 

OC-SVM이 psi,w,lo 3개가 변수였다면, SVDD는 R(hypershpere의 반지름), psi, a(원의 중심)이 변수입니다.

Boundary를 얻어내는 과정은 라그랑주 승수법을 사용한다는 점에서 동일합니다.

 

SVDD 정리

 

하지만, 매번 이렇게 라그랑주승수법을 풀면서 Hyper sphere/plane을 얻을순 없습니다.

그렇게해서 딥러닝으로 이 변수들을 자동으로 구하게해보자! 하는 분야가

Deep-SVDD및 Deep SVM계열로 비교적 최근 활발히 연구되고 있습니다.

 

 

[참조]

1. Enhancing One-class Support Vector Machines for Unsupervised Anomaly Detection

   link : https://www.dfki.de/fileadmin/user_upload/import/6957_One-class-SVM_anomaly-detection.pdf

2. http://rvlasveld.github.io/blog/2013/07/12/introduction-to-one-class-support-vector-machines/

3. 고려대학교 산업경영공학과 강필성 교수님, Anomaly Detection 강의 중 OCSVM

4. One-Class SVMs for Document Classification, Larry M. Manevitz (원논문)

댓글