(十)支撑向量机SVM

一,什么是支撑向量机

Support Vector Machine

既可以解决分类问题,也可以解决回归问题

当决策边界不唯一带来的问题就是不适定问题(典型是图像处理中的一些问题,比如马赛克,去噪,图像放大,图像修补等)

逻辑回归的决策边界为何是唯一的?

逻辑回归通过求使损失函数最小的参数求解,损失函数完全是由数据集决定的。某一个数据的影响可能就会使决策边界偏离真实的边界。进而降低了泛化能力。

SVM的决策边界不仅可以对数据样本进行划分,还希望对未来数据的泛化能力也很好。SVM的决策边界可以均衡俩个分类样本间的距离,让边界离分类样本都要尽可能的远。


解决的是线性可分问题

Hard Margin SVM 严格的

Soft Margin SVM

二,SVM背后的最优化问题

点到直线的距离公式:

拓展到n维空间:

假设n维空间中求得的决策边界满足:

那么所有的样本点满足(拆绝对值后):

注意在这里样本点对应的标签改为了1和-1而不是1和0!

进一步除以分母

可以在图中表示出来:

合并俩个不等式

对于任意的支撑向量X,我们要最大化:

但是由于对于支撑向量来说,代入分母恒为±1,因此化成最大化:

进一步改成:

最优化过程中的限定条件是:

变成平方方便求导。

最终的SVM问题就是求解带有条件的函数最值问题。

三,Soft Margin和SVM的正则化

线性的决策边界允许对训练样本有一定的容错率,进而提高对预测数据的泛化能力。

如果样本点张这样,那么使用线性的决策边界是无论如何不可能完成分类的。容错的SVM就是Soft Margin SVM。

回顾Hard Margin SVM的求解函数:

现在我们可以对他的条件适当的放松。

在图中就可以表示为:

其中的虚线部分就是:

表述就是:允许有样本点落在虚线和HMSVM的边界内。这样引入另一个参数。

我们的最优化目标就可以表示为:

这样我们既可以有SVM的思想,又可以使得算法的容忍错误的程度又尽可能的小。后边那一项就是SVM的正则项。

在实际应用中,SVM和正则项的比例是不一定相同的,我们一般在正则项前加上超参数。

条件依旧是:

同样,正则化项也有对应的L1与L2正则:

四,scikit-learn中的SVM

和kNN一样,要做数据的标准化处理!

因为涉及距离!如果在每个维度上数据的量纲不同就会出现问题,因此要标准化处理。

导入数据:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.preprocessing import StandardScaler

from sklearn.svm import LinearSVC

iris = datasets.load_iris()

X = iris.data

y = iris.target

X = X[y<2,:2] #取俩个类别

y = y[y<2]

plt.scatter(X[y==0,0], X[y==0,1], color='red')

plt.scatter(X[y==1,0], X[y==1,1], color='blue')

plt.show()

标准化:

standardScaler = StandardScaler()

standardScaler.fit(X)

X_standard = standardScaler.transform(X)

使用线性SVM

svc = LinearSVC(C=1e9) #这里的C在SVM前,C越大,容错程度越小,偏向HardMargin

svc.fit(X_standard, y)

使用绘制决策边界的函数并绘制:

plot_decision_boundary(svc, axis=[-3, 3, -3, 3])

plt.scatter(X_standard[y==0,0], X_standard[y==0,1])

plt.scatter(X_standard[y==1,0], X_standard[y==1,1])

plt.show()

svc2 = LinearSVC(C=0.01) #改变权重

svc2.fit(X_standard, y)

利用svc.coef_和svc.intercept_查看系数和截距

定义绘制SVM的边界函数:

绘制HardMargin的决策边界

对于svc2的决策边界:

五,SVM中使用多项式特征和核函数

自定义多项式特征:

数据导入:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.preprocessing import PolynomialFeatures, StandardScaler

from sklearn.svm import LinearSVC

from sklearn.pipeline import Pipeline

def PolynomialSVC(degree, C=1.0): #创建管道,默认C是1.0

    return Pipeline([

        ("poly", PolynomialFeatures(degree=degree)), #加入多项式特征

        ("std_scaler", StandardScaler()),

        ("linearSVC", LinearSVC(C=C)) #C传入用户定义的C

    ])

X, y = datasets.make_moons() #自动生成的非线性数据

plt.scatter(X[y==0,0], X[y==0,1])

plt.scatter(X[y==1,0], X[y==1,1])

plt.show()

X, y = datasets.make_moons(noise=0.15, random_state=666) #加入噪音

使用多项式特征的SVM

poly_svc = PolynomialSVC(degree=3)

poly_svc.fit(X, y)

使用上节定义的边界绘图函数:

plot_decision_boundary(poly_svc, axis=[-1.5, 2.5, -1.0, 1.5])

plt.scatter(X[y==0,0], X[y==0,1])

plt.scatter(X[y==1,0], X[y==1,1])

plt.show()

使用多项式核函数的SVM:

