支持向量机

1. SVM基础

1.1 决策边界

  • 决策边界越宽越好
  • 损失函数越小越好
  • 点到决策边界距离越大越好

在这里插入图片描述

1.2 核函数

在线性 SVM 中转化为最优化问题时求解的公式计算都是以内积(dot product)形式出现的,其中 ϕ ( X ) \phi(X) ϕ(X)是把训练集中的向量点转化到高维的非线性映射函数。因为内积的算法复杂度非常大,利用核函数来取代计算非线性映射函数的内积。

类型:

  • 高斯核函数
  • 多项式核函数
  • S 型核函数(Sigmoid、tanh)

使用核函数 kernel 的意义在于:

  • 将向量的维度从低维映射到高维
  • 降低运算复杂度

1.3 低维不可分

  • 利用一个非线性的映射把原数据集中的向量点转化到一个更高维度的空间中(比如将二维空间中的点映射到三维空间)
  • 在这个高维度的空间中找一个线性的超平面来根据线性可分的情况处理
    在这里插入图片描述

1.4 解决多分类问题

将多分类问题转化为 n 个二分类问题,n 就是类别个数。
在这里插入图片描述

1.5 SVM 算法特性

  • 训练好的模型的算法复杂度是由支持向量的个数决定的,而不是由数据的维度决定的。所以 SVM 不太容易产生过拟合。
  • SVM 训练出来的模型完全依赖于支持向量,即使训练集里面所有非支持向量的点都被去除,重复训练过程,结果仍然会得到完全一样的模型。
  • 一个 SVM 如果训练得出的支持向量个数比较少,那么SVM 训练出的模型比较容易被泛化。

1.6 效果

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_clf = SVC(kernel='linear', C=100.0)
svm_clf.fit(X, y)
# w0x0 + w1x1 + b = 0
import matplotlib.pyplot as plt
import numpy as np


def plot_svc_decision_boundary(svm_clf, xmin, xmax, sv=True):
    w = svm_clf.coef_[0]
    b = svm_clf.intercept_[0]
    x0 = np.linspace(xmin, xmax, 200)
    decision_boundary = -w[0]/w[1] * x0 - b/w[1]
    margin = 1/w[1]
    gutter_up = decision_boundary + margin
    gutter_down = decision_boundary - margin

    if sv:
        svs = svm_clf.support_vectors_
        plt.scatter(svs[:, 0], svs[:, 1], s=180, facecolors='#FFAAAA')
    plt.plot(x0, decision_boundary, 'k-', linewidth=2)
    plt.plot(x0, gutter_up, 'k--', linewidth=2)
    plt.plot(x0, gutter_down, 'k--', linewidth=2)


plot_svc_decision_boundary(svm_clf, 0, 5.5)
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'bs')
plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'ys')
plt.axis([0, 5.5, 0, 2])
plt.show()

在这里插入图片描述

1.7 标准化的影响

  • 降低特征的数值影响
from sklearn.preprocessing import StandardScaler
s = StandardScaler()
X = s.fit_transform(X)
svm_clf1 = SVC(kernel='linear', C=100.0)
svm_clf1.fit(X, y)
plot_svc_decision_boundary(svm_clf1, -2, 2.5)
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'bs')
plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'ys')
plt.axis([-2, 2.5, -2, 2])
plt.show()

在这里插入图片描述

1.8 软间隔

  • SVM 本质是在完全分类的情况下,让边界越宽越好
  • 软间隔是在损失较小准确率(忽略异常点)的情况下,让决策边界更宽
  • 防止过拟合
  • 超参数 C 控制软间隔程度
from sklearn.svm import LinearSVC

iris = datasets.load_iris()

# petal length, petal width
X = iris['data'][:, (2, 3)]

# viginica
y = (iris['target'] == 2).astype(np.float64)
# scaler = StandardScaler()
# X = scaler.fit_transform(X)

svm_clf1 = LinearSVC(C=1, random_state=42, dual=True)
svm_clf2 = LinearSVC(C=100, random_state=42, dual=True)

svm_clf1.fit(X, y)
svm_clf2.fit(X, y)
# 未收敛警告
ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
plt.figure(figsize=(14, 4))
plt.subplot(121)
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'g^', label='Virginica')
plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'bs', label='Versicolor')
plot_svc_decision_boundary(svm_clf1, 4, 6, sv=False)
plt.xlabel('Petal length', fontsize=14)
plt.ylabel('Petal width', fontsize=14)
plt.legend()
plt.title('C = {}'.format(svm_clf1.C), fontsize=16)
plt.axis([4, 6, 0.8, 2.8])

