소개
이 실습에서는 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 의 결과와 이 근사 결과를 비교했습니다. 또한, 예제 데이터셋을 생성하고 모델의 결과를 플롯했습니다.