-
핸즈온 머신러닝[5] 서포트 벡터 머신(1)핸즈온머신러닝 2022. 6. 22. 21:59
https://www.youtube.com/watch?v=dP-cDdP_Y3A&list=PLJN246lAkhQjX3LOdLVnfdFaCbGouEBeb&index=16
선형 SVM 분류
라지 마진 분류
from sklearn.svm import SVC from sklearn import datasets iris = datasets.load_iris() X = iris["data"][:, (2, 3)] # 꽃잎 길이, 꽃잎 너비 y = iris["target"] setosa_or_versicolor = (y == 0) | (y == 1) X = X[setosa_or_versicolor] y = y[setosa_or_versicolor] # SVM 분류 모델 svm_clf = SVC(kernel="linear", C=float("inf")) svm_clf.fit(X, y) # SVC(C=inf, kernel='linear')
두 클래스를 가장 넓게 벌리는 결정 경계를 찾는 것이 서포트 벡터 머신의 알고리즘.
밑의 왼쪽 그림은 결정 경계가 샘플과 너무 가깝기 때문에 좋은 결정 경계라고 보기 어려움.
반면에 오른쪽 그림은 결정 경계가 샘플과의 거리를 최대로 잘 벌려놓았기 때문에 샘플을 잘 분류하고 있음.
이때 마진의 경계에 있는 벡터를 서포트 벡터라고 한다.
특성 스케일에 따른 민감성
Xs = np.array([[1, 50], [5, 20], [3, 80], [5, 60]]).astype(np.float64) ys = np.array([0, 0, 1, 1]) svm_clf = SVC(kernel="linear", C=100) svm_clf.fit(Xs, ys) plt.figure(figsize=(9,2.7)) plt.subplot(121) plt.plot(Xs[:, 0][ys==1], Xs[:, 1][ys==1], "bo") plt.plot(Xs[:, 0][ys==0], Xs[:, 1][ys==0], "ms") plot_svc_decision_boundary(svm_clf, 0, 6) plt.xlabel("$x_0$", fontsize=20) plt.ylabel("$x_1$ ", fontsize=20, rotation=0) plt.title("Unscaled", fontsize=16) plt.axis([0, 6, 0, 90]) from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(Xs) svm_clf.fit(X_scaled, ys) plt.subplot(122) plt.plot(X_scaled[:, 0][ys==1], X_scaled[:, 1][ys==1], "bo") plt.plot(X_scaled[:, 0][ys==0], X_scaled[:, 1][ys==0], "ms") plot_svc_decision_boundary(svm_clf, -2, 2) plt.xlabel("$x'_0$", fontsize=20) plt.ylabel("$x'_1$ ", fontsize=20, rotation=0) plt.title("Scaled", fontsize=16) plt.axis([-2, 2, -2, 2]) save_fig("sensitivity_to_feature_scales_plot")
특성을 표준화 했을 때와 하지 않았을 때 각각 모델에 훈련했을 때의 결과값
소프트 마진 분류
이상치에 민감한 하드 마진
X_outliers = np.array([[3.4, 1.3], [3.2, 0.8]]) # 이상치를 만들어줌 y_outliers = np.array([0, 0]) Xo1 = np.concatenate([X, X_outliers[:1]], axis=0) yo1 = np.concatenate([y, y_outliers[:1]], axis=0) Xo2 = np.concatenate([X, X_outliers[1:]], axis=0) yo2 = np.concatenate([y, y_outliers[1:]], axis=0) svm_clf2 = SVC(kernel="linear", C=10**9) svm_clf2.fit(Xo2, yo2) fig, axes = plt.subplots(ncols=2, figsize=(10,2.7), sharey=True) plt.sca(axes[0]) plt.plot(Xo1[:, 0][yo1==1], Xo1[:, 1][yo1==1], "bs") plt.plot(Xo1[:, 0][yo1==0], Xo1[:, 1][yo1==0], "yo") plt.text(0.3, 1.0, "Impossible!", fontsize=24, color="red") plt.xlabel("Petal length", fontsize=14) plt.ylabel("Petal width", fontsize=14) plt.annotate("Outlier", xy=(X_outliers[0][0], X_outliers[0][1]), xytext=(2.5, 1.7), ha="center", arrowprops=dict(facecolor='black', shrink=0.1), fontsize=16, ) plt.axis([0, 5.5, 0, 2]) plt.sca(axes[1]) plt.plot(Xo2[:, 0][yo2==1], Xo2[:, 1][yo2==1], "bs") plt.plot(Xo2[:, 0][yo2==0], Xo2[:, 1][yo2==0], "yo") plot_svc_decision_boundary(svm_clf2, 0, 5.5) plt.xlabel("Petal length", fontsize=14) plt.annotate("Outlier", xy=(X_outliers[1][0], X_outliers[1][1]), xytext=(3.2, 0.08), ha="center", arrowprops=dict(facecolor='black', shrink=0.1), fontsize=16, ) plt.axis([0, 5.5, 0, 2]) save_fig("sensitivity_to_outliers_plot") plt.show()
오른쪽 그림의 경우 이상치에 의해서 도로의 폭(마진)이 굉장히 좁아짐
왼쪽 그림의 경우 선형 경계로 분류할 수 없음
라지 마진 vs 마진 오류
import numpy as np from sklearn import datasets from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.svm import LinearSVC iris = datasets.load_iris() X = iris["data"][:, (2, 3)] # 꽃잎 길이, 꽃잎 너비 y = (iris["target"] == 2).astype(np.float64) # Iris virginica svm_clf = Pipeline([ ("scaler", StandardScaler()), ("linear_svc", LinearSVC(C=1, loss="hinge", random_state=42)), ]) svm_clf.fit(X, y) # Pipeline(steps=[('scaler', StandardScaler()), # ('linear_svc', LinearSVC(C=1, loss='hinge', random_state=42))])
svm_clf.predict([[5.5, 1.7]]) # array([1.])
꽃잎 길이, 꽃잎 너비를 주고 예측을 시킴 --> 양성 클래스로 분류됨
scaler = StandardScaler() svm_clf1 = LinearSVC(C=1, loss="hinge", random_state=42) svm_clf2 = LinearSVC(C=100, loss="hinge", random_state=42) # 규제를 달리함 scaled_svm_clf1 = Pipeline([ ("scaler", scaler), ("linear_svc", svm_clf1), ]) scaled_svm_clf2 = Pipeline([ ("scaler", scaler), ("linear_svc", svm_clf2), ]) scaled_svm_clf1.fit(X, y) scaled_svm_clf2.fit(X, y) Pipeline(steps=[('scaler', StandardScaler()), # ('linear_svc', # LinearSVC(C=100, loss='hinge', random_state=42))])
규제(C) 파라미터 값을 1일 때와 100일 때로 각각 달리해봄
# 스케일되지 않은 파라미터로 변경 b1 = svm_clf1.decision_function([-scaler.mean_ / scaler.scale_]) b2 = svm_clf2.decision_function([-scaler.mean_ / scaler.scale_]) w1 = svm_clf1.coef_[0] / scaler.scale_ w2 = svm_clf2.coef_[0] / scaler.scale_ svm_clf1.intercept_ = np.array([b1]) svm_clf2.intercept_ = np.array([b2]) svm_clf1.coef_ = np.array([w1]) svm_clf2.coef_ = np.array([w2]) # 서포트 벡터 찾기 (libsvm과 달리 liblinear 라이브러리에서 제공하지 않기 때문에 # LinearSVC에는 서포트 벡터가 저장되어 있지 않습니다.) # y:(0,1) -> t:(-1,1) t = y * 2 - 1 support_vectors_idx1 = (t * (X.dot(w1) + b1) < 1).ravel() support_vectors_idx2 = (t * (X.dot(w2) + b2) < 1).ravel() svm_clf1.support_vectors_ = X[support_vectors_idx1] svm_clf2.support_vectors_ = X[support_vectors_idx2]
fig, axes = plt.subplots(ncols=2, figsize=(10,2.7), sharey=True) plt.sca(axes[0]) plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^", label="Iris virginica") plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs", label="Iris versicolor") plot_svc_decision_boundary(svm_clf1, 4, 5.9) plt.xlabel("Petal length", fontsize=14) plt.ylabel("Petal width", fontsize=14) plt.legend(loc="upper left", fontsize=14) plt.title("$C = {}$".format(svm_clf1.C), fontsize=16) plt.axis([4, 5.9, 0.8, 2.8]) plt.sca(axes[1]) plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^") plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs") plot_svc_decision_boundary(svm_clf2, 4, 5.99) plt.xlabel("Petal length", fontsize=14) plt.title("$C = {}$".format(svm_clf2.C), fontsize=16) plt.axis([4, 5.9, 0.8, 2.8]) save_fig("regularization_plot")
C=1: 규제가 강해서 마진 오류가 많아짐
C=100: 규제가 약해서 마진 오류가 적음
문제
1. 하드 마진 분류와 소프트 마진 분류의 차이점을 설명하시오
2. SVM 모델의 하이퍼파라미터인 C 값에 따라 모델이 어떻게 달라지는지 설명하시오
3. SVM 모델은 특성의 스케일에 민감하다. 스케일을 조정하지 않은 데이터에 대하여 SVM 모델을 훈련시킬 때의 문제점은 무엇인가??
'핸즈온머신러닝' 카테고리의 다른 글
핸즈온 머신러닝[5] 서포트 벡터 머신(3) (0) 2022.07.05 핸즈온 머신러닝[5] 서포트 벡터 머신(2) (0) 2022.07.03 핸즈온 머신러닝[4] 모델 훈련(3) (0) 2022.06.14 핸즈온 머신러닝[4] 모델 훈련(2) (0) 2022.06.13 핸즈온 머신러닝[4] 모델 훈련(1) (0) 2022.05.13