加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SVM训练及预测过程

(2012-07-18 20:57:22)
标签:

svm

训练

预测

过程

方法

分类: 2012.7
    网上有很多关于LibSVM的教程,LibSVM提供了多平台下的可执行文件,在win平台下可以直接通过命令行执行,可以利用提供的可执行文件方便的进行离线的训练和预测,这里不再赘述。这篇文章要做的是把SVM的训练及预测的过程移植到程序当中的方法进行简单阐述,而不是使用提供的可执行文件。
    过程首先要建立工程,这里以VC6.0为例,建立好工程后,需要将LibSVM中的svm.h和svm.cpp文件加入到工程当中,文件中包含我们要用到的svm_train,svm_pridect等函数,建立好这些以后需要做的就是填写SVM为我们准备好的模板。训练的数据以文本识别为依据,将字符定位和切割(字符的定位和切分是需要好好研究的)并且二值化后,就得到如下图的二值化图像,-----http://s5/bmiddle/65caa9784c5171f05fbe4&690
    我们就可以对二值化图像提取想要的特征,文本识别较为简单,提取简单的特征就可以实现比较好的识别效果,如可以将图片归一化为统一大小后平均分成八部分,计算每一份的黑色像素点数作为特征等,这里选取了125维的向量作为每一幅图像的特征。
    做好这些准备工作后,就可以开始SVM模型的训练了,就像做菜,原料准备好了,接下来就是煎炒焖炖了,训练可以分为三步:
    1、将提取的特征存入一个文本文件当中,方便以后的使用,这里不用特殊的格式,每一幅图像一个特征向量的存好就行了。
    2、将提取的特征格式化,SVM训练提取数据的时候需要按照特殊的格式,也就是SVM给我们规定的模板。SVM包含几个重要的元素:
    struct svm_problem
    {
        int l;//记录样本的总数
        double *y;//指向样本所属类别的数组
        struct svm_node **x;//指向一个存储内容为指针的数组
    };
    简单的说,svm_problem用来存储本次参加运算的所有样本(数据集)以及所属类别,成员变量l存储样本总数,y存储样本的分类,x存储的是样本的特征值。
    struct svm_node
    {
        int index;
        double value;
    };
    svm_node是用来存储单幅图像的特征数据的,打个比方说,svm_problem是一群羊,那么svm_node就是这一群羊中的一只了。需要注意的是,svm_node的存储空间应该比特征数大一位,最后一位index值必须以-1结束。
我们需要做的就是为l,x,y以及svm_node赋值,使其满足SVM的格式,具体程序如下:
 
    svm_problem prob;
    svm_node *node;

    prob.l = feature_count;//样本个数
    prob.y = new double[prob.l];//分配空间

    node = new svm_node[(PROBLEM_DIMENSION+1) * prob.l];  //样本特征存储空间,注意是连续的空间
    prob.x = new svm_node *[prob.l];             //分配空间
 
    for(int i = 0; i < prob.l; i++)
    {
        for(int j = 0; j < PROBLEM_DIMENSION; j++)
        {
            node[(PROBLEM_DIMENSION + 1) * i + j].index = j + 1;
            node[(PROBLEM_DIMENSION + 1) * i + j].value = rFeature->FeatureData[j];
        }
        node[(PROBLEM_DIMENSION + 1) * i + PROBLEM_DIMENSION].index = -1;
        prob.x[i] = &node[(PROBLEM_DIMENSION + 1) * i]; //相当与移动指针(PROBLEM_DIMENSION + 1)
                                                 //* i这一位,把这一位的地址传给prob.x[i]
        prob.y[i] = rFeature->FeatureType;//类别

        rFeature++;
    }
    其中rFeature为自定义的FEATURE类型
    typedef struct
    {
        char FeatureType;//类型
        double FeatureData[PROBLEM_DIMESION];//特征数据PROBLEM_DIMESION定义为125
    }FEATURE;

    3、格式组装好后,就需要设定SVM的训练参数,以及训练了
    svm有如下类型
    C_SVC,NU_SVC,ONE_CLASS,EPSILON_SVR,NU_SVR
    核函数有如下类型
    LINEAR,POLY,RBF,SIGMOID
    参数格式规定如下:
    struct svm_parameter
    {
        int svm_type;//SVM的类型
        int kernel_type;核函数
        double degree;//多项式参数
        double gamma;//核函数为poly/rbf/sigmoid的参数
        double coef0;//核函数为poly/sigmoid的参数

        //下面是训练所需的参数
        double cache_size;//训练所需的内存MB为单位
        double eps;//训练停止的标准
        double C;//惩罚因子,越大训练时间越长
        int nr_weight;//权重的数目,目前只有两个值,默认为0
        int *weight_label;//权重,元素个数由nr_weight决定
        double* weight;//C_SVC权重
        double nu;
        double p;
        int shrinking;//训练过程是否使用压缩
        int probability;//是否做概率估计
    };

    具体的代码实例如下:
    svm_parameter para;
    para.svm_type = C_SVC;
    para.kernel_type = RBF;
    para.degree = 3;
    para.gamma = 0.0001;
    para.coef0 = 0;
    para.nu = 0.5;
    para.cache_size = 100;
    para.C = 10;
    para.eps = 1e-5;
    para.p = 0.1;
    para.shrinking = 1;
    para.probability = 0;
    para.nr_weight = 0;
    para.weight_label = NULL;
    para.weight = NULL;

参数都设置好后就是训练了,直接调用svm.cpp中的函数:
    svm_model *model;
    model = svm_train(&prob, &para);//训练
    svm_save_model(model_name,model);//保存模型
具体的函数说明都可以查得到,model的结构规定也可以见svm中,不在赘述。


接下来是利用训练好的model进行预测的过程,过程非常简单,分为两步:
1、装载模型
    svm_model* model;
    model = svm_load_model(modelPath);
2、预测
    double p = svm_predict(model,node);
    node中保存的是要进行分类的图像的特征值。

这样,整个训练以及预测的过程就结束了。


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有