Commit 7cab6798 authored by Markus Schoeler's avatar Markus Schoeler

Added two kernels to existing SVM framework

Histogram intersection kernel (accessible by using SVM::INTER in CV namespace as kernel_type)
Exponetial chi2 kernel (accessible by using SVM::CHI2 in CV namespace as kernel_type)

Formulars:
Exp-CHI2
k(x,y) = exp(-gamma * CHI2(x,y))
CHI2(x,y) = 1- 2* SUM_i[(xi-yi)²/(xi+yi)]

Intersec
k(x,y) = SUM_i[min(xi,yi)]
parent 956aa68f
...@@ -297,7 +297,7 @@ struct CV_EXPORTS_W_MAP CvSVMParams ...@@ -297,7 +297,7 @@ struct CV_EXPORTS_W_MAP CvSVMParams
CV_PROP_RW int svm_type; CV_PROP_RW int svm_type;
CV_PROP_RW int kernel_type; CV_PROP_RW int kernel_type;
CV_PROP_RW double degree; // for poly CV_PROP_RW double degree; // for poly
CV_PROP_RW double gamma; // for poly/rbf/sigmoid CV_PROP_RW double gamma; // for poly/rbf/sigmoid/chi2
CV_PROP_RW double coef0; // for poly/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 C; // for CV_SVM_C_SVC, CV_SVM_EPS_SVR and CV_SVM_NU_SVR
...@@ -326,7 +326,10 @@ struct CV_EXPORTS CvSVMKernel ...@@ -326,7 +326,10 @@ struct CV_EXPORTS CvSVMKernel
virtual void calc_non_rbf_base( int vec_count, int vec_size, const float** vecs, virtual void calc_non_rbf_base( int vec_count, int vec_size, const float** vecs,
const float* another, float* results, const float* another, float* results,
double alpha, double beta ); double alpha, double beta );
virtual void calc_intersec( int vcount, int var_count, const float** vecs,
const float* another, float* results );
virtual void calc_chi2( int vec_count, int vec_size, const float** vecs,
const float* another, float* results );
virtual void calc_linear( int vec_count, int vec_size, const float** vecs, virtual void calc_linear( int vec_count, int vec_size, const float** vecs,
const float* another, float* results ); const float* another, float* results );
virtual void calc_rbf( int vec_count, int vec_size, const float** vecs, virtual void calc_rbf( int vec_count, int vec_size, const float** vecs,
...@@ -456,7 +459,7 @@ public: ...@@ -456,7 +459,7 @@ public:
enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 }; enum { C_SVC=100, NU_SVC=101, ONE_CLASS=102, EPS_SVR=103, NU_SVR=104 };
// SVM kernel type // SVM kernel type
enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3 }; enum { LINEAR=0, POLY=1, RBF=2, SIGMOID=3, CHI2=4, INTER=5 };
// SVM params type // SVM params type
enum { C=0, GAMMA=1, P=2, NU=3, COEF=4, DEGREE=5 }; enum { C=0, GAMMA=1, P=2, NU=3, COEF=4, DEGREE=5 };
......
...@@ -220,6 +220,8 @@ bool CvSVMKernel::create( const CvSVMParams* _params, Calc _calc_func ) ...@@ -220,6 +220,8 @@ bool CvSVMKernel::create( const CvSVMParams* _params, Calc _calc_func )
calc_func = params->kernel_type == CvSVM::RBF ? &CvSVMKernel::calc_rbf : calc_func = params->kernel_type == CvSVM::RBF ? &CvSVMKernel::calc_rbf :
params->kernel_type == CvSVM::POLY ? &CvSVMKernel::calc_poly : params->kernel_type == CvSVM::POLY ? &CvSVMKernel::calc_poly :
params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel::calc_sigmoid : params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel::calc_sigmoid :
params->kernel_type == CvSVM::CHI2 ? &CvSVMKernel::calc_chi2 :
params->kernel_type == CvSVM::INTER ? &CvSVMKernel::calc_intersec :
&CvSVMKernel::calc_linear; &CvSVMKernel::calc_linear;
return true; return true;
...@@ -318,6 +320,52 @@ void CvSVMKernel::calc_rbf( int vcount, int var_count, const float** vecs, ...@@ -318,6 +320,52 @@ void CvSVMKernel::calc_rbf( int vcount, int var_count, const float** vecs,
cvExp( &R, &R ); cvExp( &R, &R );
} }
/// Histogram intersection kernel
void CvSVMKernel::calc_intersec( int vcount, int var_count, const float** vecs,
const float* another, Qfloat* results )
{
int j, k;
for( j = 0; j < vcount; j++ )
{
const float* sample = vecs[j];
double s = 0;
for( k = 0; k <= var_count - 4; k += 4 )
s += min(sample[k],another[k]) + min(sample[k+1],another[k+1]) +
min(sample[k+2],another[k+2]) + min(sample[k+3],another[k+3]);
for( ; k < var_count; k++ )
s += min(sample[k],another[k]);
results[j] = (Qfloat)(s);
}
}
/// Exponential chi2 kernel
void CvSVMKernel::calc_chi2( int vcount, int var_count, const float** vecs,
const float* another, Qfloat* results )
{
CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results );
double gamma = -params->gamma;
int j, k;
for( j = 0; j < vcount; j++ )
{
const float* sample = vecs[j];
double chi2 = 0;
for(k = 0 ; k < var_count; k++ )
{
double d = sample[k]*another[k];
double devisor = sample[k]+another[k];
/// if devisor == 0, the Chi2 distance would be zero, but calculation would rise an error because of deviding by zero
if (devisor != 0)
{
chi2 += d*d/devisor;
}
}
results[j] = (Qfloat) (gamma*(1.0-2*chi2));
}
if( vcount > 0 )
cvExp( &R, &R );
}
void CvSVMKernel::calc( int vcount, int var_count, const float** vecs, void CvSVMKernel::calc( int vcount, int var_count, const float** vecs,
const float* another, Qfloat* results ) const float* another, Qfloat* results )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment