SVM是基于统计学习理论的一中学习方法,在统计学习理论的VC维和结构风险最小化原理的基础上, 根据有限的样本信息在模型的复杂性和学习能力之间寻求最佳折中,在样本空间或特征空间构造最优超平面将两类样本分开,以获得最好的推广能力。对于线性可分二分类问题,由支持向量构造的具有最大间隔的分类超平面将样本分开。对于线性不可分问题则通过选择适当的核函数将样本空间映射到高维特征空间,进而在特征空间中构造最优分类超平面,将传统的通过增加神经元来提高网络性能的方法转化为通过降低样本复杂度的方法来加以解决。目前主要用于数据挖掘、手写字识别、疾病诊断、图像分类、生物信息学等领域。并得到了成功的应用。
但是SVM主要研究的是小样本下机器学习的规律,无论是线性可分还是线性不可分,都需要求解复杂的二次规划问题,这相当困难。除此之外,SVM本质上用于解决二分类问题,经常用于类别数为2的样本分类,多类别的分类问题,需要构造SVM决策树,采取多次分类的方式进行,运算量大,效率低。
而同作为构造性学习方法的覆盖算法,可处理海量样本,能根据样本自身的特点,针对学习样本的特征用超平面切割球面形成“球形领域”作为神经元来构造网络,分类能力强,运算速度快,适宜于多类别的分类问题,且可读性较强,参数确定相对来说也比较容易。(出自某书中原话, 下面给出NCA 部分C++ code)
void sample_train()
{
clock_t t1, t2;
t1=clock();
sortSample();
int seq=0;
int coved_num=0;
srand((unsigned)time(NULL));
for (size_t t=0; t<I.size(); ++t)
{
vector<int> v;
for (size_t i=0; i<I[t]->v.size(); ++i)
{
v.push_back(i);
}
int uncovedn=I[t]->v.size();
while (!v.empty())
{
random_shuffle(v.begin(), v.end());
int s=v[0];
if (I[t]->v[s]->covered==1)
{
v.erase(v.begin()); //???
continue;
}
double d1=find_diffMin_d(s, t);
double d2=find_SameMax_d(s,t,d1);
double d=(d1+d2)/2;
coved_num=cover_sample(s,t,d);
Cover *c=new Cover;
int k=I[t]->v[s]->id;
int dim=samples[k]->dim;
c->seq=seq;
c->center=new double[dim];
for (int ii=0; ii<dim; ++ii)
{
c->center[ii] = samples[k]->x[ii];
}
c->cls=samples[I[t]->v[0]->id]->y;
c->r=d;
C.push_back(c);
uncovedn -= coved_num;
//
seq++;
v.erase(v.begin());
}
}
t2=clock();
vector<ExpResult *>::reverse_iterator it = Result.rbegin();
(*it)->covNum=C.size();
(*it)->trNum = samples.size();
(*it)->trTime = (double)(t2-t1)/CLOCKS_PER_SEC;
}
void sample_test()
{
int correct=0;
int refuse=0;
int uc=0;
clock_t t1, t2;
t1=clock();
for (size_t i = 0; i < samples.size(); i++)
{
double cnt_nearest = -DBL_MAX;
int k = -1;
size_t j=0;
while (j<C.size())
{
double d=inner_product(*samples[i], C[j]->center);
double r=C[j]->r;
if (cnt_nearest<(d-r))
{
cnt_nearest = d-r;
k=j;
}
++j;
}//while
if (cnt_nearest < 0)
{
++refuse;
if (samples[i]->y==C[k]->cls)
{
++uc;
}
}
else
{
if (samples[i]->y == C[k]->cls)
{
++correct;
}
}
}//for
t2 = clock();
//save exp data
vector<ExpResult *>::reverse_iterator it=Result.rbegin();
(*it)->correct=correct;
(*it)->refuse=refuse;
(*it)->guess_corr=uc;
(*it)->teNum=samples.size();
(*it)->teTime=(double)(t2-t1)/CLOCKS_PER_SEC;
(*it)->corr_rate=((float)(correct+uc))/samples.size();
}