from sklearn.svm import SVC

def PolynomialKernelSVC(degree, C=1.0):

    return Pipeline([

        ("std_scaler", StandardScaler()),

        ("kernelSVC", SVC(kernel="poly", degree=degree, C=C))

    ])

poly_kernel_svc = PolynomialKernelSVC(degree=3)

poly_kernel_svc.fit(X, y)

plot_decision_boundary(poly_kernel_svc, axis=[-1.5, 2.5, -1.0, 1.5])

plt.scatter(X[y==0,0], X[y==0,1])

plt.scatter(X[y==1,0], X[y==1,1])

plt.show()

六,什么是核函数

首先使用数学对优化函数进一步的变形:

如果使用多项式特征,x(i),x(j)变为多项式的x'(i),x'(j)再进行相乘的运算:

这样计算乘开后会复杂的多,并且增加了存储空间

核函数的想法是,可不可以不让x(i),x(j)发生上述变化,而是先对x(i),x(j)进行一个运算,使得

加入多项式特征的优化函数变为:

所以,核函数其实是一种数学技巧,并且在SVM中经常应用。

多项式核函数:

对于多项式核函数的degree,可以赋予不同的幂次:

线性核函数的d=1

七,RBF核函数

高斯核函数-SVM使用最多的核函数

高斯核函数也被称为:Radial Basis Function Kernel 镜像基函数

高斯核函数就是将每一个样本点映射到一个无穷维的特征空间

使用多项式特征为什么可以解决非线性问题?

依靠升维使得原本线性不可分的数据线性可分

方便理解:

原本的一维不可分数据长这样:

样本点都在一条直线上,就是线性不可分,但如果把样本点横坐标不变,扩充到二维空间

这样就线性可分

这就是升维的意义

高斯核的本质也是这样

在一个线性不可分的样本点中,插入俩个点l1和l2作为地标

这样y分别取这俩个地标的值,就可以变为:

使用程序具象化高斯核函数

import numpy as np

import matplotlib.pyplot as plt

x = np.arange(-4, 5, 1)

y = np.array((x >= -2) & (x <= 2), dtype='int') #线性不可分数据

def gaussian(x, l): #定义高斯核函数 其中l表示地标

    gamma = 1.0

    return np.exp(-gamma * (x-l)**2)

l1, l2 = -1, 1 #固定地标

X_new = np.empty((len(x), 2))

for i, data in enumerate(x):

    X_new[i, 0] = gaussian(data, l1)

    X_new[i, 1] = gaussian(data, l2)

plt.scatter(X_new[y==0,0], X_new[y==0,1])

plt.scatter(X_new[y==1,0], X_new[y==1,1])

plt.show()

这样就可以线性可分了

高斯核函数其实是把每一个数据点都作为了landmark。因此取了许多的landmark

将m*n的数据映射成为m*m的数据。所以当m<n,运算反而就会变得简单(eg.自然语言处理)

八,RBF核函数中的gamma

scikit-learn中的高斯核函数

高斯核函数:

高斯函数:

图像:

gamma越大,方差越小,图像越窄,数据越集中

程序:

依旧使用半月形数据并加入相同的噪音

建立pipline

使用封装好的SVC

svc = RBFKernelSVC(gamma=1)

svc.fit(X, y)

调用边界绘制函数

plot_decision_boundary(svc, axis=[-1.5, 2.5, -1.0, 1.5])

plt.scatter(X[y==0,0], X[y==0,1])

plt.scatter(X[y==1,0], X[y==1,1])

plt.show()

svc_gamma100 = RBFKernelSVC(gamma=100)

#发现gamma越大,边界越集中,明显过拟合

svc_gamma100.fit(X, y)

svc_gamma10 = RBFKernelSVC(gamma=10)

svc_gamma10.fit(X, y)

svc_gamma05 = RBFKernelSVC(gamma=0.5)

svc_gamma05.fit(X, y)

svc_gamma01 = RBFKernelSVC(gamma=0.1)

#gamma越小,边界越简单,会欠拟合

svc_gamma01.fit(X, y)

九,SVM思想解决回归问题

用SVM解决分类问题希望的是落在margin里的点越少越好

而用SVM解决回归问题则是希望里边的点越多越好

使用封装好的SVM

导入数据集:

import numpy as np

import matplotlib.pyplot as plt

from sklearn import datasets

from sklearn.model_selection import train_test_split

from sklearn.svm import LinearSVR #只能是线性的

from sklearn.svm import SVR #注意是不是SVC 可以有多项式

from sklearn.preprocessing import StandardScaler

from sklearn.pipeline import Pipeline

def StandardLinearSVR(epsilon=0.1): #定义pipline

    return Pipeline([

        ('std_scaler', StandardScaler()),

        ('linearSVR', LinearSVR(epsilon=epsilon))

    ])

boston = datasets.load_boston()

X = boston.data

y = boston.target

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

svr = StandardLinearSVR()

svr.fit(X_train, y_train)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值