Support Vector Machine。支持向量机,其含义是通过支持向量运算的分类器。其中“机”的意思是机器,可以理解为分类器。 那么什么是支持向量呢?在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。 见下图,在一个二维环境中,其中点R,S,G点和其它靠近中间黑线的点可以看作为支持向量,它们可以决定分类器,也就是黑线的具体参数。
解决的问题:
在训练数据中,每个数据都有n个的属性和一个二类类别标志,我们可以认为这些数据在一个n维空间里。我们的目标是找到一个n-1维的超平面(hyperplane),这个超平面可以将数据分成两部分,每部分数据都属于同一个类别。 其实这样的超平面有很多,我们要找到一个最佳的。因此,增加一个约束条件:这个超平面到每边最近数据点的距离是最大的。也成为最大间隔超平面(maximum-margin hyperplane)。这个分类器也成为最大间隔分类器(maximum-margin classifier)。 支持向量机是一个二类分类器。
SVM的一个优势是支持非线性分类。它结合使用拉格朗日乘子法和KKT条件,以及核函数可以产生非线性分类器。
SVM的目的是要找到一个线性分类的最佳超平面 f(x)=xw+b=0。求 w 和 b。
首先通过两个分类的最近点,找到f(x)的约束条件。
有了约束条件,就可以通过拉格朗日乘子法和KKT条件来求解,这时,问题变成了求拉格朗日乘子αi 和 b。
对于异常点的情况,加入松弛变量ξ来处理。
非线性分类的问题:映射到高维度、使用核函数。
线性分类及其约束条件
SVM的解决问题的思路是找到离超平面的最近点,通过其约束条件求出最优解。
最大几何间隔(geometrical margin)
求解问题w,b
我们使用拉格朗日乘子法(http://blog.csdn.net/on2way/article/details/47729419) 来求w和b,一个重要原因是使用拉格朗日乘子法后,还可以解决非线性划分问题。 拉格朗日乘子法可以解决下面这个问题:
消除w之后变为:
可见使用拉格朗日乘子法后,求w,b的问题变成了求拉格朗日乘子αi和b的问题。 到后面更有趣,变成了不求w了,因为αi可以直接使用到分类器中去,并且可以使用αi支持非线性的情况.
--------------------- 此段落来自 冬日新雨 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/dongrixinyu/article/details/79039215?utm_source=copy
导包sklearn.svm
from sklearn.svm import SVC
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import sklearn.datasets as datasets
使用make_blobs数据集
'''datasets.make_blobs(n_samples=100, n_features=2, centers=3,
cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)'''
X,y = datasets.make_blobs(centers=2)
plt.scatter(X[:,0],X[:,1],c = y)
随机生成数据,并且进行训练np.r_[]
f = lambda x:x + x**2 + x**1.5 +3*x**3 + x**4
a = np.linspace(0,20,100)
b = f(a)
plt.plot(a,b)
使用SVM算法训练
# kernel 分三种:线性、rbf(基于半径,圆),ploy(多项式,绘制的图形不一样)
'''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='ovr', random_state=None)'''
svc = SVC(kernel='linear')
svc.fit(X,y)
Out:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
训练模型,并训练
提取系数获取斜率
w_ = svc.coef_
w_
Out:array([[-0.39436727, 0.10620952]])
提取截距
b_ = svc.intercept_
b_
Out:array([2.37576905])
分析
# f(x,y) = w1x + w2y + b
# 三维立体中的一条直线
# f(x) = 3x + 4 f(x) = y
# y = 3x + 4
f(x,y) = z
f(x,y) = w_[0,0]*x + w_[0,1]*y + b_[0]
z = w_[0,0]*x + w_[0,1]*y + b_[0]
# 当z = 0 表示,二维的平面
'''↓↓↓'''
0 = w_[0,0]*x + w_[0,1]*y + b_[0]
-w_[0,1]*y = w_[0,0]*x + b_[0]
y = -w_[0,0]/w_[0,1]*x - b_[0]/w_[0,1]
使用代码运算出w和b:
w = -w_[0,0]/w_[0,1]
b = - b_[0]/w_[0,1]
display(w,b)
Out:
3.713106637047493
-22.368701893533434
绘制分割线
plt.scatter(X[:,0],X[:,1],c = y)
x = np.linspace(0,8,100)
plt.plot(x,w*x + b,color = 'green')
上边界和下边界
supportvectors
# 支持向量,找出来的关键点
support_vectors_ = svc.support_vectors_
support_vectors_
Out:
array([[ 5.91535817, -9.81970096],
[ 1.18690432, -8.54625144]])
绘制支撑点
plt.scatter(X[:,0],X[:,1],c = y)
x = np.linspace(2,6,100)
plt.plot(x,w*x + b,color = 'green')
'''
①support_vectors_[:,0]=array([5.91535817, 1.18690432]) ,指的是x横坐标;
②s : scalar or array_like, shape (n, ), optional
size in points^2. Default is `rcParams['lines.markersize'] ** 2`.
'''
plt.scatter(support_vectors_[:,0],support_vectors_[:,1],s = 300,alpha = 0.3,color = 'red')
画出支持向量的两条平行线
# 求出两条直线,已知经过一个点(x,y),已知斜率w,求截距b:
# y = w*x + b
# b = y - w*x
'''上截距'''
b_up = support_vectors_[0,1] - w*support_vectors_[0,0]
'''下截距'''
b_down = support_vectors_[-1,1] - w*support_vectors_[-1,0]
3D图像:
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(12,9))
axes3d = Axes3D(fig)
axes3d.scatter(X[:,0],X[:,1],zs = 0)
创建数据集
X = np.random.randn(300,2)
plt.scatter(X[:,0],X[:,1])
# 翻看之前的逻辑运算,异或运算
y = np.logical_xor(X[:,0]>0,X[:,1]>0)
y
Out:
array([ True, False, True, False, False, False, False, False, True,
True, True, True, False, False, False, True, True, True,
False, False, False, False, False, True, False, False, True,
False, True, True, True, True, True, False, True, False,
True, True, True, False, False, True, True, True, True,
…………
plt.figure(figsize=(8,8))
plt.scatter(X[:,0],X[:,1],c = y)
plt.axis([-3,3,-3,3])
Out:
[-3, 3, -3, 3]
创造-3到3范围的点以及meshgrid
a = np.linspace(-3,3,100)
b = np.linspace(-3,3,100)
A,B = np.meshgrid(a,b)
X_test = np.concatenate([A.reshape(-1,1),B.reshape(-1,1)],axis = 1)
'''plt.scatter(A,B) == plt.scatter(DataFrame(X_test)[0],DataFrame(X_test)[1])
== plt.scatter(X_test[:,0],X_test[:,-1])
'''
plt.scatter(A,B)
创造模型:rbf,训练数据
svc = SVC()
svc.fit(X,y)
Out:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
绘制图形
绘制测试点到分离超平面的距离(decision_function)
绘制轮廓线
绘制训练点
desicion_ = svc.decision_function(X_test)
desicion_
Out:
array([-0.62425578, -0.65448087, -0.68527458, ..., -0.1871134 ,
-0.18071389, -0.17495279])
plt.figure(figsize=(8,8))
# 绘制轮廓线,等高线
# TypeError: Input must be a 2D array.
plt.contour(A,B,desicion_.reshape(100,100),cmap = 'cool')
# 绘制登高面
plt.contourf(A,B,desicion_.reshape(100,100),cmap = 'PuOr_r')
plt.scatter(X[:,0],X[:,1],c = y)
plt.axis([-3,3,-3,3])
导包
iris = datasets.load_iris()
X = iris['data'][:,:2]
y = iris['target']
提取数据只提取两个特征,方便画图
创建支持向量机的模型:'linear', 'poly'(多项式), 'rbf'(Radial Basis Function:基于半径函数),
svc_linear = SVC(kernel='linear')
svc_rbf = SVC(kernel='rbf')
svc_poly = SVC(kernel='poly')
训练模型
svc_linear.fit(X,y)
svc_rbf.fit(X,y)
svc_poly.fit(X,y)
Out:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='poly',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
图片背景点
plt.scatter(X[:,0],X[:,1],c = y)
a = np.linspace(4,8,300)
b = np.linspace(1.8,4.5,300)
A,B = np.meshgrid(a,b)
X_test = np.concatenate([A.reshape(-1,1),B.reshape(-1,1)],axis = 1)
linear_y_ = svc_linear.predict(X_test)
rbf_y_ = svc_rbf.predict(X_test)
poly_y_ = svc_poly.predict(X_test)
预测并绘制图形for循环绘制图形
plt.figure(figsize=(12,8))
# 绘制线性
axes = plt.subplot(2,2,1)
axes.scatter(X_test[:,0],X_test[:,1],c = linear_y_)
axes.scatter(X[:,0],X[:,1],c = y,cmap = plt.cm.GnBu)
# 绘制rbf
axes = plt.subplot(2,2,2)
axes.scatter(X_test[:,0],X_test[:,1],c = rbf_y_)
axes.scatter(X[:,0],X[:,1],c = y,cmap = plt.cm.GnBu)
# 绘制多项式
axes = plt.subplot(2,2,3)
axes.scatter(X_test[:,0],X_test[:,1],c = poly_y_)
axes.scatter(X[:,0],X[:,1],c = y,cmap = plt.cm.GnBu)
导包
from sklearn.svm import SVR
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
自定义样本点rand,并且生成sin值
X = np.linspace(0,2*np.pi,40).reshape(-1,1)
y = np.sin(X)
plt.scatter(X,y)
数据加噪
y[2::5] +=np.random.randn(8,1)*0.2
plt.scatter(X,y)
建立模型,训练数据,并预测数据,预测训练数据就行
svr_linear = SVR(kernel='linear')
svr_rbf = SVR(kernel='rbf')
svr_poly = SVR(kernel='poly')
绘制图形,观察三种支持向量机内核不同
svr_linear.fit(X,y)
svr_rbf.fit(X,y)
svr_poly.fit(X,y)
Out:
SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1, gamma='auto',
kernel='poly', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
X_test = np.linspace(0,2*np.pi,205).reshape(-1,1)
linear_y_ = svr_linear.predict(X_test)
rbf_y_ = svr_rbf.predict(X_test)
poly_y_ = svr_poly.predict(X_test)
plt.scatter(X,y)
plt.plot(X_test,linear_y_,label = 'linear')
plt.plot(X_test,rbf_y_,label = 'rbf')
plt.plot(X_test,poly_y_,label='poly')
plt.legend()