plt.subplot(122)
plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'g^', label='Virginica')
plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'bs', label='Versicolor')
plot_svc_decision_boundary(svm_clf2, 4, 6, sv=False)
plt.xlabel('Petal length', fontsize=14)
plt.ylabel('Petal width', fontsize=14)
plt.legend()
plt.title('C = {}'.format(svm_clf2.C), fontsize=16)
plt.axis([4, 6, 0.8, 2.8])
plt.show()
# 使用较小的C值,降低过拟合风险
# 使用较高的C值,分类器会提高准确率,但会有较小的间隔

在这里插入图片描述

2. 非线性SVM

数据准备

from sklearn.datasets import make_moons

X, y = make_moons(n_samples=100, noise=0.15, random_state=42)


def plot_dataset(X, y, axes):
    plt.plot(X[:, 0][y == 0], X[:, 1][y == 0], 'bs')
    plt.plot(X[:, 0][y == 1], X[:, 1][y == 1], 'g^')
    plt.axis(axes)
    plt.xlabel('$x_1$', fontsize=20)
    plt.ylabel('$x_2$', fontsize=20)


plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.show()

在这里插入图片描述

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline

polynomial_svm_clf = Pipeline((
    ('poly_features', PolynomialFeatures(degree=3)),
    ('scaler', StandardScaler()),
    ('svm_clf', LinearSVC(C=10, loss='hinge', dual=True))
))

polynomial_svm_clf.fit(X, y)

2.1 决策边界

def plot_predictions(clf, axes):
    x0s = np.linspace(axes[0], axes[1], 100)
    x1s = np.linspace(axes[2], axes[3], 100)
    x0, x1 = np.meshgrid(x0s, x1s)
    X = np.c_[x0.ravel(), x1.ravel()]
    y_pred = clf.predict(X).reshape(x0.shape)
    plt.contourf(x0, x1, y_pred, cmap=plt.cm.brg, alpha=0.2)


plot_predictions(polynomial_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])

在这里插入图片描述

3 不同核函数的效果

3.1 线性

from sklearn.svm import SVC

# coef0为偏置项,影响小
poly_kernel_svm_clf = Pipeline((
    ('scaler', StandardScaler()),
    ('svm_clf', SVC(kernel='poly', degree=3, coef0=1, C=5))
))
poly_kernel_svm_clf.fit(X, y)
poly100_kernel_svm_clf = Pipeline((
    ('scaler', StandardScaler()),
    ('svm_clf', SVC(kernel='poly', degree=10, coef0=100, C=5))
))
poly100_kernel_svm_clf.fit(X, y)
plt.figure(figsize=(10, 4))

plt.subplot(121)
plot_predictions(poly_kernel_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title('$d=3, coef0=1, C=5$', fontsize=18)

plt.subplot(122)
plot_predictions(poly100_kernel_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title('$d=10, coef0=100, C=5$', fontsize=18)

plt.show()
# 左边较为简单,右边有过拟合趋势

在这里插入图片描述

3.2 高斯核函数

  • 利用相似度来变换特征
rbf_kernel_svm_clf = Pipeline((
    ('scaler', StandardScaler()),
    ('svm_clf', SVC(kernel='rbf', C=0.001, gamma=5))
))
poly_kernel_svm_clf.fit(X, y)
gamma1, gamma2 = 0.1, 5
C1, C2 = 0.001, 1000
hyperparams = (gamma1, C1), (gamma1, C2), (gamma2, C1), (gamma2, C2)

svm_clfs = []
for gamma, C in hyperparams:
    rbf_kernel_svm_clf = Pipeline([
        ('scaler', StandardScaler()),
        ('svm_clf', SVC(kernel='rbf', gamma=gamma, C=C))
    ])
    rbf_kernel_svm_clf.fit(X, y)
    svm_clfs.append(rbf_kernel_svm_clf)

plt.figure(figsize=(11, 7))

for i, svm_clf in enumerate(svm_clfs):
    plt.subplot(221+i)
    plot_predictions(svm_clf, [-1.5, 2.5, -1, 1.5])
    plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
    gamma, C = hyperparams[i]
    plt.title(r'$\gamma = {},C = {}$'.format(gamma, C), fontsize=16)
plt.tight_layout()
plt.show()

# gamma越大,C越大,过拟合风险大

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值