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