From 0683c74b093b05422c5595a5042670ee7932ba09 Mon Sep 17 00:00:00 2001 From: Raynald Chung Date: Thu, 27 Mar 2014 17:18:07 +0100 Subject: [PATCH 1/3] Add SVDD support --- sklearn/svm/src/libsvm/svm.cpp | 120 +++++++++++++++++++++++++++++++++ sklearn/svm/src/libsvm/svm.h | 2 +- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/sklearn/svm/src/libsvm/svm.cpp b/sklearn/svm/src/libsvm/svm.cpp index c6b183908c7e6..8cebde8401a36 100644 --- a/sklearn/svm/src/libsvm/svm.cpp +++ b/sklearn/svm/src/libsvm/svm.cpp @@ -1816,6 +1816,114 @@ static void solve_nu_svr( delete[] y; } +static void solve_svdd( + const svm_problem *prob, const svm_parameter *param, + double *alpha, Solver::SolutionInfo* si) +{ + int l = prob->l; + int i,j; + double r_square; + double C = param->C; + double *QD = new double[l]; + double *linear_term = new double[l]; + schar *ones = new schar[l]; + + ONE_CLASS_Q Q = ONE_CLASS_Q(*prob, *param); + for(i=0;i (double)1/l) + { + double sum_alpha = 1; + for(i=0;ieps, si, param->shrinking); + + // \bar{R} = 2(obj-rho) + sum K_{ii}*alpha_i + // because rho = (a^Ta - \bar{R})/2 + r_square = 2*(si->obj-si->rho); + for(i=0;i 1/l, where dual is divided by 2 + for(i=0;ix[i],prob->x[j],*param); + } + si->obj = (obj + rho/l)*C; + si->rho = rho / (l*l); + + } + + info("R^2 = %f\n",r_square); + + delete[] linear_term; + delete[] QD; + delete[] ones; + +} + +static void solve_r2( + const svm_problem *prob, const svm_parameter *param, + double *alpha, Solver::SolutionInfo* si) +{ + svm_parameter svdd_param = *param; + svdd_param.C = 2; + + solve_svdd(prob,&svdd_param,alpha,si); +} + +static void solve_r2q( + const svm_problem *prob, const svm_parameter *param, + double *alpha, Solver::SolutionInfo* si) +{ + int l = prob->l; + double *linear_term = new double[l]; + schar *ones = new schar[l]; + int i; + + alpha[0] = 1; + for(i=1;ix[i],prob->x[i],*param) + 1.0/param->C); + ones[i] = 1; + } + + Solver s; + s.Solve(l, R2_Qq(*prob,*param), linear_term, ones, + alpha, INF, INF, param->eps, si, param->shrinking); + + info("R^2 = %f\n", -2 *si->obj); + + delete[] linear_term; + delete[] ones; +} + // // decision_function // @@ -1853,6 +1961,18 @@ static decision_function svm_train_one( si.upper_bound = Malloc(double,2*prob->l); solve_nu_svr(prob,param,alpha,&si); break; + case SVDD: + si.upper_bound = Malloc(double,2*prob->l); + solve_svdd(prob,param,alpha,&si); + break; + case R2: + si.upper_bound = Malloc(double,2*prob->l); + solve_r2(prob,param,alpha,&si); + break; + case R2q: + si.upper_bound = Malloc(double,2*prob->l); + solve_r2q(prob,param,alpha,&si); + break; } *status |= si.solve_timed_out; diff --git a/sklearn/svm/src/libsvm/svm.h b/sklearn/svm/src/libsvm/svm.h index 93a041377a464..41643ec8012ed 100644 --- a/sklearn/svm/src/libsvm/svm.h +++ b/sklearn/svm/src/libsvm/svm.h @@ -39,7 +39,7 @@ struct svm_csr_problem }; -enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR }; /* svm_type */ +enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR, SVDD, R2, R2q }; /* svm_type */ enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED }; /* kernel_type */ struct svm_parameter From ccc10e4b4929296aed977d9884d9f03676a461b7 Mon Sep 17 00:00:00 2001 From: Raynald Chung Date: Fri, 28 Mar 2014 15:28:46 +0100 Subject: [PATCH 2/3] Reversion2 --- sklearn/svm/src/libsvm/svm.cpp | 94 +++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/sklearn/svm/src/libsvm/svm.cpp b/sklearn/svm/src/libsvm/svm.cpp index 8cebde8401a36..cced7b2638e9a 100644 --- a/sklearn/svm/src/libsvm/svm.cpp +++ b/sklearn/svm/src/libsvm/svm.cpp @@ -1494,11 +1494,60 @@ class ONE_CLASS_Q: public Kernel double *QD; }; +class R2_Qq: public Kernel +{ + public: + R2_Qq(const PREFIX(problem) & prob, const svm_parameter& param) + :Kernel(prob.l, prob.x, param) + { + cache = new Cache(prob.l,(int)(param.cache_size*(1<<20))); + this->C = param.C; + QD = new double[prob.l]; + for(int i=0;i*kernel_function)(i,i) + 1/C; + } + + Qfloat *get_Q(int i, int len) const + { + Qfloat *data; + int start; + if((start = cache->get_data(i,&data,len)) < len) + { + for(int j=start;j*kernel_function)(i,j); + if(i >= start && i < len) + data[i] += 1/C; + } + return data; + } + + double *get_QD() const + { + return QD; + } + + void swap_index(int i, int j) const + { + cache->swap_index(i,j); + Kernel::swap_index(i,j); + swap(QD[i],QD[j]); + } + + ~R2_Qq() + { + delete cache; + } + private: + Cache *cache; + double C; + double *QD; +}; + class SVR_Q: public Kernel { -public: - SVR_Q(const PREFIX(problem)& prob, const svm_parameter& param) - :Kernel(prob.l, prob.x, param) + public: + SVR_Q(const PREFIX(problem)& prob, const svm_parameter& param) + :Kernel(prob.l, prob.x, param) { l = prob.l; cache = new Cache(l,(long int)(param.cache_size*(1<<20))); @@ -1817,38 +1866,43 @@ static void solve_nu_svr( } static void solve_svdd( - const svm_problem *prob, const svm_parameter *param, + const PREFIX(problem) *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { int l = prob->l; int i,j; double r_square; - double C = param->C; + double *C = new double[2*l]; double *QD = new double[l]; double *linear_term = new double[l]; schar *ones = new schar[l]; + double sum; ONE_CLASS_Q Q = ONE_CLASS_Q(*prob, *param); + sum = 0; for(i=0;iW[i]*param->C; + sum += C[i]; } + sum /= l; - if(C > (double)1/l) + if(sum > (double)1/l) { double sum_alpha = 1; for(i=0;ieps, si, param->shrinking); + s.Solve(l, Q, linear_term, ones, alpha, C, + param->eps, si, param->shrinking, param->max_iter); // \bar{R} = 2(obj-rho) + sum K_{ii}*alpha_i // because rho = (a^Ta - \bar{R})/2 @@ -1870,9 +1924,9 @@ static void solve_svdd( obj -= QD[i]/2; rho += QD[i]/2; for(j=i+1;jx[i],prob->x[j],*param); + rho += Kernel::k_function(prob->x+i, prob->x+j,*param); } - si->obj = (obj + rho/l)*C; + si->obj = (obj + rho/l)*sum; si->rho = rho / (l*l); } @@ -1882,11 +1936,12 @@ static void solve_svdd( delete[] linear_term; delete[] QD; delete[] ones; + delete[] C; } static void solve_r2( - const svm_problem *prob, const svm_parameter *param, + const PREFIX(problem) *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { svm_parameter svdd_param = *param; @@ -1896,11 +1951,12 @@ static void solve_r2( } static void solve_r2q( - const svm_problem *prob, const svm_parameter *param, + const PREFIX(problem) *prob, const svm_parameter *param, double *alpha, Solver::SolutionInfo* si) { int l = prob->l; double *linear_term = new double[l]; + double *C=new double[l]; schar *ones = new schar[l]; int i; @@ -1910,18 +1966,20 @@ static void solve_r2q( for(i=0;ix[i],prob->x[i],*param) + 1.0/param->C); + C[i] = INF; + linear_term[i]=-0.5*(Kernel::k_function(prob->x+i,prob->x+i,*param) + 1.0/param->C); ones[i] = 1; } Solver s; s.Solve(l, R2_Qq(*prob,*param), linear_term, ones, - alpha, INF, INF, param->eps, si, param->shrinking); + alpha, C, param->eps, si, param->shrinking, param->max_iter); info("R^2 = %f\n", -2 *si->obj); delete[] linear_term; delete[] ones; + delete[] C; } // @@ -1962,15 +2020,15 @@ static decision_function svm_train_one( solve_nu_svr(prob,param,alpha,&si); break; case SVDD: - si.upper_bound = Malloc(double,2*prob->l); + si.upper_bound = Malloc(double,prob->l); solve_svdd(prob,param,alpha,&si); break; case R2: - si.upper_bound = Malloc(double,2*prob->l); + si.upper_bound = Malloc(double,prob->l); solve_r2(prob,param,alpha,&si); break; case R2q: - si.upper_bound = Malloc(double,2*prob->l); + si.upper_bound = Malloc(double,prob->l); solve_r2q(prob,param,alpha,&si); break; } From 8a1c8dbe15a6f222b3050802cabba0ff9086f9ab Mon Sep 17 00:00:00 2001 From: Raynald Chung Date: Fri, 28 Mar 2014 16:33:42 +0100 Subject: [PATCH 3/3] SVDD added --- sklearn/svm/src/libsvm/svm.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sklearn/svm/src/libsvm/svm.cpp b/sklearn/svm/src/libsvm/svm.cpp index cced7b2638e9a..638ee8815608e 100644 --- a/sklearn/svm/src/libsvm/svm.cpp +++ b/sklearn/svm/src/libsvm/svm.cpp @@ -1924,7 +1924,11 @@ static void solve_svdd( obj -= QD[i]/2; rho += QD[i]/2; for(j=i+1;jx+i, prob->x+j,*param); +#else + rho += Kernel::k_function(prob->x[i], prob->x[j],*param); +#endif } si->obj = (obj + rho/l)*sum; si->rho = rho / (l*l); @@ -1967,7 +1971,11 @@ static void solve_r2q( for(i=0;ix+i,prob->x+i,*param) + 1.0/param->C); +#else + linear_term[i]=-0.5*(Kernel::k_function(prob->x[i],prob->x[i],*param) + 1.0/param->C); +#endif ones[i] = 1; }