小言_互联网的博客

机器学习 —— 支持向量机SVM(Support Vector Machine)

320人阅读  评论(0)

【关键词】支持向量,最大几何间隔,拉格朗日乘子法

一、支持向量机的原理

Support Vector Machine。支持向量机,其含义是通过支持向量运算的分类器。其中“机”的意思是机器,可以理解为分类器。 那么什么是支持向量呢?在求解的过程中,会发现只根据部分数据就可以确定分类器,这些数据称为支持向量。 见下图,在一个二维环境中,其中点R,S,G点和其它靠近中间黑线的点可以看作为支持向量,它们可以决定分类器,也就是黑线的具体参数。

解决的问题:

  • 线性分类

在训练数据中,每个数据都有n个的属性和一个二类类别标志,我们可以认为这些数据在一个n维空间里。我们的目标是找到一个n-1维的超平面(hyperplane),这个超平面可以将数据分成两部分,每部分数据都属于同一个类别。 其实这样的超平面有很多,我们要找到一个最佳的。因此,增加一个约束条件:这个超平面到每边最近数据点的距离是最大的。也成为最大间隔超平面(maximum-margin hyperplane)。这个分类器也成为最大间隔分类器(maximum-margin classifier)。 支持向量机是一个二类分类器。

  • 非线性分类

SVM的一个优势是支持非线性分类。它结合使用拉格朗日乘子法和KKT条件,以及核函数可以产生非线性分类器。

二、实战

1、画出决策边界

导包sklearn.svm


  
  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. %matplotlib inline
  5. # SVC: 分类
  6. # SVR:回归
  7. from sklearn.svm import SVC,SVR

随机生成数据,并且进行训练

  • from sklearn.datasets import make_blobs

  
  1. from sklearn.datasets import make_blobs
  2. data,target = make_blobs(centers= 2)
  3. target
  4. plt.scatter(data[:, 0],data[:, 1],c=target)

 创建SVC模型(使用线性核函数),并训练


  
  1. # C=1.0, 惩罚系数,C越大越严格(有可能过拟合),C越小越不严格
  2. # kernel='rbf', 核函数
  3. # linear:线性核函数,不常用
  4. # rbf:默认值,高斯核函数,基于半径的和函数,可以解决非线性问题
  5. # poly:多项式核函数
  6. svc = SVC(C= 1.0,kernel= 'linear')
  7. svc.fit(data,target)

提取系数获取斜率


  
  1. w1,w2 = svc.coef_[ 0]
  2. w1,w2
  3. # (1.0522835977410239, -0.8013229035839045)

线性方程的截距


  
  1. b = svc.intercept_[ 0]
  2. b
  3. # 9.794733796740164

得到线性方程


  
  1. # w1 * x1 + w2 * x2 + b = 0
  2. # x2 作为y轴,x1作为x轴
  3. # x2 = -(w1 * x1 + b) / w2

画图


  
  1. plt.scatter(data[:, 0],data[:, 1],c=target)
  2. x = np.linspace(data[:, 0]. min(),data[:, 0]. max(), 20)
  3. y = -(w1 * x + b) / w2
  4. plt.plot(x,y)

 

获取支持向量


  
  1. svc.support_vectors_
  2. '''
  3. array([[-5.79772872, 5.85766345],
  4. [-4.59471853, 4.94156096]])
  5. '''

画出支持向量所在直线


  
  1. plt.scatter(data[:, 0],data[:, 1],c=target)
  2. x = np.linspace(data[:, 0]. min(),data[:, 0]. max(), 20)
  3. y = -(w1 * x + b) / w2
  4. plt.plot(x,y)
  5. # 画支持向量
  6. vectors = svc.support_vectors_
  7. plt.scatter(vectors[:, 0],vectors[:, 1],c= 'r',alpha= 0.3,s= 200)
  8. # 活出支持向量所在的虚线
  9. # vectors = array([[-4.64189396, 5.45729366],
  10. # [-6.04692482, 7.04214351],
  11. # [-3.63094168, 5.92881411],
  12. # [-4.74569939, 7.93088232]])
  13. b1 = -(w1 * vectors[ 0, 0] + w2 * vectors[ 0, 1])
  14. b2 = -(w1 * vectors[ 1, 0] + w2 * vectors[ 1, 1])
  15. y1 = -(w1 * x + b1) / w2
  16. y2 = -(w1 * x + b2) / w2
  17. plt.plot(x,y1,ls= '--')
  18. plt.plot(x,y2,ls= '--')

 

2、使用多种核函数对iris数据集进行分类

导包

        from sklearn.datasets import load_iris


  
  1. from sklearn.datasets import load_iris
  2. data,target = load_iris(return_X_y= True)
  3. data.shape
  4. # (150, 4)

提取数据只提取两个特征,方便画图


  
  1. data2 = data[:,: 2].copy()
  2. plt.scatter(data2[:, 0],data2[:, 1],c=target)


  
  1. def get_XY( data2):
  2. x = np.linspace(data2[:, 0]. min(),data2[:, 0]. max(), 1000)
  3. y = np.linspace(data2[:, 1]. min(),data2[:, 1]. max(), 1000)
  4. X,Y = np.meshgrid(x,y)
  5. XY = np.c_[X.ravel(),Y.ravel()]
  6. return X,Y,XY
  7. X,Y,XY = get_XY(data2)

