总体概述:
在数据点中找到距离分割平面最近的点(支持向量),然后优化w和b来最大化支持向量到分割超平面的距离。
支持向量机(SVM)是机器学习算法之一,是二分类算法。给定一组训练样本集,如图,样本数据集是二维的,分散在平面上,需要找到一条直线将数据集分割开。可以分开的直线有很多,我们要找到其中泛化能力最好,鲁棒性最强的直线。这是在平面上的点,如果是在三维空间中,则需要找到一个平面;如果是超过三维以上的维数,则需要找到一个超平面。
超平面的表达式为(超平面上任意一点在法向量W上投影长度为定值b):
原理举例:wT取(w1,w2),x取(x1,x2)T, 则原式得 w1x1+w2x2+b=0 与传统直线 Ax+By+c=0 方程式
相同,由二维三维空间推到更高维平面的一般式即为上式。
W:为平面法向量,决定了超平面的方向
b: 决定了超平面距原点的距离
法向量与样本属性的个数、超空间维数相同。在超空间中我们要求的参数就是决定超平面的W和b值。
在超空间中任意一点x到超平面的距离为:
我们可以由特殊到一般的理解一下这个式子,如果在二维空间即平面上,点到直线的距离为:
式子中A,B,C是直线的参数也就是W,x0和y0是x的坐标,这样r式是不是就好理解了,这个距离是几何距离,也就是人眼直观看到的距离。几何距离只有大小没有方向,因为式子是被套上绝对值的,将绝对值摘掉,现在我们就人为规定,样本数据中到超平面的距离为正的点为+1类的样本点,就是这类点给它打个标签+1,到超平面的距离为负的点标签为-1,为什么不是+2,-2其实都可以,取1是为了后续方便计算;
现在假设这个超平面能够将样本正确分类,只不过这个超平面的w和b值我们不知道,这正是我们要求的,但是这个平面是一定存在的,有:
将几何距离r式中的分子绝对值和分母拿掉以后(因为都为正)剩下的wT+b是能够判断出样本为+1还是-1类别的部分,定义函数距离(很重要)为:
函数距离就是样本类别乘wT+b。因为正样本类别为+1,且wT+b也为正;负样本类别为-1且wT+b为负。所以函数距离只有大小没有方向。
函数距离就相当于几何距离的分子部分,在所有样本中每一个点都有一个函数距离和一个几何距离,几何距离是可观测到的直接的距离,函数距离具有如下性质:一个点到超平面的函数距离取决于这个超平面的法向量和b值,同一个超平面可以有多组w和b值,但每组值成比例。w和b值不同,点的函数距离也不同。
三维空间举例:
现有两个平面2x+3y+4z+2=0 与 4x+6y+8z+4=0
有点:x(1,1,1),则点到平面的函数距离分别为:11,22。但平面实质为一个平面,只有w和b值不同,也就是说我们可以通过放缩w和b值,来控制函数距离!!!
重点:支持向量机数学模型原理,其实就是通过控制函数距离来求得最大几何距离。也就是函数距离为约束条件,几何距离为目标函数。具体往下看:
通过放缩w和b,让两类中某一类点距超平面的函数距离分别为1(离超平面的距离相等,为1方便后续计算)。
W和b值未知,但总存在一组值满足上述。如图:
中间最粗的平面为我们要求的超平面,两边的虚线为支撑平面,支撑平面上的点就是支持向量,通过放缩超平面的w和b值,使支持向量到超平面的函数距离为1,支持向量是距超平面最近的点,所以其他向量点到超平面的函数距离一定大于等于1。其实这时候就可以建立最初的模型了,为:
解释一下这个模型,首先先不看目标函数,先看约束条件,约束添加表达的是所有样本点到超平面的距离要大于等于1,在支撑平面上的为1,其他的大于1,根据约束条件其实可以得到无数个平面,如下面两个:
但是,在这些平面中我们需要的是泛华能力最好,鲁棒性最强的那一个,也就是最宽的那一个(margin最大),这时候就需要通过定义目标函数来求得,宽度最大也就是几何距离最大,几何距离的分子是函数距离,而两个支撑平面的函数距离我们定义完了是2,所以才有了上面的数学模型。
总的来说,就是通过函数距离作为约束条件得到无数个能把样本正确分开的平面,然后通过目标函数在这些平面中找最宽的!
把上面的数学模型转化为:
把求最大转变为求最小,即把模型转化为凸函数,其实到这里已经是优化问题了,凸函数是比较容易找到最优解的,因为局部极值就等于全局极值。至于为什么加个二分之一的系数,加个平方,都是为了后续解模型时求导方便。这个模型即为支持向量机的基本型,后面涉及到的软间隔,支持向量回归都从这个形式出发。
所建立的模型为凸二次规划(局部极值的全局极值、目标函数为二次约束条件为一次)。能直接用现成的优化计算包求解,但是可以有更高效的办法。利用拉格朗日乘子法,将两个参数的优化问题转化为一个参数的优化问题,进而求解模型。
对所建立的模型使用拉格朗日乘子法,将约束条件转化为目标函数,即对每条约束添加拉格朗日乘子 ɑi>0。得到如下拉格朗日函数。
对于等式约束可以直接使用拉格朗日乘子法求极值,对于不等式约束要满足KKT条件约束进行求解,模型对应的KKT条件为:
将w公式代入原函数有:
上面最后的那个式子可以看到已经不含w和b值了,就只有拉格朗日乘子。利用SMO算法将每个样本数据的乘子解出来,观察约束条件
总有
和
前者意味着向量点根本不会在求和中出现,后者意味着向量在支撑平面上,是一个支撑向量,训练完成后大部分样本都不需要保留。也就是训练完后大部分拉格朗日乘子都为零,只有在支撑平面上的样本的拉格朗日乘子不为0。
至此,已经对支持向量机有一个基本认识,以上数学推理为支持向量机的硬间隔。记住这个模型:
支持向量机的软间隔、核函数方法、支持向量回归都是在这个模型的基础上的。上面讲的是样本完全线性可分,但是实际中,不可分的情况多谢,如果是线性不可分的如:
需要把数据映射到更高维空间,这时候用到核函数。
参考:
https://www.zybuluo.com/77qingliu/note/1137445
常用核函数
如果数据有噪声如:
那么用到的是支持向量机的软间隔。
如果你不是分类数据而是要有监督的预测数据,那么就是支持向量回归。
线性可分支持向量机的实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
生成模拟数据
导入sklearn模拟二分类数据生成模块
from sklearn.datasets.samples_generator import make_blobs
生成模拟二分类数据集
X, y = make_blobs(n_samples=150, n_features=2, centers=2, cluster_std=1.2, random_state=40)
设置颜色参数
colors = {0:'r', 1:'g'}
绘制二分类数据集的散点图
plt.scatter(X[:,0], X[:,1], marker='o', c=pd.Series(y).map(colors))
plt.show();
将标签转换为1/-1
y_ = y.copy()
y_[y_==0] = -1
y_ = y_.astype(float)
数据切割
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y_, test_size=0.3, random_state=43)
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
凸优化求解库cvxopt的使用
from cvxopt import matrix, solvers
定义二次规划参数
P = matrix([[1.0,0.0],[0.0,0.0]])
q = matrix([3.0,4.0])
G = matrix([[-1.0,0.0,-1.0,2.0,3.0],[0.0,-1.0,-3.0,5.0,4.0]])
h = matrix([0.0,0.0,-15.0,100.0,80.0])
构建求解
sol = solvers.qp(P, q, G, h)
获取最优值
print(sol['x'], sol['primal objective'])
线性可分支持向量机
### 实现线性可分支持向量机
### 硬间隔最大化策略
class Hard_Margin_SVM:
### 线性可分支持向量机拟合方法
def fit(self, X, y):
训练样本数和特征数
m, n = X.shape
初始化二次规划相关变量:P/q/G/h
self.P = matrix(np.identity(n + 1, dtype=np.float))
self.q = matrix(np.zeros((n + 1,), dtype=np.float))
self.G = matrix(np.zeros((m, n + 1), dtype=np.float))
self.h = -matrix(np.ones((m,), dtype=np.float))
将数据转为变量
self.P[0, 0] = 0
for i in range(m):
self.G[i, 0] = -y[i]
self.G[i, 1:] = -X[i, :] * y[i]
构建二次规划求解
sol = solvers.qp(self.P, self.q, self.G, self.h)
对权重和偏置寻优
self.w = np.zeros(n,)
self.b = sol['x'][0]
for i in range(1, n + 1):
self.w[i - 1] = sol['x'][i]
return self.w, self.b
### 定义模型预测函数
def predict(self, X):
return np.sign(np.dot(self.w, X.T) + self.b)
创建线性可分支持向量机模型实例
hard_margin_svm = Hard_Margin_SVM()
执行训练
hard_margin_svm.fit(X_train, y_train)
模型预测
y_pred = hard_margin_svm.predict(X_test)
from sklearn.metrics import accuracy_score
计算测试集准确率
print(accuracy_score(y_test, y_pred))
from matplotlib.colors import ListedColormap
### 绘制线性可分支持向量机决策边界图
def plot_classifer(model, X, y):
超参数边界
x_min = -7
x_max = 12
y_min = -12
y_max = -1
step = 0.05
meshgrid
xx, yy = np.meshgrid(np.arange(x_min, x_max, step),
np.arange(y_min, y_max, step))
模型预测
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
定义color map
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA'])
cmap_bold = ListedColormap(['#FF0000', '#003300'])
z = z.reshape(xx.shape)
plt.figure(figsize=(8, 5), dpi=96)
plt.pcolormesh(xx, yy, z, cmap=cmap_light)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold)
plt.show()
plot_classifer(hard_margin_svm, X_train, y_train)
分类:
sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=None,random_state=None)
参数:
C:C-SVC的惩罚参数C,默认值是1.0,C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。
kernel :核函数,默认是rbf,可以是'linear’, 'poly’, 'rbf’, 'sigmoid’, 'precomputed’
– 线性:linear
– 多项式:(gamma*u’v + coef0)^degree– RBF函数:exp(-gamma|u-v|^2)–sigmoid:tanh(gammau’*v + coef0)
degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。
gamma :'rbf’,'poly’ 和'sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features
coef0 :核函数的常数项。对于'poly’和 'sigmoid’有用。
probability :是否采用概率估计.默认为False
布尔类型,可选,默认为False
决定是否启用概率估计。需要在训练fit()模型时加上这个参数,之后才能用相关的方法:predict_proba和predict_log_proba
shrinking :是否采用shrinking heuristic方法,默认为true
tol :停止训练的误差值大小,默认为1e-3
cache_size :核函数cache缓存大小,默认为200
class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)
verbose :允许冗余输出?
max_iter :最大迭代次数。-1为无限制。
decision_function_shape :'ovo’, 'ovr’ or None, default=None3
random_state :数据洗牌时的种子值,int值
主要调节的参数有:C、kernel、degree、gamma、coef0。
回归:
sklearn.svm.SVR(kernel ='rbf',degree = 3,gamma ='auto_deprecated',coef0 = 0.0,tol = 0.001,C = 1.0,epsilon = 0.1,shrinking = True,cache_size = 200,verbose = False,max_iter = -1 )
SVM种类,用途和关键参数表
使用SVM预测模型的通用步骤:
(1)选择使用的SVM类
(2)用数据训练模型
(3)检查验证误差并作为基准线
(4)为SVM参数尝试不同的值
(5)检查验证误差是否改进
(6)再次使用最优参数的数据来训练模型
样例代码:
import numpy as np
from sklearn.model_selection import GridSearchCV
parameters={'kernel':['linear','rbf','sigmoid','poly'],'C':np.linspace(0.1,20,50),'gamma':np.linspace(0.1,20,20)}
svc = svm.SVC()
model = GridSearchCV(svc,parameters,cv=5,scoring='accuracy')
model.fit(X_train,y_train)
model.best_params_
model.score(X_test,y_test)
联系客服