ADP 실기 7장 Support Vector Machine
본 게시물은 Support Vector Machine에 대해 소개한다.
1. Support Vector Machine
1.1 Concpet
SVM은 새로운 데이터가 입력되었을 때 기존 데이터를 활용해 분류하는 방법으로, SVC를 확장한 알고리즘
1.2 최대 마진 분류기
- 초평면: p차원 공간에서 차원이 (p-1)인 평평한 affin 부분 공간
- margin: 관측치부터 초평면 사이의 가장 짧은 거리
- maximal margin: 관측치로부터 마진이 가장 큰 평면을 찾음
- support vector: 초평면에서 가장 가까운 관측치
1.3 서포트 벡터 분류기
- 일부 오류를 수용하는 최대 마진을 가진 초평면 분류기
1.4 서포트 벡터 머신
- SVC는 데이터가 두 클래스로 나뉘고, 경계가 선형일 경우
- SVM은 SVC의 개념을 확장하여 커널 함수를 사용해 고차원에서 선형 분류를 하는 기법
1.5 서포트 벡터 회귀
- SVM은 일정한 마진 오류 안에서 두 클래스 간의 도로 폭이 최대가 되도록 학습
- SVR은 제한된 마진 오류 안에서 도로 안에 가능한 많은 데이터 샘플이 속하도록 학습
2. Support Vector Classifier
2.1 Parameters
class sklearn.svm.SVC(*, C=1.0, kernel=‘rbf’, degree=3, gamma=‘scale’, coef0=0.0,
shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None,
verbose=False, max_iter=- 1, decision_function_shape=‘ovr’, break_ties=False,
random_state=None)
- C: 오분류 허용 계수 (C>0)
- kernel: linear, poly, rbf, sigmoid, precomputed
- degree: 커널 함수를 poly로 하였을 때 설정함
- gamma: 커널 함수를 poly, rbf, sigmoid로 설정하였을 때, scaling 계수
- class_weight: 각 클래스의 가중치로 None일때 모든 가중치는 1
2.2 Attributes
- class_weight_: 각 클래스의 가중치
- coef_: 커널을 linear로 하였을 때 계수
- support_vectors_: 서포트 벡터
2.3 Methods
- decision_function(X): 데이터 샘플의 confidence score를 반환
- predict(X), predict_proba(X), predict_log_proba(X)
2.4 Implementation
😗 데이터 불러오기
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
c=pd.read_csv(“https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/classification.csv”)
c
# 데이터 분포 확인
sns.pairplot(hue='success', data=c)
# 데이터 분리
from sklearn.model_selection import train_test_split
x=c[['age', 'interest']]
y=c['success']
train_x, test_x, train_y, test_y = train_test_split(x,y,stratify=y,
train_size=0.7, random_state=1)
print(train_x.shape, test_x.shape, train_y.shape, test_y.shape)
(207, 2) (90, 2) (207,) (90,)
# 스케일링 적용 및 데이터 분포 확인
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
train_x=scaler.fit_transform(train_x)
sns.pairplot(data=pd.concat([pd.DataFrame(train_x),
train_y.reset_index(drop=True)],
axis=1),
hue='success')
- SVM은 이상치에 민감하기에 Standard Scaler를 적용
- Scaler 적용 후 데이터의 분포를 명확히 확인 가능
# 분류기 모델 생성 및 학습
from sklearn.svm import SVC
clf = SVC(C=0.5, random_state=45)
clf.fit(train_x, train_y)
# 평가
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score
test_x_scal = scaler.transform(test_x)
pred=clf.predict(test_x_scal)
test_cm=confusion_matrix(test_y, pred)
test_acc=accuracy_score(test_y, pred)
test_prc=precision_score(test_y, pred)
test_rcll=recall_score(test_y, pred)
test_f1=f1_score(test_y, pred)
print(test_cm)
print('정확도\t{}%'.format(round(test_acc*100,2)))
print('정밀도\t{}%'.format(round(test_prc*100,2)))
print('재현율\t{}%'.format(round(test_rcll*100,2)))
print('F1\t{}%'.format(round(test_f1*100,2)))
[[37 2]
[10 41]]
정확도 86.67%
정밀도 95.35%
재현율 80.39%
F1 87.23%
📍 오분류 계수에 따른 Margin의 변화
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import LinearSVC
plt.figure(figsize=(10, 5))
for i, C in enumerate([1, 500]):
clf = LinearSVC(C=C, loss="hinge", random_state=42).fit(train_x,
train_y)
# decision function으로 서포트 벡터 얻기
decision_function = clf.decision_function(train_x)
support_vector_indices = np.where(np.abs(decision_function) <= 1 +
1e-15)[0]
support_vectors = train_x[support_vector_indices]
plt.subplot(1, 2, i + 1)
plt.scatter(train_x[:, 0], train_x[:, 1], c=train_y, s=30, cmap
=plt.cm.Paired)
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx, yy = np.meshgrid(
np.linspace(xlim[0], xlim[1], 50), np.linspace(ylim[0], ylim[1], 50)
)
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contour(
xx,
yy,
Z,
colors="k",
levels=[-1, 0, 1],
alpha=0.5,
linestyles=["--", "-", "--"],
)
plt.scatter(
support_vectors[:, 0],
support_vectors[:, 1],
s=100,
linewidth=1,
facecolors="none",
edgecolors="k",
)
plt.title("C=" + str(C))
plt.tight_layout()
plt.show()
3. Support Vector Regression
3.1 Parameters
class sklearn.svm.SVR(*, kernel=‘rbf’, degree=3, gamma=‘scale’, coef0=0.0,
tol=0.001, C=1.0, epsilon=0.1, shrinking=True, cache_size=200, verbose=False,
max_iter=- 1)
- SVC와 동일
3.2 Attributes
- SVC와 동일
3.3 Methods
- 분류가 아니기에 prob를 구하는 method는 없음
- 나머진 동일
3.4 Implementation
😗 데이터 생성하기
import numpy as np
X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
print(X[0:6], '\n\n',y[0:10])
[[0.52871606]
[0.57116235]
[0.66348438]
[0.69907167]
[0.85967932]
[0.96984676]]
[0.50442513 0.54061027 0.61586575 0.64350738 0.7576333 0.82479908
0.83998352 0.86173085 0.86618382 0.89379124]
# 타깃데이터에 노이즈 추가하기
y[::5] += 3 * (0.5 - np.random.rand(8))
print(y[0:10])
- 노이즈를 추가함으로 실제 환경과 비슷하게 함
# 커널별 회귀 모델 생성 및 학습
from sklearn.svm import SVR
svr_rbf = SVR(kernel="rbf", C=100, gamma=0.1, epsilon=0.1)
svr_lin = SVR(kernel="linear", C=100, gamma="auto")
svr_poly = SVR(kernel="poly", C=100, gamma="auto", degree=3,
epsilon=0.1, coef0=1)
svr_rbf.fit(X, y)
svr_lin.fit(X, y)
svr_poly.fit(X, y)
# 커널별 모델 평가
rbf_pred=svr_rbf.predict(X)
lin_pred=svr_lin.predict(X)
poly_pred=svr_poly.predict(X)
from sklearn.metrics import mean_squared_error, mean_absolute_error, mean_squared_error
import pandas as pd
import numpy as np
preds = [rbf_pred, lin_pred, poly_pred]
kernel = ['Random_Forest', 'Linear', 'Polynomial']
evls = ['mse', 'rmse', 'mae']
results=pd.DataFrame(index=kernel,columns=evls)
for pred, nm in zip(preds, kernel):
mse = mean_squared_error(y, pred)
mae = mean_absolute_error(y, pred)
rmse = np.sqrt(mse)
results.loc[nm]['mse']=round(mse,2)
results.loc[nm]['rmse']=round(rmse,2)
results.loc[nm]['mae']=round(mae,2)
results
lw = 2
svrs = [svr_rbf, svr_lin, svr_poly]
kernel_label = ["RBF", "Linear", "Polynomial"]
model_color = ["m", "c", "g"]
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 10), sharey=True)
for ix, svr in enumerate(svrs):
axes[ix].plot(
X,
svr.fit(X, y).predict(X),
color=model_color[ix],
lw=lw,
label="{} model".format(kernel_label[ix]),
)
axes[ix].scatter(
X[svr.support_],
y[svr.support_],
facecolor="none",
edgecolor=model_color[ix],
s=50,
label="{} support vectors".format(kernel_label[ix]),
)
axes[ix].scatter(
X[np.setdiff1d(np.arange(len(X)), svr.support_)],
y[np.setdiff1d(np.arange(len(X)), svr.support_)],
facecolor="none",
edgecolor="k",
s=50,
label="other training data",
)
axes[ix].legend(
loc="upper center",
bbox_to_anchor=(0.5, 1.1),
ncol=1,
fancybox=True,
shadow=True,
)
fig.text(0.5, 0.04, "data", ha="center", va="center")
fig.text(0.06, 0.5, "target", ha="center", va="center", rotation="vertical")
fig.suptitle("Support Vector Regression", fontsize=14)
plt.show()
댓글남기기