SVM理解与入门

作者: 抹茶不加茶 | 来源:发表于2020-03-11 19:59 被阅读0次

    原理

    SVM是支持向量机的缩写,可用于解决分类或者回归问题。
    我们前面讲过逻辑回归一类的算法,其特征如下

    1
    主要是通过一个决策面/决策边界将数据分类,但是我们可能会遇到决策边界不唯一的情况,我们将这称之为不适定问题
    2
    这时候要是出现一个新的数据,对于不同的决策边界,其分类结果可能会出现差异
    3
    SVM就是希望找到一个最优的决策边界,其实不难想象,最“中间”的那条线应该就是我们要去寻找的,具体的一些变量已经在图中画出
    另外我们也要注意到,数据有时候并不会如此规整地分布,有时候误差或者噪音也会出现,如果我们完完全全将两个类别直接分开,这是Hard Margin SVM;如果对于这一两个噪音,我们希望忽视他们的存在,虽然降低了原始数据的准确率,但是换来了我们更加重视的模型泛化能力,这是Soft Margin SVM。
    我们先来看Hard Margin SVM
    • 其实从上面的图以及分析我们不难得出一个结论,要想找到最优化的决策边界,我们希望margin或者d参数要尽可能的大,因为这时候我们得到的决策边界方向是最优的。
    • 所以SVM目标在这里就变成了最大化margin,即最大化d
    • 回忆高中数学知识中的直线间距公式,我们可推导出
      直线距离
      其中||w||表示w的模,也就是更号下wi的平方和
      如图,我们首先确定了我们的目标直线为图中函数式给出的那一条,也就是最中间的那一条
      题图
      对于两个类别中的数据点,他们都必须距离这个决策边界d以上的大小,于是我们得到两个不等式作为限制条件
      st
      我们同除d进行化简
      化简1
      这时候其实我们可以接着化简,因为分母就是一个数,我们只需要改改w和b即可
      化简2
      这时候图中三条直线便可以这样表示出来
      直线距离2
      我们未来将式子更好看方便,我们将wd还是记做w,bd还是记做b,但是这时候的式子意义上和之前的式子已然不同
      化简3
      类似于直接逻辑回归的化简,我们再进行如下变换
      化简4
      我们回过头来看我们的目标
      目标
      总结起来就是:
      总结
      其中st表示条件
    我们再来分析Soft Margin SVM以及正则化

    还是我们上面所提及的,之所以需要soft margin,是因为部分偏差误差数据,我们如果过于在意是否正确分出来,可能会导致过拟合,而我们更应该在意的是模型的泛化能力,所以我们需要做出一个拥有一定容错能力的SVM。


    1
    • 所谓容错能力,即意味着我们需要对之前的限制条件进行一定的宽松处理
      我们将st变为:


      soft

      那么我们如何去限制引入的参数不至于过大呢,因为如果过大那么容错过大势必引起模型的识别率降低。

    • 我们再将目标改变一下


      目标改变

      这时候新的总结为:(其中C是用来调节两部分的重要程度)


      总结
      其实这里的目标也可以这样:
      正则
    标准化处理

    类似于knn,SVM在使用前也需要进行数据标准化处理


    当一方单位很大时
    当两方单位相同时

    所以我们需要进行标准化处理

    使用sklearn进行实现

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    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
    

    得到散点图


    原始数据
    #使用SVM算法进行分类
    
    #先进行标准化
    from sklearn.preprocessing import StandardScaler
    standardScaler=StandardScaler()
    standardScaler.fit(x)
    x_standand=standardScaler.transform(x)
    
    #使用线性svm
    from sklearn.svm import LinearSVC#C表示分类
    svc=LinearSVC(C=1e9)
    svc.fit(x_standand,y)
    
    结果1

    绘制代码有些复杂,能力有限不做写出


    C值很大时的结果
    svc2=LinearSVC(C=0.01)
    svc2.fit(x_standand,y)
    svc2.score(x_standand,y)
    

    我们调整C值,得到新的结果


    结果2
    C值较小时的结果

    正如我们上面所分析的,减小C值可以使得容错率上升,虽然会降低一定的准确率,但是提到了模型泛化能力

    SVM中使用多项式特征
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    from sklearn import datasets
    x,y=datasets.make_moons()
    x,y=datasets.make_moons(noise=0.15)
    plt.scatter(x[y==0,0],x[y==0,1])
    plt.scatter(x[y==1,0],x[y==1,1])
    

    我们可以得到这个数据集的大小为:


    大小

    数据集未添加噪音前的散点图为


    原始散点图
    加噪后
    #使用多项式特征的SVM
    from sklearn.preprocessing import PolynomialFeatures,StandardScaler
    from sklearn.svm import LinearSVC
    from sklearn.pipeline import Pipeline
    def PolynomialSVC(degree,C=1):
        return Pipeline([
            ("poly",PolynomialFeatures(degree=degree)),
            ("std_scaler",StandardScaler()),
            ("linearSVC",LinearSVC(C=C))
        ])
    poly_svc=PolynomialSVC(degree=3)
    poly_svc.fit(x,y)
    poly_svc.score(x,y)
    

    这时候我们利用sklearn中的LinearSVC进行处理,其中利用了管道


    结果3
    得到的score非常高

    我们还可以使用多项式核函数进行处理

    #使用多项式核函数的SVM
    from sklearn.preprocessing import PolynomialFeatures,StandardScaler
    #from sklearn.svm import LinearSVC
    from sklearn.pipeline import Pipeline
    from sklearn.svm import SVC
    def PolynomialKernelSVC(degree,C=1.0):
        return Pipeline([
            #("poly",PolynomialFeatures(degree=degree)),
            ("std_scaler",StandardScaler()),
            ("kernelSVC",SVC(kernel="poly",degree=degree,C=C))#kernl参数设置为poly时可以达到多项式特征效果
        ])
    poly_kernel_svc=PolynomialKernelSVC(degree=3)
    poly_kernel_svc.fit(x,y)
    poly_kernel_svc.score(x,y)
    
    结果4

    这个核函数计算的结果和前面使用poly计算的结果却是不同的,我们接着来了解核函数

    核函数

    我们前面得到了目标优化的函数以及条件不等式,我们可以继续转换成等价条件


    等价于

    回顾之前,我们是如何进行多项式分类的呢,我们是在原来数据的基础上,加上了一个多项式项,然后变成新的x'。


    原来的办法
    而核函数的思想是,我们可以通过一个函数运算,使得x(i),x(j)经过函数运算之后的结果直接就是x'(i)*x'(j)
    核函数办法

    这里的K函数即为核函数

    多项式核函数
    定义为: 多项式核函数,这里为二次
    原理
    d阶的多项式核函数,d为degree

    前面我们传了kernel=poly,同时degree设为3,即使用的是三阶的多项式核函数


    线性核函数
    高斯核函数

    高斯核函数是SVM中使用最多的核函数

    高斯核函数RBF
    gamma是唯一的超参数
    • 高斯核函数将每一个样本点映射到一个无穷维的特征空间
      依靠升维使得原本线性不可分的数据线性可分


      一维
      二维

      如图,我们通过升维使得原本线性不可分的数据变得线性可分
      高斯核函数就是这个原理
      举个例子:


      高斯核函数将一维映射到二维
      映射后
      实际上,有多少个样本,高斯函数中就会有多少个地表点,也就是y有多少个取值,x映射到多少维
      映射
      由于样本数是可以无穷个,所以说,可以映射成无穷维
      高斯函数分布

      我们可以很容易得到gamma和sitea的关系,进而又图像我们们可以得出结论

    • gamma越大,高斯分布越窄;
    • gamma越小,高斯分布越宽
      我们下面利用sklearn来看一下:
    from sklearn.preprocessing import StandardScaler
    from sklearn.svm import SVC
    from sklearn.pipeline import Pipeline
    def RBFKernelSVC(gamma=1.0):
        return Pipeline([
            #("poly",PolynomialFeatures(degree=degree)),
            ("std_scaler",StandardScaler()),
            ("rbfSVC",SVC(kernel="rbf",gamma=gamma))#kernl参数设置为poly时可以达到多项式特征效果
        ])
    svc=RBFKernelSVC(gamma=1)
    svc.fit(x,y)
    svc.score(x,y)
    
    决策边界gamma=1
    准确率gamma=1
    svc100=RBFKernelSVC(gamma=100)
    svc100.fit(x,y)
    svc100.score(x,y)
    
    决策边界gamma=100
    准确率gamma=100

    于是我们得出结论,gamma过大时会过拟合,gamma过小时也会欠拟合,这里欠拟合的图就不贴出来了

    使用SVM解决回归问题

    希望数据尽可能的在线之间,与前述分类问题相反
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import datasets
    boston= datasets.load_boston()
    x=boston.data
    y=boston.target  
    from sklearn.model_selection import train_test_split
    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=6)
    #实际上这里size默认是0.2
    from sklearn.svm import LinearSVR
    from sklearn.svm import SVR
    from sklearn.preprocessing import StandardScaler
    from sklearn.pipeline import Pipeline
    def StandardLinearSVR(epsilon=1.0):
       return Pipeline([
           #("poly",PolynomialFeatures(degree=degree)),
           ("std_scaler",StandardScaler()),
           ("linearSVR",LinearSVR(epsilon=epsilon))
       ])
    svr=StandardLinearSVR()
    svr.fit(x_train,y_train)
    svr.score(x_test,y_test) 
    
    结果

    相关文章

      网友评论

        本文标题:SVM理解与入门

        本文链接:https://www.haomeiwen.com/subject/ahdqjhtx.html