精华内容
下载资源
问答
  • SVM模型超参数优化目前常用的方法是让C和g在一定的范围内取值,对于取定的c和g,把训练集作为原始数据集利用K-CV方法得到在此对c和g组合下验证集的分类准确率,最终取得训练集验证分类准确率最高的那组c和g作为最佳...

    SVM模型超参数优化目前常用的方法是让C和g在一定的范围内取值,对于取定的c和g,把训练集作为原始数据集利用K-CV方法得到在此对c和g组合下验证集的分类准确率,最终取得训练集验证分类准确率最高的那组c和g作为最佳参数。对于可能会有多组的c和g对应着最高的验证分类准备率的情况下,选取能够达到最高验证分类准确率中参数c最小的那对c和g作为最佳的参数,在取最小c的情况下,可能还会存在多组g,那么就选取搜索到的第一组c和g作为最佳参数。因为惩罚系数c值过大,会导致过于拟合的情况,模型泛化能力不好。

    这种寻优思想可以用网格参数优化来实现。惩罚参数的变化范围在[2^cmin,2^cmax],即在该范围内寻找最佳的参数c,默认值为cmin=-8,cmax=8,。RBF中的g变化范围也在[2^gmin,2^gmax],,默认值同样为为gmin=-8,gmax=8。c,g分别构成横轴和纵轴,cstep,gstep分别是进行网格参数须有时 c和g的步进太小,即c的取值为 2^cmin,2^(cmin+cstep),…,2^cmax ,同理g,默认步进取值为1,通过这种方法找到最佳的c和g组合。

    import numpy as np
    from sklearn import svm
    from sklearn.linear_model import LogisticRegression
    
    my_matrix=np.loadtxt("E:\\pima-indians-diabetes.txt",delimiter=",",skiprows=0) 
    
    lenth_x=len(my_matrix[0])
    
    data_y=my_matrix[:,lenth_x-1]
    
    data_x=my_matrix[:,0:lenth_x-1]
    print(data_x[0:2],len(data_x[0]),len(data_x))
    data_shape=data_x.shape
    data_rows=data_shape[0]
    data_cols=data_shape[1]
    
    data_col_max=data_x.max(axis=0)#获取二维数组列向最大值
    data_col_min=data_x.min(axis=0)#获取二维数组列向最小值
    for i in xrange(0, data_rows, 1):#将输入数组归一化
        for j in xrange(0, data_cols, 1):
            data_x[i][j] = \
                (data_x[i][j] - data_col_min[j]) / \
                (data_col_max[j] - data_col_min[j])
    print(data_x[0:2])
    (array([[   6.   ,  148.   ,   72.   ,   35.   ,    0.   ,   33.6  ,
               0.627,   50.   ],
           [   1.   ,   85.   ,   66.   ,   29.   ,    0.   ,   26.6  ,
               0.351,   31.   ]]), 8, 768)
    [[ 0.35294118  0.74371859  0.59016393  0.35353535  0.          0.50074516
       0.23441503  0.48333333]
     [ 0.05882353  0.42713568  0.54098361  0.29292929  0.          0.39642325
       0.11656704  0.16666667]]
    
    n_train=int(len(data_y)*0.7)#选择70%的数据作为训练集,15%的数据作为超参数选择,15%做验证
    n_select=int(len(data_y)*0.85)
    X_train=data_x[:n_train]
    y_train=data_y[:n_train]
    print(len(y_train))
    X_select=data_x[n_train:n_select]
    y_select=data_y[n_train:n_select]
    print(len(y_select))
    X_test=data_x[n_select:]
    y_test=data_y[n_select:]
    print(len(y_test))
    537
    115
    116
    
    result =[]
    for i in (-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5):
        C = 2 ** i
        for j in (-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5):
            G = 2 ** j
            clf1 = svm.SVC(kernel='rbf', gamma=G, C=C).fit(X_train,y_train)
            y_predictions1=clf1.predict(X_select)
            k=0
            for i in range(len(y_select)):
                if y_predictions1[i]==y_select[i]:
                    k+=1
            result.append([C,G,k])
    result1 = sorted(result, key=lambda x:x[2])
    
    for i in result1:
        print i
    [0.03125, 0.03125, 81]
    [0.03125, 0.0625, 81]
    [0.03125, 0.125, 81]
    [0.03125, 0.25, 81]
    [0.03125, 0.5, 81]
    [0.03125, 1, 81]
    [0.03125, 2, 81]
    [0.03125, 4, 81]
    [0.03125, 8, 81]
    [0.03125, 16, 81]
    [0.03125, 32, 81]
    [0.0625, 0.03125, 81]
    [0.0625, 0.0625, 81]
    [0.0625, 0.125, 81]
    [0.0625, 0.25, 81]
    [0.0625, 0.5, 81]
    [0.0625, 1, 81]
    [0.0625, 8, 81]
    [0.0625, 16, 81]
    [0.0625, 32, 81]
    [0.125, 0.03125, 81]
    [0.125, 0.0625, 81]
    [0.125, 0.125, 81]
    [0.125, 0.25, 81]
    [0.125, 16, 81]
    [0.125, 32, 81]
    [0.25, 0.03125, 81]
    [0.25, 0.0625, 81]
    [0.25, 0.125, 81]
    [0.25, 0.25, 81]
    [0.25, 32, 81]
    [0.5, 0.03125, 81]
    [0.5, 0.0625, 81]
    [0.5, 32, 81]
    [1, 0.03125, 81]
    [0.125, 0.5, 82]
    [0.0625, 2, 83]
    [0.5, 0.125, 83]
    [0.0625, 4, 84]
    [1, 0.0625, 84]
    [2, 0.03125, 84]
    [32, 16, 86]
    [0.125, 8, 87]
    [0.25, 16, 87]
    [8, 32, 87]
    [16, 32, 87]
    [32, 32, 87]
    [4, 32, 88]
    [8, 16, 90]
    [16, 16, 90]
    [0.125, 1, 91]
    [8, 0.125, 91]
    [2, 32, 92]
    [4, 0.25, 92]
    [16, 0.0625, 92]
    [16, 0.125, 92]
    [16, 8, 92]
    [32, 0.125, 92]
    [0.125, 4, 93]
    [0.5, 1, 93]
    [1, 0.125, 93]
    [1, 0.25, 93]
    [1, 0.5, 93]
    [1, 1, 93]
    [2, 0.0625, 93]
    [2, 0.125, 93]
    [2, 0.25, 93]
    [2, 0.5, 93]
    [4, 0.03125, 93]
    [4, 0.0625, 93]
    [4, 16, 93]
    [8, 0.25, 93]
    [16, 0.25, 93]
    [32, 0.0625, 93]
    [32, 8, 93]
    [0.25, 0.5, 94]
    [0.25, 1, 94]
    [0.25, 2, 94]
    [0.5, 0.25, 94]
    [4, 0.125, 94]
    [4, 0.5, 94]
    [8, 0.03125, 94]
    [8, 0.0625, 94]
    [16, 0.03125, 94]
    [16, 1, 94]
    [32, 0.03125, 94]
    [32, 4, 94]
    [0.125, 2, 95]
    [0.25, 4, 95]
    [0.5, 0.5, 95]
    [0.5, 2, 95]
    [1, 32, 95]
    [8, 0.5, 95]
    [8, 2, 95]
    [8, 8, 95]
    [16, 2, 95]
    [32, 0.25, 95]
    [32, 0.5, 95]
    [32, 2, 95]
    [0.25, 8, 96]
    [0.5, 4, 96]
    [0.5, 16, 96]
    [1, 2, 96]
    [2, 1, 96]
    [16, 0.5, 96]
    [16, 4, 96]
    [32, 1, 96]
    [0.5, 8, 97]
    [1, 4, 97]
    [1, 8, 97]
    [1, 16, 97]
    [2, 2, 97]
    [2, 4, 97]
    [2, 8, 97]
    [2, 16, 97]
    [4, 2, 97]
    [4, 8, 97]
    [8, 1, 97]
    [8, 4, 97]
    [4, 1, 98]
    [4, 4, 98]
    

    我们可以选择C=0.5,G=8作为模型的超参数

    clf_final= svm.SVC(kernel='rbf', gamma=8, C=0.5).fit(X_train,y_train)
    clf2=LogisticRegression()#模型2逻辑回归还是选择默认参数
    clf2.fit(X_train,y_train)
    LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False)
    
    X_test_final=data_x[n_train:]
    y_test_final=data_y[n_train:]
    y_predictions_final=clf_final.predict(X_test_final)
    y_predictions2=clf2.predict(X_test_final)
    k,h=0,0
    for i in range(len(y_test_final)):
        if y_predictions_final[i]==y_test_final[i]:
            k+=1
    for i in range(len(y_test_final)):
        if y_predictions2[i]==y_test_final[i]:
            h+=1 
    print(k,h)
    (186, 181)
    
    accuracy_svm=float(k)/float(len(y_test_final))
    accuracy_LogR=float(h)/float(len(y_test_final))
    print"The accuracy of SVM is %f, and the accuracy of LogisticRegression is %f"%(accuracy_svm,accuracy_LogR)
    The accuracy of SVM is 0.805195, and the accuracy of LogisticRegression is 0.783550
    

    通过对SVM超参数优化后,可以明显看出模型预测结果准确率超过了逻辑回归,比第一次和第二次实验只使用默认参数效果来的好。

    展开全文
  • 6.1 SVM 过拟合的原因 实际我们应用的SVM模型都是核函数+软间隔的支持向量机,那么,有以下原因导致SVM过拟合: 选择的核函数过于powerful,...6.2 如何选择SVM模型 采用不同核函数,会有不同的参数数量,那么...

    6.1 SVM 过拟合的原因

    实际我们应用的SVM模型都是核函数+软间隔的支持向量机,那么,有以下原因导致SVM过拟合:

    • 选择的核函数过于powerful,比如多项式核中的Q设置的次数过高
    • 要求的间隔过大,即在软间隔支持向量机中C的参数过大时,表示比较重视间隔,坚持要数据完全分离,当C趋于无穷大时,相当于硬间隔SVM

    6.2 如何选择SVM模型

    采用不同核函数,会有不同的参数数量,那么如何选择SVM的参数呢?

    • 最简单有效的方法就是交叉验证
    • SVM的留一验证法误差会小于支持向量所占比例
      • EloocvSVN

    因此,支持向量的数量比较多时,可能表示你的模型的留一验证误差会比较大,可以利用这里来做一个初步的检查模型。

    展开全文
  • SVM模型

    万次阅读 2015-04-27 15:00:07
    1.SVM(support vector machine)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,利用间隔最大化求最优分离超平面: 2.SVM分类器的模型为: 3.函数间隔与几何间隔的概念 (1)函数...

    (一)简介

    1.SVM(support vector machine)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,利用间隔最大化求最优分离超平面:


    2.SVM分类器的模型为(函数值只有正负1):


    3.几何间隔与函数间隔的概念

    (1)几何间隔


    PS:根据点到直线的距离公式可推导;

    (2)函数间隔

           

      

    PS:间隔大于0表示正确分类;

    4.SVM模型有3种:

    (1)线性可分支持向量机:适用于训练数据线性可分;

    (2)线性支持向量机:适用于训练数据近似线性可分,也就是存在一些特异点,将这些特异点去除后的样本线性可分;(现实中的数据经常是线性不可分的)

    (3)非线性支持向量机:适用于训练数据线性不可分,可采用相应的核技巧;

    5.SVM模型的学习都可以根据拉格朗日的对偶性转换为求解对偶问题的最优解;目前实现最多最流行的就是序列最小优化,也就是SMO( Sequential Minimal Optimization)

    (二)线性可分支持向量机

    1.原始优化问题:

    (1)根据SVM的最大间隔约束条件可以得到以下的约束问题:


    (2)根据上述的函数间隔与几何间隔的关系,约束问题可以等价于:


    (3)由于函数间隔不影响优化问题(函数间隔的大小随着w与b的同比例变化而变化),因此可以设定为1(意味着支持向量上的样本点的函数间隔为1),约束问题可以等价于:


    PS:SVM的学习策略是具有线性约束的二次型目标函数,属于凸优化问题;为优化该学习策略,可以采用已经比较成熟的相关软件,quadratic programming(QP)软件;不过在实际应用中,为了引入核技巧使SVM扩展到高维空间中,常使用拉格朗日对偶与SMO结合的方法优化模型;

    2.定义拉格朗日函数如下:


    3.KKT恒等式:


    PS:由KKT条件可以看出,若a大于0,其对应的样本点的函数间隔一定等于1;

    4.对偶问题最优解与原始问题最优解的对应关系(由KKT条件可得):

    (其中

    5.对偶优化问题如下:


    PS:由SMO优化算法求解未知参数a;

    6.支持向量:

    (1)在线性可分的情况下,训练数据集的样本点中与分离超平面距离最近的样本点的实例称为支持向量,构成间隔边界(函数间隔为1);

    (2)在决定分离超平面时只有支持向量起作用,而其他实例点并不起作用,这点从w与b的表达式可以看出;因此将这种分类模型称为支持向量机;

    (三)线性支持向量机

    1.原始优化问题:线性不可分数据集意味着有些样本点不能满足函数间隔大于等于1的约束条件,因此可以对每个样本点引入一个松弛变量:


    2.定义拉格朗日函数如下:


    其中:

    3.KKT恒等式:

    4.对偶问题最优解与原始问题最优解的对应关系(由KKT条件可得):

    5.对偶优化问题如下:


    6.支持向量

    (1)当a = 0时,样本点在函数间隔边界以外,对模型没有作用;

    (2)当0〈a〈C时,则u不等于0,因此等于0,也就是样本点在函数间隔为1的平面;

    (3)当a = C时:

    1)0〈〈1:样本点分类正确,落在间隔边界与分离超平面之间;

    2) = 1:样本点落在分离超平面上;

    3)〉1:样本点分类错误,落在间隔边界与分离超平面之间;

    (四)非线性支持向量机

    1.核函数:假设X是输入空间,H是特征空间,那么从X到H的映射函数记为:


    那么核函数的定义如下:


    2.在线性支持向量机中引入核技巧,可以用来解决非线性可分数据的分类问题,主要是在对偶问题的目标函数以及决策函数中引入核函数:

            


    PS:KKT式子中也有类似结论;

    3.常见核函数:

    (1)高斯核函数:


    (2)多项式核函数:


    (五)SMO算法

    1.优化问题:


    2.SMO算法的思想:

    (1)SMO是一种启发式算法,选择两个变量固定其他变量,针对选择的两个变量构造二次规划问题,二次规划问题可以直接得到解析解;SMO算法将原问题 不断地分解为子问题并对子问题进行求解进而达到求解原问题的目的;

    (2)之所以选择每次更新两个变量是因为目标函数中的第二个约束,若固定其他的变量,那么最后一个变量也随之确定,因此需要更新两个变量;

    3.两个变量二次规划问题的求解:

    (1)假设选择的两个变量是a1跟a2,那么有:

    可以写成:


    (2)a1跟a2的约束可以表示如下:


    (3)固定其他变量,原始优化问题可以表示如下:


    从以上式子可以看出,优化问题属于单变量的二次规划问题,很容易得到解析解,记为:


    (4)由于a2具有以上的约束,因此解析解不一定是最终的最优解,需要根据情况分析:



    4.变量的选择方法:具体的方法查看 platt 的论文,这里不做详述;

    (六)SVM优缺点

    1.优点

    (1)可用于线性/非线性分类,也可以用于回归;

    (2)低泛化误差;

    (3)容易解释;

    (4)计算复杂度较低;

    (5)处理小样本,非线性,高维数问题;

    2.缺点

    (1)对参数和核函数的选择比较敏感;

    (2)原始的SVM只比较擅长处理二分类问题;

    PS:

    《拉格朗日对偶算法》

    1.优化问题形式如下:


    其中:

    (1)f(x)函数与g(x)函数是多元连续可导函数,h(x)函数是仿射函数;

    (2)若f(x)是二次函数且g(x)是仿射函数,则为凸二次规划问题;

    (3)在上述优化问题中,常常利用拉格朗日对偶性将原始问题转化为对偶问题,通过解对偶问题而得到原始问题的解;

    2.定义拉格朗日函数如下:


    3.原始问题与对偶问题

    (1)原始问题及其最优解表示如下:


    (2)对偶问题及其最优解表示如下:


    (3)原始问题与对偶问题最优解的比较:


    (4)若f(x)与g(x)为凸函数且h(x)为仿射函数:


    4.KKT条件:


    PS:KKT条件与最优解互为充要条件;

    展开全文
  • 学习SVM(一) SVM模型训练与分类的OpenCV实现

    万次阅读 多人点赞 2017-03-29 21:47:52
    学习SVM(一) SVM模型训练与分类的OpenCV实现 学习SVM(二) 如何理解支持向量机的最大分类间隔 学习SVM(三)理解SVM中的对偶问题 学习SVM(四) 理解SVM中的支持向量(Support Vector)Andrew Ng 在斯坦福大学...

    简介

    学习SVM(一) SVM模型训练与分类的OpenCV实现
    学习SVM(二) 如何理解支持向量机的最大分类间隔
    学习SVM(三)理解SVM中的对偶问题
    学习SVM(四) 理解SVM中的支持向量(Support Vector)
    学习SVM(五)理解线性SVM的松弛因子

    Andrew Ng 在斯坦福大学的机器学习公开课上这样评价支持向量机:
    support vector machines is the supervised learning algorithm that many people consider the most effective off-the-shelf supervised learning algorithm.That point of view is debatable,but there are many people that hold that point of view.

    可见,在监督学习算法中支持向量机有着非常广泛的应用,而且在解决图像分类问题时有着优异的效果。

    OpenCV集成了这种学习算法,它被包含在ml模块下的CvSVM类中,下面我们用OpenCV实现SVM的数据准备模型训练加载模型实现分类,为了理解起来更加直观,我们用三个工程来实现。

    数据准备

    在OpenCV的安装路径下,搜索digits,可以得到一张图片,图片大小为1000*2000,有0-9的10个数字,每5行为一个数字,总共50行,共有5000个手写数字,每个数字块大小为20*20。 下面将把这些数字中的0和1作为二分类的准备数据。其中0有500张,1有500张。
    用下面的代码将图片准备好,在写入路径提前建立好文件夹:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        char ad[128]={0};
        int  filename = 0,filenum=0; 
        Mat img = imread("digits.png");
        Mat gray;
        cvtColor(img, gray, CV_BGR2GRAY);
        int b = 20;
        int m = gray.rows / b;   //原图为1000*2000
        int n = gray.cols / b;   //裁剪为5000个20*20的小图块
    
        for (int i = 0; i < m; i++)
        {
            int offsetRow = i*b;  //行上的偏移量
            if(i%5==0&&i!=0)
            {
                filename++;
                filenum=0;
            }
            for (int j = 0; j < n; j++)
            {
                int offsetCol = j*b; //列上的偏移量
                sprintf_s(ad, "D:\\data\\%d\\%d.jpg",filename,filenum++);
                //截取20*20的小块
                Mat tmp;
                gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
                imwrite(ad,tmp);
            }
        }
        return 0;
    }

    最后可以得到这样的结果:
    这里写图片描述
    组织的二分类数据形式为:

    --D  --data
        --train_image
          --0400张)
          --1400张)
        --test_image
          --0100张)
          --1100张)

    这里写图片描述
    训练数据800张,0,1各400张;测试数据200张,0,1各100张

    模型训练

    数据准备完成之后,就可以用下面的代码训练了:

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    
    void getFiles( string path, vector<string>& files);
    void get_1(Mat& trainingImages, vector<int>& trainingLabels);
    void get_0(Mat& trainingImages, vector<int>& trainingLabels);
    
    int main()
    {
        //获取训练数据
        Mat classes;
        Mat trainingData;
        Mat trainingImages;
        vector<int> trainingLabels;
        get_1(trainingImages, trainingLabels);
        get_0(trainingImages, trainingLabels);
        Mat(trainingImages).copyTo(trainingData);
        trainingData.convertTo(trainingData, CV_32FC1);
        Mat(trainingLabels).copyTo(classes);
        //配置SVM训练器参数
        CvSVMParams SVM_params;
        SVM_params.svm_type = CvSVM::C_SVC;
        SVM_params.kernel_type = CvSVM::LINEAR; 
        SVM_params.degree = 0;
        SVM_params.gamma = 1;
        SVM_params.coef0 = 0;
        SVM_params.C = 1;
        SVM_params.nu = 0;
        SVM_params.p = 0;
        SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01);
        //训练
        CvSVM svm;
        svm.train(trainingData, classes, Mat(), Mat(), SVM_params);
        //保存模型
        svm.save("svm.xml");
        cout<<"训练好了!!!"<<endl;
        getchar();
        return 0;
    }
    void getFiles( string path, vector<string>& files )  
    {  
        long   hFile   =   0;  
        struct _finddata_t fileinfo;  
        string p;  
        if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
        {  
            do  
            {  
                if((fileinfo.attrib &  _A_SUBDIR))  
                {  
                    if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
                        getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
                }  
                else  
                {  
                    files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
                }  
            }while(_findnext(hFile, &fileinfo)  == 0);  
    
            _findclose(hFile);  
        }  
    } 
    void get_1(Mat& trainingImages, vector<int>& trainingLabels)
    {
        char * filePath = "D:\\data\\train_image\\1"; 
        vector<string> files;  
        getFiles(filePath, files );  
        int number = files.size();  
        for (int i = 0;i < number;i++)  
        {  
            Mat  SrcImage=imread(files[i].c_str());
            SrcImage= SrcImage.reshape(1, 1);
            trainingImages.push_back(SrcImage);
            trainingLabels.push_back(1);
        }  
    }
    void get_0(Mat& trainingImages, vector<int>& trainingLabels)
    {
        char * filePath = "D:\\data\\train_image\\0"; 
        vector<string> files;  
        getFiles(filePath, files );  
        int number = files.size();  
        for (int i = 0;i < number;i++)  
        {  
            Mat  SrcImage=imread(files[i].c_str());
            SrcImage= SrcImage.reshape(1, 1);
            trainingImages.push_back(SrcImage);
            trainingLabels.push_back(0);
        }  
    }

    整个训练过程可以分为一下几个部分:
    数据准备:
    该例程中一个定义了三个子程序用来实现数据准备工作:
    getFiles()用来遍历文件夹下所有文件,可以参考:
    http://blog.csdn.net/chaipp0607/article/details/53914954
    getBubble()用来获取有气泡的图片和与其对应的Labels,该例程将Labels定为1。
    getNoBubble()用来获取没有气泡的图片与其对应的Labels,该例程将Labels定为0。
    getBubble()与getNoBubble()将获取一张图片后会将图片(特征)写入到容器中,紧接着会将标签写入另一个容器中,这样就保证了特征和标签是一一对应的关系push_back(0)或者push_back(1)其实就是我们贴标签的过程。

    trainingImages.push_back(SrcImage);
    trainingLabels.push_back(0);

    在主函数中,将getBubble()与getNoBubble()写好的包含特征的矩阵拷贝给trainingData,将包含标签的vector容器进行类型转换后拷贝到trainingLabels里,至此,数据准备工作完成,trainingData与trainingLabels就是我们要训练的数据。

        Mat classes;
        Mat trainingData;
        Mat trainingImages;
        vector<int> trainingLabels;
        getBubble(trainingImages, trainingLabels);
        getNoBubble(trainingImages, trainingLabels);
        Mat(trainingImages).copyTo(trainingData);
        trainingData.convertTo(trainingData, CV_32FC1);
        Mat(trainingLabels).copyTo(classes);

    特征选取
    其实特征提取和数据的准备是同步完成的,我们最后要训练的也是正负样本的特征。本例程中同样在getBubble()与getNoBubble()函数中完成特征提取工作,只是我们简单粗暴将整个图的所有像素作为了特征,因为我们关注更多的是整个的训练过程,所以选择了最简单的方式完成特征提取工作,除此中外,特征提取的方式有很多,比如LBP,HOG等等。

      SrcImage= SrcImage.reshape(1, 1);

    我们利用reshape()函数完成特征提取,原型如下:

     Mat reshape(int cn, int rows=0) const;

    可以看到该函数的参数非常简单,cn为新的通道数,如果cn = 0,表示通道数不会改变。参数rows为新的行数,如果rows = 0,表示行数不会改变。我们将参数定义为reshape(1, 1)的结果就是原图像对应的矩阵将被拉伸成一个一行的向量,作为特征向量。
    参数配置
    参数配置是SVM的核心部分,在Opencv中它被定义成一个结构体类型,如下:

    struct CV_EXPORTS_W_MAP CvSVMParams
    {
        CvSVMParams();
        CvSVMParams(  
        int svm_type, 
        int kernel_type,
        double degree, 
        double coef0,
        double Cvalue, 
        double p,
        CvMat* class_weights, 
        CvTermCriteria term_crit );
        CV_PROP_RW int         svm_type;
        CV_PROP_RW int         kernel_type;
        CV_PROP_RW double      degree; // for poly
        CV_PROP_RW double      gamma;  // for poly/rbf/sigmoid
        CV_PROP_RW double      coef0;  // for poly/sigmoid
        CV_PROP_RW double      C;  // for CV_SVM_C_SVC,       CV_SVM_EPS_SVR and CV_SVM_NU_SVR
        CV_PROP_RW double      nu; // for CV_SVM_NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVR
        CV_PROP_RW double      p; // for CV_SVM_EPS_SVR
        CvMat*      class_weights; // for CV_SVM_C_SVC
        CV_PROP_RW CvTermCriteria term_crit; // termination criteria
    };

    所以在例程中我们定义了一个结构体变量用来配置这些参数,而这个变量也就是CVSVM类中train函数的第五个参数,下面对参数进行说明。
    SVM_params.svm_type :SVM的类型:
    C_SVC表示SVM分类器,C_SVR表示SVM回归
    SVM_params.kernel_type:核函数类型
    线性核LINEAR:
    d(x,y)=(x,y)
    多项式核POLY:
    d(x,y)=(gamma*(x’y)+coef0)degree
    径向基核RBF:
    d(x,y)=exp(-gamma*|x-y|^2)
    sigmoid核SIGMOID:
    d(x,y)= tanh(gamma*(x’y)+ coef0)

    SVM_params.degree:核函数中的参数degree,针对多项式核函数;
    SVM_params.gama:核函数中的参数gamma,针对多项式/RBF/SIGMOID核函数;
    SVM_params.coef0:核函数中的参数,针对多项式/SIGMOID核函数;
    SVM_params.c:SVM最优问题参数,设置C-SVCEPS_SVRNU_SVR的参数;
    SVM_params.nu:SVM最优问题参数,设置NU_SVCONE_CLASSNU_SVR的参数;
    SVM_params.p:SVM最优问题参数,设置EPS_SVR 中损失函数p的值.
    训练模型

    CvSVM svm;
    svm.train(trainingData, classes, Mat(), Mat(), SVM_params);

    通过上面的过程,我们准备好了待训练的数据和训练需要的参数,其实可以理解为这个准备工作就是在为svm.train()函数准备实参的过程。来看一下svm.train()函数,Opencv将SVM封装成CvSVM库,这个库是基于台湾大学林智仁(Lin Chih-Jen)教授等人开发的LIBSVM封装的,由于篇幅限制,不再全部粘贴库的定义,所以一下代码只是CvSVM库中的一部分数据和函数:

    class CV_EXPORTS_W CvSVM : public CvStatModel
    {
    public:
    virtual bool train( 
      const CvMat* trainData, 
      const CvMat* responses,
      const CvMat* varIdx=0, 
      const CvMat* sampleIdx=0,
      CvSVMParams params=CvSVMParams() );
    virtual float predict( 
      const CvMat* sample, 
      bool returnDFVal=false ) const;

    我们就是应用类中定义的train函数完成模型训练工作。
    保存模型

    svm.save("svm.xml");

    保存模型只有一行代码,利用save()函数,我们看下它的定义:

        CV_WRAP virtual void save( const char* filename, const char* name=0 ) const;

    该函数被定义在CvStatModel类中,CvStatModel是ML库中的统计模型基类,其他 ML 类都是从这个类中继承。

    总结:到这里我们就完成了模型训练工作,可以看到真正用于训练的代码其实很少,OpenCV最支持向量机的封装极大地降低了我们的编程工作。

    加载模型实现分类

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    
    void getFiles( string path, vector<string>& files );
    
    int main()
    {
        int result = 0;
        char * filePath = "D:\\data\\test_image\\0"; 
        vector<string> files;  
        getFiles(filePath, files );  
        int number = files.size();  
        cout<<number<<endl;
        CvSVM svm;
        svm.clear();
        string modelpath = "svm.xml";
        FileStorage svm_fs(modelpath,FileStorage::READ);
        if(svm_fs.isOpened())
        {
            svm.load(modelpath.c_str());
        }
        for (int i = 0;i < number;i++)  
        {  
            Mat inMat = imread(files[i].c_str());
            Mat p = inMat.reshape(1, 1);
            p.convertTo(p, CV_32FC1);
            int response = (int)svm.predict(p);
            if (response == 0)
            {
                result++;
            }
        }
        cout<<result<<endl;
        getchar();
        return  0;
    }
    void getFiles( string path, vector<string>& files )  
    {  
        long   hFile   =   0;  
        struct _finddata_t fileinfo;  
        string p;  
        if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
        {  
            do  
            {  
                if((fileinfo.attrib &  _A_SUBDIR))  
                {  
                    if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
                        getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
                }  
                else  
                {       files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
                }  
            }while(_findnext(hFile, &fileinfo)  == 0);  
            _findclose(hFile);  
        }  
    } 

    在上面我们把该介绍的都说的差不多了,这个例程中只是用到了load()函数用于模型加载,加载的就是上面例子中生成的模型,load()被定义在CvStatModel这个基类中:

        svm.load(modelpath.c_str());

    load的路径是string modelpath = "svm.xml",这意味着svm.mxl文件应该在测试工程的根目录下面,但是因为训练和预测是两个独立的工程,所以必须要拷贝一下这个文件。最后用到predict()函数用来预测分类结果,predict()被定义在CVSVM类中。

    注意:

    1.为什么要建立三个独立的工程呢?
    主要是考虑写在一起话,代码量会比较大,逻辑没有分开清晰,当跑通上面的代码之后,就可以随意的改了。
    2.为什么加上数据准备?
    之前有评论说道数据的问题,提供数据后实验能更顺利一些,因为本身代码没有什么含金量,这样可以更顺利的运行起来工程,并修改它。
    3.一些容易引起异常的情况:
    (1):注意生成的.xml记得拷贝到预测工程下;
    (2):注意准备好数据路径和代码是不是一致;
    (3):注意训练的特征要和测试的特征一致;

    展开全文
  • SVM学习笔记(四)——SVM模型实例程序分类效果总结SVM模型优点SVM模型缺点 下面将用一个简单的例子来看看带核函数的SVM模型的非线性分类效果。 程序 生成数据集 #生成数据集 from sklearn.datasets import make_...
  • from sklearn import svm from sklearn.linear_model import LogisticRegression my_matrix=np.loadtxt("E:\\pima-indians-diabetes.txt",delimiter=",",skiprows=0) lenth_x=len(my_matrix...
  • SVM模型结构

    千次阅读 2019-10-10 10:31:23
    通俗来讲,SVM是一种二类分类模型,其基本模型定义为:特征空间上的间隔最大的线性分类器,其学习策略是间隔最大化,最终可转化为一个凸二次规划问题的求解。 二、模型的构建和结构 2.1 模型构建 1)KEY IDEA1:...
  • svm模型初步理解

    千次阅读 2020-10-12 19:35:06
    什么是SVM模型 支持向量机,因其英文名为support vector machine,故一般简称SVM,通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一...
  • SVM学习(一)SVM模型训练与分类

    万次阅读 多人点赞 2019-03-08 17:27:04
    SVM模型训练与分类 支持向量机(SVM): 一个能够将不同类样本在样本空间分隔的超平面。换句话说,给定一些标记好的训练本(监督式学习),SVM算法输出一个最优化的超分隔平面。本次利用VS2015+OpenCV3.4.1实现SVM...
  • from sklearn import svm from sklearn.linear_model import LogisticRegression my_matrix=np.loadtxt("D:/data/pima-indians-diabetes.txt",delimiter=",",skiprows=0) ...
  • 在matlab中进行SVM模型训练,通常有两种选择: 注意: a、如果matlab安装了LibSVM,在使用matlab自带的SVM时,需要进行搜索路径重新设定  路径重新设定方法:在matlab软件主窗口中【主页】--【设置路径】移除...
  • sklearn中的SVM模型

    2020-01-15 17:18:10
    支持向量机(SVM)是一种强大的可用于监督式学习分类问题和回归问题,以及非监督式异常检测问题等的常见... 基于liblinear库的SVM分类模型,仅支持线性核,可调节损失函数和惩罚项。多分类问题采用'ovr'策略。不支...
  • #https://github.com/Deepcong2019/java-tensorflow-svm 四种方案(目前实现前两种,基于jpmml调用svm.pmml时...java调用tensorflow pb模型 + java 基于jpmml包 调用在python上训练的SVM.pmml模型 java调用tensorf...
  • 学习SVM(一) SVM模型训练与分类的OpenCV实现 学习SVM(二) 如何理解支持向量机的最大分类间隔 学习SVM(三)理解SVM中的对偶问题 学习SVM(四) 理解SVM中的支持向量(Support Vector) 学习SVM(五)理解...
  • Spark实现SVM模型

    千次阅读 2017-03-06 21:22:42
    关于SVM算法SVM,即Support Vector Machine(支持向量机),是一种使用线性分割平面的二元分类算法。其原理是通过寻求结构化风险最小来提高学习机泛化能力,实现经验风险和置信范围的最小化,从而达到在统计样本量较...
  • 保存SVM模型并调用

    千次阅读 2019-06-15 18:42:21
    将训练好的模型保存为pickle文件,有以下步骤: 1)以二进制的方式打开文件: file = open("G:/Download_Data_bishe/save_model/model.pickle", "wb") 2)然后将模型写入文件:pickle.dump(classifier, file) 3...
  • SVM 模型训练到social LSTM

    千次阅读 2019-05-09 15:25:45
    之前看过台大李宏毅的SVM介绍,我寻思我没看到...但是有关于SVM模型介绍是有点少的。 最近看到一篇paper The relation probabilities are determined by a probabilistic SVM trained on 3D motion indicator f...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 74,925
精华内容 29,970
关键字:

怎么选择svm模型