SGD 기반 One-Class SVM 비교 플롯

Beginner

This tutorial is from open-source community. Access the source code

소개

이 실습에서는 RBF 커널의 경우 One-Class SVM 의 해를 근사하기 위해 확률적 경사 하강법 (SGD) 을 사용하는 방법을 보여줍니다.

이 근사 결과를 커널화된 접근 방식을 사용한 One-Class SVM 의 결과와 비교할 것입니다. 이 실습의 목적은 계산 시간 측면에서 근사의 이점을 보여주는 것이 아니라, 소규모 데이터셋에서 SGD 를 사용하여 유사한 결과를 얻을 수 있음을 보여주는 데 있습니다.

VM 팁

VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습을 위한 Jupyter Notebook에 접근합니다.

때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사를 자동화할 수 없습니다.

학습 중 문제가 발생하면 Labby 에 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.

라이브러리 가져오기

이 실습에서는 NumPy, Matplotlib, scikit-learn 라이브러리를 가져와 사용합니다.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import OneClassSVM
from sklearn.linear_model import SGDOneClassSVM
from sklearn.kernel_approximation import Nystroem
from sklearn.pipeline import make_pipeline

데이터 생성

이 실습에서는 소규모 데이터셋을 생성합니다. 훈련 샘플 500 개, 테스트 샘플 20 개, 이상치 샘플 20 개를 생성합니다.

random_state = 42
rng = np.random.RandomState(random_state)

## 훈련 데이터 생성
X = 0.3 * rng.randn(500, 2)
X_train = np.r_[X + 2, X - 2]
## 일반적인 새로운 관측치 생성
X = 0.3 * rng.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
## 이상치 새로운 관측치 생성
X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))

일변량 SVM 적합

먼저 RBF 커널을 사용하는 일변량 SVM 을 데이터셋에 적합시킵니다.

## OCSVM 하이퍼파라미터
nu = 0.05
gamma = 2.0

## 일변량 SVM 적합
clf = OneClassSVM(gamma=gamma, kernel="rbf", nu=nu)
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

Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

SGD 를 사용한 일변량 SVM 적합

다음으로, SGD 를 사용하여 일변량 SVM 을 적합합니다. 커널 근사를 사용하여 데이터셋에 SGD 를 적용합니다.

## 커널 근사와 SGD 를 사용한 일변량 SVM 적합
transform = Nystroem(gamma=gamma, random_state=random_state)
clf_sgd = SGDOneClassSVM(
    nu=nu, shuffle=True, fit_intercept=True, random_state=random_state, tol=1e-4
)
pipe_sgd = make_pipeline(transform, clf_sgd)
pipe_sgd.fit(X_train)
y_pred_train_sgd = pipe_sgd.predict(X_train)
y_pred_test_sgd = pipe_sgd.predict(X_test)
y_pred_outliers_sgd = pipe_sgd.predict(X_outliers)
n_error_train_sgd = y_pred_train_sgd[y_pred_train_sgd == -1].size
n_error_test_sgd = y_pred_test_sgd[y_pred_test_sgd == -1].size
n_error_outliers_sgd = y_pred_outliers_sgd[y_pred_outliers_sgd == 1].size

Z_sgd = pipe_sgd.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z_sgd = Z_sgd.reshape(xx.shape)

결과 플롯

마지막으로, One-Class SVM 과 SGD 를 사용한 One-Class SVM 의 결과를 플롯합니다.

## 결정 함수의 레벨 세트를 플롯
plt.figure(figsize=(9, 6))
plt.title("One Class SVM")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap=plt.cm.PuBu)
a = plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors="darkred")
plt.contourf(xx, yy, Z, levels=[0, Z.max()], colors="palevioletred")

s = 20
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c="white", s=s, edgecolors="k")
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c="blueviolet", s=s, edgecolors="k")
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c="gold", s=s, edgecolors="k")
plt.axis("tight")
plt.xlim((-4.5, 4.5))
plt.ylim((-4.5, 4.5))
plt.legend(
    [a.collections[0], b1, b2, c],
    [
        "학습된 경계",
        "훈련 관측치",
        "새로운 일반 관측치",
        "새로운 이상 관측치",
    ],
    loc="upper left",
)
plt.xlabel(
    "훈련 오류: %d/%d; 새로운 일반 오류: %d/%d; 새로운 이상 오류: %d/%d"
    % (
        n_error_train,
        X_train.shape[0],
        n_error_test,
        X_test.shape[0],
        n_error_outliers,
        X_outliers.shape[0],
    )
)
plt.show()

plt.figure(figsize=(9, 6))
plt.title("온라인 One-Class SVM")
plt.contourf(xx, yy, Z_sgd, levels=np.linspace(Z_sgd.min(), 0, 7), cmap=plt.cm.PuBu)
a = plt.contour(xx, yy, Z_sgd, levels=[0], linewidths=2, colors="darkred")
plt.contourf(xx, yy, Z_sgd, levels=[0, Z_sgd.max()], colors="palevioletred")

s = 20
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c="white", s=s, edgecolors="k")
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c="blueviolet", s=s, edgecolors="k")
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c="gold", s=s, edgecolors="k")
plt.axis("tight")
plt.xlim((-4.5, 4.5))
plt.ylim((-4.5, 4.5))
plt.legend(
    [a.collections[0], b1, b2, c],
    [
        "학습된 경계",
        "훈련 관측치",
        "새로운 일반 관측치",
        "새로운 이상 관측치",
    ],
    loc="upper left",
)
plt.xlabel(
    "훈련 오류: %d/%d; 새로운 일반 오류: %d/%d; 새로운 이상 오류: %d/%d"
    % (
        n_error_train_sgd,
        X_train.shape[0],
        n_error_test_sgd,
        X_test.shape[0],
        n_error_outliers_sgd,
        X_outliers.shape[0],
    )
)
plt.show()

요약

이 실험에서는 RBF 커널을 사용한 일변량 SVM 의 해를 근사하기 위해 확률적 경사 하강법 (SGD) 을 사용하는 방법을 보여주었습니다. 커널 기반 접근 방식을 사용한 일변량 SVM 의 결과와 이 근사 결과를 비교했습니다. 또한, 예제 데이터셋을 생성하고 모델의 결과를 플롯했습니다.