단일 클래스 서포트 벡터 머신(One-Class Support Vector Machine)
이번 포스팅에서는 단일 클래스 분류 기법 중 단일 클래스 서포트 벡터 머신(One-Class Support Vector Machine, OC-SVM)에 관한 내용을 공유해보려고 합니다.
OC-SVM 이란?
Support Vector 기반의 Anomaly Detection 방법 중 하나로 Data를 N차원의 Feature space로 mapping 한 뒤, 분류 경계면(Hyper Plane)을 통해 mapping된 Data 중 normal data들이 원점으로부터 최대한 멀어지게 만들어서 분류하는 방법입니다.
일반적인 SVM과는 차이를 가지고 있는데, Binary-Classification에 많이 쓰이는 SVM은 각 데이터들 속 Support Vector 간의 Margin을 기준으로 Hyper plane을 나누지만, OCSVM은 원점을 기준으로 하기에, 조건에 따라 데이터가 아무리 많아도 Class가 1개일 수 있습니다.
Hyper Plane
위의 수식에 따라 Hyper plane을 구할 수 있으며 크게 3가지의 텀으로 구분됩니다. 첫 번째는 1/2*llwll^2 텀으로 각 데이터들에 따라 모델의 변동성이 최소화 되도록 보정하는 역할을 수행합니다. 두 번째는 1/vn * sigma(psi) 텀으로 psi는 데이터와 hyper plane간의 거리를 의미합니다. 추후 보정텀이 추가되어, Hyper plane 바깥(비정상)에 있는 점들의 거리의 SUM만 남게됩니다. (비정상일수록 Loss커짐) 세 번째는 p(lo) 텀으로 원점과 Hyper plane간의 거리, 이 값을 빼줆으로써 최소화 문제를 만족할 때 p가 최대가 되도록 합니다.(원점에서 Hyper plane이 최대한 멀어지도록)
다음으로 예제 코드를 통해 OC-SVM을 살펴보겠습니다.
Step 1: Import Libraries
필요한 라이브러리를 임포트 합니다.
# Synthetic dataset from sklearn.datasets import make_classification # Data processing import pandas as pd import numpy as np from collections import Counter # Visualization import matplotlib.pyplot as plt # Model and performance from sklearn.svm import OneClassSVM from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report
Step 2: Create Imbalanced Dataset
불균형 데이터를 생성합니다.
# Create an imbalanced dataset X, y = make_classification(n_samples=100000, n_features=2, n_informative=2, n_redundant=0, n_repeated=0, n_classes=2, n_clusters_per_class=1, weights=[0.995, 0.005], class_sep=0.5, random_state=0) # Convert the data from numpy array to a pandas dataframe df = pd.DataFrame({'feature1': X[:, 0], 'feature2': X[:, 1], 'target': y}) # Check the target distribution df['target'].value_counts(normalize = True)
Step 3: Train Test Split
학습을 위해 훈련 데이터와 테스트 데이터를 분리합니다.
# Train test split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Check the number of records print('The number of records in the training dataset is', X_train.shape[0]) print('The number of records in the test dataset is', X_test.shape[0]) print(f"The training dataset has {sorted(Counter(y_train).items())[0][1]} records for the majority class and {sorted(Counter(y_train).items())[1][1]} records for the minority class.")
Step 4: Train One-Class Support Vector Machine (SVM) Model
OCSVM을 학습합니다.
# Train the one class support vector machine (SVM) model one_class_svm = OneClassSVM(nu=0.01, kernel = 'rbf', gamma = 'auto').fit(X_train)
Step 5: Predict Anomalies
학습한 모델을 바탕으로 결과 값을 예측합니다.
# Predict the anomalies prediction = one_class_svm.predict(X_test) # Change the anomalies' values to make it consistent with the true values prediction = [1 if i==-1 else 0 for i in prediction] # Check the model performance print(classification_report(y_test, prediction))
Step 6: Customize Predictions Using Scores
점수를 사용하여 예측합니다.
# Get the scores for the testing dataset score = one_class_svm.score_samples(X_test) # Check the score for 2% of outliers score_threshold = np.percentile(score, 2) print(f'The customized score threshold for 2% of outliers is {score_threshold:.2f}') # Check the model performance at 2% threshold customized_prediction = [1 if i < score_threshold else 0 for i in score] # # Check the prediction performance print(classification_report(y_test, customized_prediction))
Step 7: Visualization
결과를 시각화 합니다.
# Put the testing dataset and predictions in the same dataframe df_test = pd.DataFrame(X_test, columns=['feature1', 'feature2']) df_test['y_test'] = y_test df_test['one_class_svm_prediction'] = prediction df_test['one_class_svm_prediction_cutomized'] = customized_prediction # Visualize the actual and predicted anomalies fig, (ax0, ax1, ax2)=plt.subplots(1,3, sharey=True, figsize=(20,6)) # Ground truth ax0.set_title('Original') ax0.scatter(df_test['feature1'], df_test['feature2'], c=df_test['y_test'], cmap='rainbow') # One-Class SVM Predictions ax1.set_title('One-Class SVM Predictions') ax1.scatter(df_test['feature1'], df_test['feature2'], c=df_test['one_class_svm_prediction'], cmap='rainbow') # One-Class SVM Predictions With Customized Threshold ax2.set_title('One-Class SVM Predictions With Customized Threshold') ax2.scatter(df_test['feature1'], df_test['feature2'], c=df_test['one_class_svm_prediction_cutomized'], cmap='rainbow')
이상으로 단일 클래스 서포트 벡터 머신에 대해 알아보았습니다.
참고 자료