• 机器学习作业---支持向量机SVM(一)了解SVM


    推文:支持向量机通俗导论(理解SVM的三层境界)

    ----------------线性核函数-----------------

    一:作业介绍

    在本练习的前半部分,您将使用支持向量机。各种示例2D数据集。使用这些数据集进行实验将帮助您直观地了解支持向量机如何工作,以及如何使用支持向量机的高斯内核。

    二:导入数据和数据可视化

    (一)数据导入

    data = sio.loadmat("ex6data1.mat")
    
    X = data['X']
    y = data['y'].flatten()
    m = y.size
    
    print(X.shape,y.shape)

    (二)数据显示

    print("X:
    ",X[:10,])
    print("y:
    ",y[:10])

    (三)数据可视化

    def plot_data(X,y):
        posX = X[np.where(y==1)]    #获取正样本
        negX = X[np.where(y==0)]    #获取负样本
    
        plt.scatter(posX[:,0],posX[:,1],c='b',marker='X')   #散点图绘制 正样本
        plt.scatter(negX[:,0],negX[:,1],c='r',marker='o')   #散点图绘制 负样本
    plt.figure()
    plot_data(X,y)
    plt.show()

    可以看出左上角的那个数据点为异常点(误差点)。

    (四)获取横轴、、竖轴最值。后面绘制决策边界需要

    print(np.min(X[:,0]),np.max(X[:,0]))    #0.086405 4.015
    print(np.min(X[:,1]),np.max(X[:,1]))    #1.6177 4.6162

    所以我们对于横轴取值范围为(-0.5,4.5),竖轴取值范围为(1.3,5)

    三:svm模块之线性核函数 

    sklearn提供了很多机器学习的库,本次作业主要也是用它来解决SVM的问题

    重点补充numpy.meshgrid()理解

    https://blog.csdn.net/lllxxq141592654/article/details/81532855

    (一)C=1时(C较小时,相当于入较大(平滑,泛化能力好),可能会导致欠拟合,高偏差),不因为一个异常点影响“大边界”

    1.获取分类器的准确率

    c = 1
    clf = svm.SVC(c,kernel="linear",tol=1e-3)   #实例化分类器,C为误差项惩罚系数,核函数选择线性核,停止训练的误差值大小,默认为1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
    clf.fit(X,y)    #导入数据进行训练
    
    print(clf.score(X,y))   #分类器的准确率

    2.绘制决策边界《重点》

    #绘制决策边界
    def plot_boundary(model):
        x_min,x_max = -0.5,4.5
        y_min, y_max = 1.3, 5
        # 生成网格点坐标矩阵
        xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                           np.linspace(y_min,y_max,500))
        # print(xx.shape,yy.shape)
        # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->对应了网格点坐标矩阵中的每一个坐标点
        # 用训练好的分类器去预测各个坐标点中的数据的标签为[1]的值(其他为0)---全为1的位置就是决策边界
        z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
        # print(z.shape)
        # for i in range(z.size):   #z中全为0、1值
        #     if z[i] != 0:
        #         print(z[i])
        zz = z.reshape(xx.shape)    #将我们预测出来的z值有一维空间,转换为二维网格坐标矩阵,便于在二维平面绘制决策边界
        plt.contour(xx, yy, zz) #绘制决策边界 xx,yy是矩阵坐标,zz是我们对各个坐标的赋值,其中为1 的地方就是我们要找的决策边界
    data = sio.loadmat("ex6data1.mat")
    
    X = data['X']
    y = data['y'].flatten()
    m = y.size
    
    c = 1
    clf = svm.SVC(c,kernel="linear",tol=1e-3)   #实例化分类器,C为误差项惩罚系数,核函数选择线性核,停止训练的误差值大小,默认为1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
    clf.fit(X,y)    #导入数据进行训练
    
    plt.figure()
    
    plot_boundary(clf)
    plot_data(X,y)
    plt.show()

    c=1,此时不因为一个异常点影响“大边界”,拟合效果较好

    (二)c=100,可以很好的拟合正类和负类,但由于一个异常点造成过拟合,不能最大边界

    ----------------高斯核函数-----------------

    一:数据导入及可视化

    (一)数据可视化

    data = sio.loadmat("ex6data2.mat")
    
    X = data['X']
    y = data['y'].flatten()
    m = y.size
    
    plt.figure()
    
    plot_data(X,y)
    plt.show()

    (二)获取数据上下界

    print(np.min(X[:,0]),np.max(X[:,0]))    #0.0449309 0.998848
    print(np.min(X[:,1]),np.max(X[:,1]))    #0.402632 0.988596

    所以我们绘制决策边界时,取横坐标从(0,1)。竖轴(0.4,1)

    二:svm模块之高斯核函数

    使用高斯核函数解决线性不可分问题,并观察 σ取值对模型复杂度的影响。

    (一)简单实现高斯核函数---测试

    高斯核函数公式:

    def gaussian_kernel(x1,x2,sigma=0.1):
        x1 = x1.flatten()
        x2 = x2.flatten()
    
        gk = np.exp(-np.sum(np.power((x1-x2),2))/(2*np.power(sigma,2)))
    
        return gk
    x1 = np.array([1,2,1])
    x2 = np.array([0,4,-1])
    sigma = 2
    
    print(gaussian_kernel(x1,x2,sigma))

    (二)调用sklearn中的高斯核函数实现SVM算法

    c = 1gamma = 1
    clf = svm.SVC(c,kernel="rbf",gamma)   #实例化分类器,C为误差项惩罚系数,核函数选择高斯核,设置gamma字段为gamma,注意gamma不等于σ,但是两者有关联。https://blog.csdn.net/weixin_41990278/article/details/93137009
    clf.fit(X,y)    #导入数据进行训练
    
    print(clf.score(X,y))   #分类器的准确率

    补充:SVM算法中的gamma字段《重点》

    此外大家注意RBF公式里面的sigma和gamma的关系如下:

    (三)绘制决策边界---修改坐标范围即可

    #绘制决策边界
    def plot_boundary(model):
        x_min,x_max = 0,1
        y_min, y_max = 0.4, 1
        # 生成网格点坐标矩阵
        xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                           np.linspace(y_min,y_max,500))
        # print(xx.shape,yy.shape)
        # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->对应了网格点坐标矩阵中的每一个坐标点
        # 用训练好的分类器去预测各个坐标点中的数据的标签为[1]的值(其他为0)---全为1的位置就是决策边界
        z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
        # print(z.shape)
        # for i in range(z.size):   #z中全为0、1值
        #     if z[i] != 0:
        #         print(z[i])
        zz = z.reshape(xx.shape)    #将我们预测出来的z值有一维空间,转换为二维网格坐标矩阵,便于在二维平面绘制决策边界
        plt.contour(xx, yy, zz) #绘制决策边界 xx,yy是矩阵坐标,zz是我们对各个坐标的赋值,其中为1 的地方就是我们要找的决策边界
    plt.figure()
    
    plot_boundary(clf)
    plot_data(X,y)
    plt.show()

    可以看出当gamma=1时,拟合效果并不是很好!!!

    (四)不同gamma的选取

    1.gamma=1时

    分类器的准确率如下:

    2.gamma=50

    分类器的准确率如下:

    3.gamma=1000

    分类器的准确率如下:

    (五)结论:σ和gamma

    sigma和gamma的关系如下:

    这里面大家需要注意的就是gamma的物理意义,就是大家提到很多的RBF的幅宽,它会影响每个支持向量对应的高斯的作用范围,从而影响泛化性能。

    1.如果gamma设的太大,σ会很小,σ很小的高斯分布长得又高又瘦, 会造成只会作用于支持向量样本附近,对于未知样本分类效果很差,存在训练准确率可以很高,(如果让σ无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合)而测试准确率不高的可能,就是通常说的过训练;

    2.而如果gamma设的过小,σ会很大,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。

    ----------------寻找最优参数 C 和 σ-----------------

    一:SVM模型有两个非常重要的参数C与σ

    (一)其中 C是惩罚系数,即对误差的宽容度。

    1.c越高,入越小,容易过拟合。说明越不能容忍出现误差,

    2.C越小,入越大,容易欠拟合。说明可以容忍出现误差,

    C过大或过小,泛化能力变差

    (二)σ隐含地决定了数据映射到新的特征空间后的分布

    gamma是选择RBF函数作为kernel后,该函数自带的一个参数。

    从gamma和σ之间关系,可以看出。gamma也隐含地决定了数据映射到新的特征空间后的分布

    1.如果gamma设的太大,σ会很小,σ很小的高斯分布长得又高又瘦, 会造成只会作用于支持向量样本附近,对于未知样本分类效果很差,存在训练准确率可以很高,(如果让σ无穷小,则理论上,高斯核的SVM可以拟合任何非线性数据,但容易过拟合)而测试准确率不高的可能,就是通常说的过训练;

    2.而如果gamma设的过小,σ会很大,则会造成平滑效应太大,无法在训练集上得到特别高的准确率,也会影响测试集的准确率。

    二:加载数据及数据可视化

    (一)绘制数据(训练集数据)

    def plot_data(X,y):
        posX = X[np.where(y==1)]    #获取正样本
        negX = X[np.where(y==0)]    #获取负样本
    
        plt.scatter(posX[:,0],posX[:,1],c='b',marker='X')   #散点图绘制 正样本
        plt.scatter(negX[:,0],negX[:,1],c='r',marker='o')   #散点图绘制 负样本
    data = sio.loadmat("ex6data3.mat")
    
    X = data['X']
    y = data['y'].flatten()
    X = data['X']
    y = data['y'].flatten()
    Xval = data['Xval']
    yval = data['yval'].flatten()
    m = y.size
    plt.figure()
    
    plot_data(X,y)
    plt.show()

     

    (二)获取数据最值

    print(np.min(X[:,0]),np.max(X[:,0]))    #-0.596774 0.297235
    print(np.min(X[:,1]),np.max(X[:,1]))    #-0.657895 0.573392

    这里我们取横轴(-0.6,0.4),竖轴(-0.7,0.6)

    三:根据验证集评分获取最优准确率和参数(C、σ)

    def get_best_params(X,y,Xval,yval):
        # C 和 σ 的候选值
        Cvalues = [3, 10, 30, 100, 0.01, 0.03, 0.1, 0.3, 1]  # 9
        gammas = [1, 3, 10, 30, 100, 0.01, 0.03, 0.1, 0.3]  # 9
    
        best_score = 0  #用于存放最佳准确率
        best_params = (0,0) #用于存放参数C和σ
    
        for c in Cvalues:
            for gamma in gammas:
                clf = svm.SVC(c,kernel='rbf',gamma=gamma)
                clf.fit(X,y)    # 用训练集数据拟合模型
                score = clf.score(Xval,yval)    # 用验证集数据进行评分
                if score > best_score:
                    best_score = score
                    best_params = (c,gamma)
    
        return best_score,best_params
    score, params = get_best_params(X,y,Xval,yval)
    print("score:
    ",score)
    print("C gamma:
    ",params)

    注意:获取到的最优参数组合不只有一组(可能有多组的评分一样,都是最优,这里我们使用了>,所以只取了第一个最优的),更改候选值的顺序,最佳参数组合及其对应的决策边界也会改变。

    四:根据我们获得的最优参数,绘制决策边界

    #绘制决策边界
    def plot_boundary(model):
        x_min,x_max = -0.6,0.4
        y_min, y_max = -0.7,0.6
        # 生成网格点坐标矩阵
        xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                           np.linspace(y_min,y_max,500))
        # print(xx.shape,yy.shape)
        # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->对应了网格点坐标矩阵中的每一个坐标点
        # 用训练好的分类器去预测各个坐标点中的数据的标签为[1]的值(其他为0)---全为1的位置就是决策边界
        z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
        # print(z.shape)
        # for i in range(z.size):   #z中全为0、1值
        #     if z[i] != 0:
        #         print(z[i])
        zz = z.reshape(xx.shape)    #将我们预测出来的z值有一维空间,转换为二维网格坐标矩阵,便于在二维平面绘制决策边界
        plt.contour(xx, yy, zz) #绘制决策边界 xx,yy是矩阵坐标,zz是我们对各个坐标的赋值,其中为1 的地方就是我们要找的决策边界
    data = sio.loadmat("ex6data3.mat")
    
    X = data['X']
    y = data['y'].flatten()
    Xval = data['Xval']
    yval = data['yval'].flatten()
    
    score, params = get_best_params(X,y,Xval,yval)
    
    c = params[0]
    gamma = params[1]
    clf = svm.SVC(c,kernel="rbf",gamma=gamma)   #实例化分类器,C为误差项惩罚系数,核函数选择线性核,停止训练的误差值大小,默认为1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
    clf.fit(X,y)    #导入数据进行训练
    
    plt.figure()
    
    plot_boundary(clf)
    plot_data(X,y)
    plt.show()

  • 相关阅读:
    前端开发聚合
    6. webRTC
    14.移动端图片浏览组件 react-wx-images-viewer
    windows下怎样使用md命令一次建立多级子目录
    mysql打印输出转csv格式
    Java Stream简介, 流的基本概念
    Linux使用Shell脚本实现ftp的自动上传下载
    在Linux中设置UMASK值
    SFTP+OpenSSH+ChrootDirectory设置
    导出php5.4支持的数组格式,即以[]为标识符而不是以array()标识
  • 原文地址:https://www.cnblogs.com/ssyfj/p/12927232.html
Copyright © 2020-2023  润新知