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


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

    一、支持向量机的原理

    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()

  • 相关阅读:
    【Linux】文件权限详解
    小程序获取用户手机号
    2022.11.8-----leetcode.1684
    Java上传文件大小受限怎么解决
    一幅长文细学TypeScript(一)——上手
    列举一些常用的Webpack配置和插件
    C/C++运算优先级
    Certificates does not conform to algorithm constraints 解决方案
    {} >= {} 返回 true
    Java学习笔记:SQLite数据库
  • 原文地址:https://blog.csdn.net/qq_52421831/article/details/127770723