SVM-SMO算法C++实现

本文详细介绍了如何使用C++实现支持向量机(SVM)的SMO(Sequential Minimal Optimization)算法,包括数据加载和矩阵操作的关键步骤,为理解SVM优化过程提供了实践指导。
摘要由CSDN通过智能技术生成

SMO程序

#include <iostream>
#include <stdlib.h>
#include <string>
#include <math.h>
#include "matrix.h"
#include <fstream>
#include <sstream>
#include <stack>
using namespace std;
#define MAX_SIZE_OF_TRAINING_SET 100
#define MAX_NUMIT 100
#define MAX 1000000
#define MIN -100000
//SMO参数结构体
struct OS
{
    Matrix x;
    Matrix y;
    double C;
    double soft;
    int m;
    Matrix alphas;
    double b;
    Matrix eCache;
    Matrix kernel;
    bool k;
};
//核函数的结构体
struct kTup
{
    int type;//0,1
    double arg;
};
class SMOP
{
    //非常值得注意的是svm中训练样本按列排列,即每一列是一个样本,所以导致w是行向量
public:
    OS os;
public:
    /**
    根据参数,来生成不同的核函数
    */
    Matrix kernelTran(Matrix x,Matrix xOneCol,kTup ktup)
    {
        Matrix K;
        K.initMatrix(&K,x.col,1);
        Matrix xOneColT;
        xOneColT.initMatrix(&xOneColT,xOneCol.row,xOneCol.col);
        xOneColT.transposematrix(xOneCol,&xOneColT);
        if(ktup.type==1)
        {
            K.multsmatrix(&K,x,xOneColT);
        }
        if(ktup.type==2)
        {
            //高斯核
        }
        return K;
    }
    /**
    结构体OS的初始化,用于保存所以SMO算法中需要用到的参数
    */
    int initOs(Matrix x,Matrix y,double C,double soft,kTup ktup)
    {
        os.x.initMatrix(&os.x,x.col,x.row);
        os.x.copy(x,&os.x);
        os.y.initMatrix(&os.y,y.col,y.row);
        os.y.copy(y,&os.y);
        os.eCache.initMatrix(&os.eCache,x.col,2);
        os.alphas.initMatrix(&os.alphas,x.col,1);

        os.b=0;
        os.C=C;
        os.m=x.col;
        os.kernel.initMatrix(&os.kernel,os.m,os.m);
        os.soft=soft;
        if(ktup.type!=0)
        {
            int i=0,j=0;
            Matrix xOneCol;
            xOneCol.initMatrix(&xOneCol,1,os.x.row);
            Matrix kOneRow;
            kOneRow.initMatrix(&kOneRow,os.m,1);
            cout<<"-----------"<<endl;
            for(i=0; i<os.m; i++)
            {
                xOneCol=xOneCol.getOneCol(x,i);
                kOneRow=kernelTran(x,xOneCol,ktup);
                for(j=0; j<os.m; j++)
                    os.kernel.mat[j][i]=kOneRow.mat[j][0];
            }
            os.k=true;
            return 0;
        }
        os.k=false;
        return 0;
    }
    /**
    上下限剪辑函数
    */
    double clipAlpha(double alpha,double L,double H)
    {
        if(alpha>H)
            return H;
        if(alpha<L)
            return L;
        return alpha;
    }
    /**
    误差值的计算也是根据数学表达式来实现的

    **/
    double calcEk(int k)
    {
        Matrix ay;
        ay.initMatrix(&ay,os.x.col,1);
        int i;
        for(i=0; i<os.m; i++)
        {
            ay.mat[i][0]=os.alphas.mat[i][0]*os.y.mat[i][0];
        }
        Matrix ayT;
        ayT.initMatrix(&ayT,ay.row,ay.col);
        ayT.transposematrix(ay,&ayT);
        Matrix f;
        f.initMatrix(&f,1,1);
        if(!os.k)
        {
            Matrix ayTx;
            ayTx.initMatrix(&ayTx,ayT.col,os.x.row);
            ayTx.multsmatrix(&ayTx,ayT,os.x);

            Matrix xOneCol;
            xOneCol.initMatrix(&xOneCol,1,os.x.row);
            xOneCol=xOneCol.getOneCol(os.x,k);

            Matrix xOneColT;
            xOneColT.initMatrix(&xOneColT,xOneCol.row,xOneCol.col);
            xOneColT.transposematrix(xOneCol,&xOneColT);
            f.multsmatrix(&f,ayTx,xOneColT);//值得商榷
        }
        else
        {
            Matrix kOneRow;
            kOneRow.initMatrix(&kOneRow,os.m,1);
            kOneRow=kOneRow.getOneRow(os.kernel,k);
            f.multsmatrix(&f,ayT,kOneRow);//值得商榷
        }
        double fXK=f.mat[0][0]+os.b-os.y.mat[k][0];
        return fXK;
    }
    ///更新误差矩阵
    void updataEk(int k)
    {
        double Ek;
        Ek=calcEk(k);//计算误差值
        os.eCache.mat[k][0]=1;
        os.eCache.mat[k][1]=Ek;
    }
    /**
    对于第二个alpha的选择采用Ei-Ej的大小进行衡量,同时这里引用一个矩阵来保存不变的E,减少计算量
    选择出合适第二个alpha2,对于第一次进来,保存误差值E的矩阵必然没有一个有效的,所以采用随机策略
    随机选择策略其实可以任意选择,具体没有实现,而是采用等价方式实现,但需要注意数据越界问题
    **/
    int selectJ(int i,double Ei)
    {
        int maxK=-1;
        double Ek;
        double Ej;
        double deltaE;
        double maxDeltaE=0;
        int k;
        for(k=0
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值