创建支持向量机的模型:'linear', 'poly'(多项式), 'rbf'(Radial Basis Function:基于半径函数)


  
  1. svc_dict = {
  2. 'linear':SVC(kernel= 'linear'),
  3. 'poly':SVC(kernel= 'poly'),
  4. 'rbf':SVC(kernel= 'rbf')
  5. }
  6. for i,key in enumerate(svc_dict):
  7. # 训练
  8. svc = svc_dict[key]
  9. svc.fit(data2,target)
  10. # 预测
  11. y_pred = svc.predict(XY)
  12. # 画图
  13. axes = plt.subplot( 1, 3,i+ 1)
  14. axes.pcolormesh(X,Y,y_pred.reshape( 1000, 1000),shading= 'auto')
  15. axes.scatter(data2[:, 0],data2[:, 1],c = target,cmap= 'rainbow')
  16. axes.set_title(key,fontsize= 20)

3、SVM分离坐标点

生成随机数据


  
  1. data = np.random.randn( 300, 2)
  2. data
  3. plt.scatter(data[:, 0],data[:, 1])

将1,3象限 和 2,4象限区分颜色


  
  1. target = (data[:, 0] * data[:, 1] > 0) * 1
  2. target
  3. # target = 1: 一三象限;target = 0:二四象限
  4. '''
  5. array([1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1,
  6. 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1,
  7. 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0,
  8. 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0,
  9. 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0,
  10. 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1,
  11. 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0,
  12. 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1,
  13. 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
  14. 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0,
  15. 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
  16. 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
  17. 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
  18. 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1])
  19. '''
  20. plt.scatter(data[:, 0],data[:, 1],c=target)

使用基于半径核函数


  
  1. svc = SVC()
  2. svc.fit(data,target)

创造一个范围的点以及meshgrid


  
  1. def get_XY( data):
  2. x = np.linspace(data[:, 0]. min(),data[:, 0]. max(), 1000)
  3. y = np.linspace(data[:, 1]. min(),data[:, 1]. max(), 1000)
  4. X,Y = np.meshgrid(x,y)
  5. XY = np.c_[X.ravel(),Y.ravel()]
  6. return X,Y,XY
  7. X,Y,XY = get_XY(data)

测试点到分离超平面的距离(decision_function)


  
  1. distance = svc.decision_function(XY)
  2. distance
  3. '''
  4. array([0.2733806 , 0.27487237, 0.27637551, ..., 0.33516833, 0.33292289,
  5. 0.33069489])
  6. '''

把距离当成一个二维的图片

画出图形

  • 等高线
    • C = plt.contour(X, Y, distance.reshape(1000, 1000))

  
  1. plt.figure(figsize=( 5, 5),dpi= 150)
  2. plt.imshow(distance.reshape( 1000, 1000),extent=[data[:, 0]. min(),data[:, 0]. max(),data[:, 1]. min(),data[:, 1]. max()])
  3. # 等高线
  4. C = plt.contour(X,Y,distance.reshape( 1000, 1000))
  5. plt.clabel(C) # 显示等高线
  6. plt.scatter(data[:, 0],data[:, 1],c=target)

4、使用SVM多种核函数进行回归

自定义样本点rand,并且生成sin值


  
  1. x = np.random.random( 100) * 10
  2. y = np.sin(x)
  3. plt.scatter(x, y)

数据加噪


  
  1. y[ : : 5] += np.random.randn( 20) * 0.2
  2. plt.scatter(x, y)

提供测试数据

x_test = np.linspace(0, 10, 100).reshape(-1, 1)

用不同的核函数预测


  
  1. # linear
  2. linear = SVR(kernel= 'linear')
  3. linear.fit(x.reshape(- 1, 1), y)
  4. y_linear = linear.predict(x_test)
  5. # poly
  6. poly = SVR(kernel= 'poly')
  7. poly.fit(x.reshape(- 1, 1), y)
  8. y_poly = poly.predict(x_test)
  9. # rbf
  10. rbf = SVR(kernel= 'rbf')
  11. rbf.fit(x.reshape(- 1, 1), y)
  12. y_rbf = rbf.predict(x_test)
  13. from sklearn.neighbors import KNeighborsRegressor
  14. from sklearn.tree import DecisionTreeRegressor
  15. # knn
  16. knn = KNeighborsRegressor(n_neighbors= 5)
  17. knn.fit(x.reshape(- 1, 1), y)
  18. y_knn = knn.predict(x_test)
  19. # tree
  20. tree = DecisionTreeRegressor()
  21. tree.fit(x.reshape(- 1, 1), y)
  22. y_ = tree.predict(x_test)

绘制图形,观察三种支持向量机内核不同


  
  1. plt.scatter(x, y)
  2. plt.plot(x_test, y_linear, label= 'Linear')
  3. plt.plot(x_test, y_poly, label= 'poly')
  4. plt.plot(x_test, y_rbf, label= 'rbf')
  5. plt.plot(x_test, y_knn, label= 'knn')
  6. plt.plot(x_test, y_, label= 'tree')
  7. plt.legend()


转载:https://blog.csdn.net/qq_52421831/article/details/127770723
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场