36 #ifndef DOXYGEN_SHOULD_SKIP_THIS
64 template <
class S,
class T>
inline void clone(T*& dst, S* src, int32_t n)
67 memcpy((
void *)dst,(
void *)src,
sizeof(T)*n);
84 Cache(int32_t l, int64_t size);
90 int32_t get_data(
const int32_t index, Qfloat **data, int32_t len);
91 void swap_index(int32_t i, int32_t j);
105 void lru_delete(head_t *h);
106 void lru_insert(head_t *h);
109 Cache::Cache(int32_t l_, int64_t size_):l(l_),size(size_)
111 head = (head_t *)calloc(l,
sizeof(head_t));
112 size /=
sizeof(Qfloat);
113 size -= l *
sizeof(head_t) /
sizeof(Qfloat);
115 lru_head.next = lru_head.prev = &lru_head;
120 for(head_t *h = lru_head.next; h != &lru_head; h=h->next)
125 void Cache::lru_delete(head_t *h)
128 h->prev->next = h->next;
129 h->next->prev = h->prev;
132 void Cache::lru_insert(head_t *h)
136 h->prev = lru_head.prev;
141 int32_t Cache::get_data(
const int32_t index, Qfloat **data, int32_t len)
143 head_t *h = &head[index];
144 if(h->len) lru_delete(h);
145 int32_t more = len - h->len;
152 head_t *old = lru_head.next;
171 void Cache::swap_index(int32_t i, int32_t j)
175 if(head[i].len) lru_delete(&head[i]);
176 if(head[j].len) lru_delete(&head[j]);
179 if(head[i].len) lru_insert(&head[i]);
180 if(head[j].len) lru_insert(&head[j]);
183 for(head_t *h = lru_head.next; h!=&lru_head; h=h->next)
211 virtual Qfloat *get_Q(int32_t column, int32_t len)
const = 0;
212 virtual Qfloat *get_QD()
const = 0;
213 virtual void swap_index(int32_t i, int32_t j)
const = 0;
214 virtual ~QMatrix() {}
222 struct Q_THREAD_PARAM
229 const LibSVMKernel* q;
234 class LibSVMKernel:
public QMatrix {
236 LibSVMKernel(int32_t l, svm_node *
const * x,
const svm_parameter& param);
237 virtual ~LibSVMKernel();
239 virtual Qfloat *get_Q(int32_t column, int32_t len)
const = 0;
240 virtual Qfloat *get_QD()
const = 0;
241 virtual void swap_index(int32_t i, int32_t j)
const
247 static void* compute_Q_parallel_helper(
void* p)
249 Q_THREAD_PARAM* params= (Q_THREAD_PARAM*) p;
251 int32_t start=params->start;
252 int32_t end=params->end;
254 Qfloat* data=params->data;
255 const LibSVMKernel* q=params->q;
259 for(int32_t j=start;j<end;j++)
260 data[j] = (Qfloat) y[i]*y[j]*q->kernel_function(i,j);
264 for(int32_t j=start;j<end;j++)
265 data[j] = (Qfloat) q->kernel_function(i,j);
271 void compute_Q_parallel(Qfloat* data,
float64_t* lab, int32_t i, int32_t start, int32_t len)
const
276 Q_THREAD_PARAM params;
283 compute_Q_parallel_helper((
void*) ¶ms);
288 int32_t total_num=(len-start);
289 pthread_t* threads =
SG_MALLOC(pthread_t, num_threads-1);
290 Q_THREAD_PARAM* params =
SG_MALLOC(Q_THREAD_PARAM, num_threads);
291 int32_t step= total_num/num_threads;
296 for (t=0; t<num_threads; t++)
299 params[t].start=t*step;
300 params[t].end=(t+1)*step;
305 int code=pthread_create(&threads[t], NULL,
306 compute_Q_parallel_helper, (
void*)¶ms[t]);
310 SG_SWARNING(
"Thread creation failed (thread %d of %d) "
311 "with error:'%s'\n",t, num_threads, strerror(code));
318 params[t].start=t*step;
323 compute_Q_parallel_helper(¶ms[t]);
325 for (t=0; t<num_threads; t++)
327 if (pthread_join(threads[t], NULL) != 0)
328 SG_SWARNING(
"pthread_join of thread %d/%d failed\n", t, num_threads);
337 inline float64_t kernel_function(int32_t i, int32_t j)
const
339 return kernel->kernel(x[i]->index,x[j]->index);
348 const int32_t kernel_type;
349 const int32_t degree;
354 LibSVMKernel::LibSVMKernel(int32_t l, svm_node *
const * x_,
const svm_parameter& param)
355 : kernel_type(param.kernel_type), degree(param.degree),
356 gamma(param.gamma), coef0(param.coef0)
361 max_train_time=param.max_train_time;
364 LibSVMKernel::~LibSVMKernel()
391 virtual ~Solver() {};
393 struct SolutionInfo {
402 int32_t l,
const QMatrix& Q,
const float64_t *p_,
const schar *y_,
404 SolutionInfo* si, int32_t shrinking,
bool use_bias);
410 enum { LOWER_BOUND, UPPER_BOUND, FREE };
425 return (y[i] > 0)? Cp : Cn;
427 void update_alpha_status(int32_t i)
429 if(alpha[i] >= get_C(i))
430 alpha_status[i] = UPPER_BOUND;
431 else if(alpha[i] <= 0)
432 alpha_status[i] = LOWER_BOUND;
433 else alpha_status[i] = FREE;
435 bool is_upper_bound(int32_t i) {
return alpha_status[i] == UPPER_BOUND; }
436 bool is_lower_bound(int32_t i) {
return alpha_status[i] == LOWER_BOUND; }
437 bool is_free(int32_t i) {
return alpha_status[i] == FREE; }
438 void swap_index(int32_t i, int32_t j);
439 void reconstruct_gradient();
440 virtual int32_t select_working_set(int32_t &i, int32_t &j,
float64_t &gap);
442 virtual void do_shrinking();
447 void Solver::swap_index(int32_t i, int32_t j)
459 void Solver::reconstruct_gradient()
463 if(active_size == l)
return;
468 for(j=active_size;j<l;j++)
469 G[j] = G_bar[j] + p[j];
471 for(j=0;j<active_size;j++)
475 if (nr_free*l > 2*active_size*(l-active_size))
477 for(i=active_size;i<l;i++)
479 const Qfloat *Q_i = Q->get_Q(i,active_size);
480 for(j=0;j<active_size;j++)
482 G[i] += alpha[j] * Q_i[j];
487 for(i=0;i<active_size;i++)
490 const Qfloat *Q_i = Q->get_Q(i,l);
492 for(j=active_size;j<l;j++)
493 G[j] += alpha_i * Q_i[j];
499 int32_t p_l,
const QMatrix& p_Q,
const float64_t *p_p,
501 float64_t p_eps, SolutionInfo* p_si, int32_t shrinking,
bool use_bias)
508 clone(alpha,p_alpha,l);
517 for(int32_t i=0;i<l;i++)
518 update_alpha_status(i);
524 for(int32_t i=0;i<l;i++)
541 SG_SINFO(
"Computing gradient for initial set of non-zero alphas\n");
545 if(!is_lower_bound(i))
547 const Qfloat *Q_i = Q->get_Q(i,l);
551 G[j] += alpha_i*Q_i[j];
552 if(is_upper_bound(i))
554 G_bar[j] += get_C(i) * Q_i[j];
568 if (Q->max_train_time > 0 && start_time.cur_time_diff() > Q->max_train_time)
576 if(shrinking) do_shrinking();
582 if(select_working_set(i,j, gap)!=0)
585 reconstruct_gradient();
589 if(select_working_set(i,j, gap)!=0)
601 const Qfloat *Q_i = Q->get_Q(i,active_size);
602 const Qfloat *Q_j = Q->get_Q(j,active_size);
612 double pi=G[i]-Q_i[i]*alpha[i]-Q_i[j]*alpha[j];
613 double pj=G[j]-Q_i[j]*alpha[i]-Q_j[j]*alpha[j];
614 double det=Q_i[i]*Q_j[j]-Q_i[j]*Q_i[j];
615 double alpha_i=-(Q_j[j]*pi-Q_i[j]*pj)/det;
617 double alpha_j=-(-Q_i[j]*pi+Q_i[i]*pj)/det;
620 if (alpha_i==0 || alpha_i == C_i)
622 if (alpha_j==0 || alpha_j == C_j)
625 alpha[i]=alpha_i; alpha[j]=alpha_j;
631 float64_t quad_coef = Q_i[i]+Q_j[j]+2*Q_i[j];
660 alpha[j] = C_i - diff;
668 alpha[i] = C_j + diff;
674 float64_t quad_coef = Q_i[i]+Q_j[j]-2*Q_i[j];
687 alpha[j] = sum - C_i;
703 alpha[i] = sum - C_j;
719 float64_t delta_alpha_i = alpha[i] - old_alpha_i;
720 float64_t delta_alpha_j = alpha[j] - old_alpha_j;
722 for(int32_t k=0;k<active_size;k++)
724 G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
730 bool ui = is_upper_bound(i);
731 bool uj = is_upper_bound(j);
732 update_alpha_status(i);
733 update_alpha_status(j);
735 if(ui != is_upper_bound(i))
740 G_bar[k] -= C_i * Q_i[k];
743 G_bar[k] += C_i * Q_i[k];
746 if(uj != is_upper_bound(j))
751 G_bar[k] -= C_j * Q_j[k];
754 G_bar[k] += C_j * Q_j[k];
763 v += alpha[i] * (G[i] + p[i]);
769 SG_SPRINT(
"dual obj=%f primal obf=%f gap=%f\n", v/2, primal, gap);
779 p_si->rho = calculate_rho();
786 v += alpha[i] * (G[i] + p[i]);
793 for(int32_t i=0;i<l;i++)
794 p_alpha[active_set[i]] = alpha[i];
797 p_si->upper_bound_p = Cp;
798 p_si->upper_bound_n = Cn;
800 SG_SINFO(
"\noptimization finished, #iter = %d\n",iter);
812 int32_t Solver::select_working_set(
813 int32_t &out_i, int32_t &out_j,
float64_t &gap)
823 int32_t Gmax_idx = -1;
824 int32_t Gmin_idx = -1;
827 for(int32_t t=0;t<active_size;t++)
830 if(!is_upper_bound(t))
839 if(!is_lower_bound(t))
847 int32_t i = Gmax_idx;
848 const Qfloat *Q_i = NULL;
850 Q_i = Q->get_Q(i,active_size);
852 for(int32_t j=0;j<active_size;j++)
856 if (!is_lower_bound(j))
864 float64_t quad_coef=Q_i[i]+QD[j]-2.0*y[i]*Q_i[j];
866 obj_diff = -(grad_diff*grad_diff)/quad_coef;
868 obj_diff = -(grad_diff*grad_diff)/TAU;
870 if (obj_diff <= obj_diff_min)
873 obj_diff_min = obj_diff;
880 if (!is_upper_bound(j))
888 float64_t quad_coef=Q_i[i]+QD[j]+2.0*y[i]*Q_i[j];
890 obj_diff = -(grad_diff*grad_diff)/quad_coef;
892 obj_diff = -(grad_diff*grad_diff)/TAU;
894 if (obj_diff <= obj_diff_min)
897 obj_diff_min = obj_diff;
915 if(is_upper_bound(i))
918 return(-G[i] > Gmax1);
920 return(-G[i] > Gmax2);
922 else if(is_lower_bound(i))
925 return(G[i] > Gmax2);
927 return(G[i] > Gmax1);
934 void Solver::do_shrinking()
941 for(i=0;i<active_size;i++)
945 if(!is_upper_bound(i))
950 if(!is_lower_bound(i))
958 if(!is_upper_bound(i))
963 if(!is_lower_bound(i))
971 if(unshrink ==
false && Gmax1 + Gmax2 <= eps*10)
974 reconstruct_gradient();
978 for(i=0;i<active_size;i++)
979 if (be_shrunk(i, Gmax1, Gmax2))
982 while (active_size > i)
984 if (!be_shrunk(active_size, Gmax1, Gmax2))
986 swap_index(i,active_size);
998 float64_t ub = INF, lb = -INF, sum_free = 0;
999 for(int32_t i=0;i<active_size;i++)
1003 if(is_upper_bound(i))
1010 else if(is_lower_bound(i))
1025 r = sum_free/nr_free;
1036 class WeightedSolver :
public Solver
1044 this->Cs = cost_vec;
1066 class Solver_NU :
public Solver
1071 int32_t p_l,
const QMatrix& p_Q,
const float64_t *p_p,
1073 float64_t p_eps, SolutionInfo* p_si, int32_t shrinking,
bool use_bias)
1076 Solver::Solve(p_l,p_Q,p_p,p_y,p_alpha,p_Cp,p_Cn,p_eps,p_si,
1077 shrinking,use_bias);
1081 int32_t select_working_set(int32_t &i, int32_t &j,
float64_t &gap);
1086 void do_shrinking();
1090 int32_t Solver_NU::select_working_set(
1091 int32_t &out_i, int32_t &out_j,
float64_t &gap)
1101 int32_t Gmaxp_idx = -1;
1105 int32_t Gmaxn_idx = -1;
1107 int32_t Gmin_idx = -1;
1110 for(int32_t t=0;t<active_size;t++)
1113 if(!is_upper_bound(t))
1122 if(!is_lower_bound(t))
1130 int32_t ip = Gmaxp_idx;
1131 int32_t
in = Gmaxn_idx;
1132 const Qfloat *Q_ip = NULL;
1133 const Qfloat *Q_in = NULL;
1135 Q_ip = Q->get_Q(ip,active_size);
1137 Q_in = Q->get_Q(in,active_size);
1139 for(int32_t j=0;j<active_size;j++)
1143 if (!is_lower_bound(j))
1151 float64_t quad_coef = Q_ip[ip]+QD[j]-2*Q_ip[j];
1153 obj_diff = -(grad_diff*grad_diff)/quad_coef;
1155 obj_diff = -(grad_diff*grad_diff)/TAU;
1157 if (obj_diff <= obj_diff_min)
1160 obj_diff_min = obj_diff;
1167 if (!is_upper_bound(j))
1170 if (-G[j] >= Gmaxn2)
1177 obj_diff = -(grad_diff*grad_diff)/quad_coef;
1179 obj_diff = -(grad_diff*grad_diff)/TAU;
1181 if (obj_diff <= obj_diff_min)
1184 obj_diff_min = obj_diff;
1195 if (y[Gmin_idx] == +1)
1204 bool Solver_NU::be_shrunk(
1208 if(is_upper_bound(i))
1211 return(-G[i] > Gmax1);
1213 return(-G[i] > Gmax4);
1215 else if(is_lower_bound(i))
1218 return(G[i] > Gmax2);
1220 return(G[i] > Gmax3);
1226 void Solver_NU::do_shrinking()
1235 for(i=0;i<active_size;i++)
1237 if(!is_upper_bound(i))
1241 if(-G[i] > Gmax1) Gmax1 = -G[i];
1243 else if(-G[i] > Gmax4) Gmax4 = -G[i];
1245 if(!is_lower_bound(i))
1249 if(G[i] > Gmax2) Gmax2 = G[i];
1251 else if(G[i] > Gmax3) Gmax3 = G[i];
1255 if(unshrink ==
false &&
CMath::max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10)
1258 reconstruct_gradient();
1262 for(i=0;i<active_size;i++)
1263 if (be_shrunk(i, Gmax1, Gmax2, Gmax3, Gmax4))
1266 while (active_size > i)
1268 if (!be_shrunk(active_size, Gmax1, Gmax2, Gmax3, Gmax4))
1270 swap_index(i,active_size);
1280 int32_t nr_free1 = 0,nr_free2 = 0;
1285 for(int32_t i=0; i<active_size; i++)
1289 if(is_upper_bound(i))
1291 else if(is_lower_bound(i))
1301 if(is_upper_bound(i))
1303 else if(is_lower_bound(i))
1315 r1 = sum_free1/nr_free1;
1320 r2 = sum_free2/nr_free2;
1328 class SVC_QMC:
public LibSVMKernel
1331 SVC_QMC(
const svm_problem& prob,
const svm_parameter& param,
const schar *y_, int32_t n_class,
float64_t fac)
1332 :LibSVMKernel(prob.l, prob.x, param)
1337 cache =
new Cache(prob.l,(int64_t)(param.cache_size*(1l<<20)));
1339 for(int32_t i=0;i<prob.l;i++)
1341 QD[i]= factor*(nr_class-1)*kernel_function(i,i);
1345 Qfloat *get_Q(int32_t i, int32_t len)
const
1349 if((start = cache->get_data(i,&data,len)) < len)
1351 compute_Q_parallel(data, NULL, i, start, len);
1353 for(int32_t j=start;j<len;j++)
1356 data[j] *= (factor*(nr_class-1));
1358 data[j] *= (-factor);
1364 inline Qfloat get_orig_Qij(Qfloat Q, int32_t i, int32_t j)
1367 return Q/(nr_class-1);
1372 Qfloat *get_QD()
const
1377 void swap_index(int32_t i, int32_t j)
const
1379 cache->swap_index(i,j);
1380 LibSVMKernel::swap_index(i,j);
1404 class Solver_NUMC :
public Solver
1407 Solver_NUMC(int32_t n_class,
float64_t svm_nu)
1414 int32_t p_l,
const QMatrix& p_Q,
const float64_t *p_p,
1416 float64_t p_eps, SolutionInfo* p_si, int32_t shrinking,
bool use_bias)
1419 Solver::Solve(p_l,p_Q,p_p,p_y,p_alpha,p_Cp,p_Cn,p_eps,p_si,shrinking, use_bias);
1425 int32_t select_working_set(int32_t &i, int32_t &j,
float64_t &gap);
1430 void do_shrinking();
1440 clone(alpha,p_alpha,l);
1443 for(int32_t i=0;i<l;i++)
1444 update_alpha_status(i);
1449 for (int32_t i=0; i<nr_class; i++)
1455 for (int32_t i=0; i<active_size; i++)
1457 update_alpha_status(i);
1458 if(!is_upper_bound(i) && !is_lower_bound(i))
1459 class_count[(int32_t) y[i]]++;
1472 for (int32_t i=0; i<nr_class; i++)
1474 zero_counts[i]=-INF;
1478 for (int32_t i=0; i<active_size; i++)
1484 Qfloat* Q_i = Q->get_Q(i,active_size);
1487 for (
int j=0; j<active_size; j++)
1489 quad+= alpha[i]*alpha[j]*Q_i[j];
1492 if(!is_upper_bound(i) && !is_lower_bound(i))
1497 if (class_count[(int32_t) y[i]] == 0 && y[j]==y[i])
1498 sum_zero_count+= tmp;
1500 SVC_QMC* QMC=(SVC_QMC*) Q;
1501 float64_t norm_tmp=alpha[i]*alpha[j]*QMC->get_orig_Qij(Q_i[j], i, j);
1503 normwcw[(int32_t) y[i]]+=norm_tmp;
1505 normwcw[(int32_t) y[i]]-=2.0/nr_class*norm_tmp;
1506 normwc_const+=norm_tmp;
1509 if (class_count[(int32_t) y[i]] == 0)
1511 if (zero_counts[(int32_t) y[i]]<sum_zero_count)
1512 zero_counts[(int32_t) y[i]]=sum_zero_count;
1515 biases[(int32_t) y[i]+1]-=sum_free;
1516 if (class_count[(int32_t) y[i]] != 0.0)
1517 rho+=sum_free/class_count[(int32_t) y[i]];
1518 outputs[i]+=sum_free+sum_atbound;
1521 for (int32_t i=0; i<nr_class; i++)
1523 if (class_count[i] == 0.0)
1524 rho+=zero_counts[i];
1526 normwcw[i]+=normwc_const/
CMath::sq(nr_class);
1537 for (int32_t i=0; i<nr_class; i++)
1539 if (class_count[i] != 0.0)
1540 biases[i+1]=biases[i+1]/class_count[i]+rho;
1542 biases[i+1]+=rho-zero_counts[i];
1552 for (int32_t i=0; i<l; i++)
1553 outputs[i]+=biases[(int32_t) y[i]+1];
1561 for (int32_t i=0; i<active_size; i++)
1563 if (is_lower_bound(i))
1572 float64_t primal=0.5*quad- nr_class*rho+xi*mu;
1585 int32_t Solver_NUMC::select_working_set(
1586 int32_t &out_i, int32_t &out_j,
float64_t &gap)
1596 int32_t best_out_i=-1;
1597 int32_t best_out_j=-1;
1601 int32_t* Gmaxp_idx =
SG_MALLOC(int32_t, nr_class);
1603 int32_t* Gmin_idx =
SG_MALLOC(int32_t, nr_class);
1606 for (int32_t i=0; i<nr_class; i++)
1612 obj_diff_min[i]=INF;
1615 for(int32_t t=0;t<active_size;t++)
1618 if(!is_upper_bound(t))
1620 if(-G[t] >= Gmaxp[cidx])
1622 Gmaxp[cidx] = -G[t];
1623 Gmaxp_idx[cidx] = t;
1628 for(int32_t j=0;j<active_size;j++)
1631 int32_t ip = Gmaxp_idx[cidx];
1632 const Qfloat *Q_ip = NULL;
1634 Q_ip = Q->get_Q(ip,active_size);
1636 if (!is_lower_bound(j))
1639 if (G[j] >= Gmaxp2[cidx])
1640 Gmaxp2[cidx] = G[j];
1644 float64_t quad_coef = Q_ip[ip]+QD[j]-2*Q_ip[j];
1646 obj_diff = -(grad_diff*grad_diff)/quad_coef;
1648 obj_diff = -(grad_diff*grad_diff)/TAU;
1650 if (obj_diff <= obj_diff_min[cidx])
1653 obj_diff_min[cidx] = obj_diff;
1658 gap=Gmaxp[cidx]+Gmaxp2[cidx];
1659 if (gap>=best_gap && Gmin_idx[cidx]>=0 &&
1660 Gmaxp_idx[cidx]>=0 && Gmin_idx[cidx]<active_size)
1662 out_i = Gmaxp_idx[cidx];
1663 out_j = Gmin_idx[cidx];
1675 SG_SDEBUG(
"i=%d j=%d best_gap=%f y_i=%f y_j=%f\n", out_i, out_j, gap, y[out_i], y[out_j]);
1690 bool Solver_NUMC::be_shrunk(
1697 void Solver_NUMC::do_shrinking()
1710 class SVC_Q:
public LibSVMKernel
1713 SVC_Q(
const svm_problem& prob,
const svm_parameter& param,
const schar *y_)
1714 :LibSVMKernel(prob.l, prob.x, param)
1717 cache =
new Cache(prob.l,(int64_t)(param.cache_size*(1l<<20)));
1719 for(int32_t i=0;i<prob.l;i++)
1720 QD[i]= (Qfloat)kernel_function(i,i);
1723 Qfloat *get_Q(int32_t i, int32_t len)
const
1727 if((start = cache->get_data(i,&data,len)) < len)
1728 compute_Q_parallel(data, y, i, start, len);
1733 Qfloat *get_QD()
const
1738 void swap_index(int32_t i, int32_t j)
const
1740 cache->swap_index(i,j);
1741 LibSVMKernel::swap_index(i,j);
1759 class ONE_CLASS_Q:
public LibSVMKernel
1762 ONE_CLASS_Q(
const svm_problem& prob,
const svm_parameter& param)
1763 :LibSVMKernel(prob.l, prob.x, param)
1765 cache =
new Cache(prob.l,(int64_t)(param.cache_size*(1l<<20)));
1767 for(int32_t i=0;i<prob.l;i++)
1768 QD[i]= (Qfloat)kernel_function(i,i);
1771 Qfloat *get_Q(int32_t i, int32_t len)
const
1775 if((start = cache->get_data(i,&data,len)) < len)
1776 compute_Q_parallel(data, NULL, i, start, len);
1781 Qfloat *get_QD()
const
1786 void swap_index(int32_t i, int32_t j)
const
1788 cache->swap_index(i,j);
1789 LibSVMKernel::swap_index(i,j);
1803 class SVR_Q:
public LibSVMKernel
1806 SVR_Q(
const svm_problem& prob,
const svm_parameter& param)
1807 :LibSVMKernel(prob.l, prob.x, param)
1810 cache =
new Cache(l,(int64_t)(param.cache_size*(1l<<20)));
1814 for(int32_t k=0;k<l;k++)
1820 QD[k]= (Qfloat)kernel_function(k,k);
1828 void swap_index(int32_t i, int32_t j)
const
1835 Qfloat *get_Q(int32_t i, int32_t len)
const
1838 int32_t real_i = index[i];
1839 if(cache->get_data(real_i,&data,l) < l)
1840 compute_Q_parallel(data, NULL, real_i, 0, l);
1843 Qfloat *buf = buffer[next_buffer];
1844 next_buffer = 1 - next_buffer;
1846 for(int32_t j=0;j<len;j++)
1847 buf[j] = si * sign[j] * data[index[j]];
1851 Qfloat *get_QD()
const
1871 mutable int32_t next_buffer;
1879 static void solve_c_svc(
1880 const svm_problem *prob,
const svm_parameter* param,
1883 int32_t l = prob->l;
1891 if(prob->y[i] > 0) y[i] = +1;
else y[i]=-1;
1895 s.Solve(l, SVC_Q(*prob,*param,y), prob->pv, y,
1896 alpha, Cp, Cn, param->eps, si, param->shrinking, param->use_bias);
1900 sum_alpha += alpha[i];
1903 SG_SINFO(
"nu = %f\n", sum_alpha/(param->C*prob->l));
1913 void solve_c_svc_weighted(
1914 const svm_problem *prob,
const svm_parameter* param,
1927 if(prob->y[i] > 0) y[i] = +1;
else y[i]=-1;
1930 WeightedSolver s = WeightedSolver(prob->C);
1931 s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y,
1932 alpha, Cp, Cn, param->eps, si, param->shrinking, param->use_bias);
1936 sum_alpha += alpha[i];
1948 static void solve_nu_svc(
1949 const svm_problem *prob,
const svm_parameter *param,
1950 float64_t *alpha, Solver::SolutionInfo* si)
1953 int32_t l = prob->l;
1971 sum_pos -= alpha[i];
1976 sum_neg -= alpha[i];
1985 s.Solve(l, SVC_Q(*prob,*param,y), zeros, y,
1986 alpha, 1.0, 1.0, param->eps, si, param->shrinking, param->use_bias);
1996 si->upper_bound_p = 1/r;
1997 si->upper_bound_n = 1/r;
2003 static void solve_nu_multiclass_svc(
const svm_problem *prob,
2004 const svm_parameter *param, Solver::SolutionInfo* si, svm_model* model)
2006 int32_t l = prob->l;
2012 for(int32_t i=0;i<l;i++)
2018 int32_t nr_class=param->nr_class;
2021 for (int32_t j=0; j<nr_class; j++)
2022 sum_class[j] = nu*l/nr_class;
2024 for(int32_t i=0;i<l;i++)
2026 alpha[i] =
CMath::min(1.0,sum_class[int32_t(y[i])]);
2027 sum_class[int32_t(y[i])] -= alpha[i];
2034 for (int32_t i=0;i<l;i++)
2037 Solver_NUMC s(nr_class, nu);
2040 s.Solve(l, Q, zeros, y,
2041 alpha, 1.0, 1.0, param->eps, si, param->shrinking, param->use_bias);
2044 int32_t* class_sv_count=
SG_MALLOC(int32_t, nr_class);
2046 for (int32_t i=0; i<nr_class; i++)
2047 class_sv_count[i]=0;
2049 for (int32_t i=0; i<l; i++)
2052 class_sv_count[(int32_t) y[i]]++;
2058 model->nr_class = nr_class;
2059 model->label = NULL;
2060 model->SV =
SG_MALLOC(svm_node*,nr_class);
2061 model->nSV =
SG_MALLOC(int32_t, nr_class);
2065 for (int32_t i=0; i<nr_class+1; i++)
2068 model->objective = si->obj;
2070 if (param->use_bias)
2072 SG_SDEBUG(
"Computing biases and primal objective\n");
2073 float64_t primal = s.compute_primal(y, alpha, model->rho, model->normwcw);
2074 SG_SINFO(
"Primal = %10.10f\n", primal);
2077 for (int32_t i=0; i<nr_class; i++)
2079 model->nSV[i]=class_sv_count[i];
2080 model->SV[i] =
SG_MALLOC(svm_node,class_sv_count[i]);
2082 class_sv_count[i]=0;
2085 for (int32_t i=0;i<prob->l;i++)
2087 if(fabs(alpha[i]) > 0)
2089 model->SV[(int32_t) y[i]][class_sv_count[(int32_t) y[i]]].index = prob->x[i]->index;
2090 model->sv_coef[(int32_t) y[i]][class_sv_count[(int32_t) y[i]]] = alpha[i];
2091 class_sv_count[(int32_t) y[i]]++;
2100 static void solve_one_class(
2101 const svm_problem *prob,
const svm_parameter *param,
2102 float64_t *alpha, Solver::SolutionInfo* si)
2104 int32_t l = prob->l;
2109 int32_t n = (int32_t)(param->nu*prob->l);
2114 alpha[n] = param->nu * prob->l - n;
2125 s.Solve(l, ONE_CLASS_Q(*prob,*param), zeros, ones,
2126 alpha, 1.0, 1.0, param->eps, si, param->shrinking, param->use_bias);
2132 static void solve_epsilon_svr(
2133 const svm_problem *prob,
const svm_parameter *param,
2134 float64_t *alpha, Solver::SolutionInfo* si)
2136 int32_t l = prob->l;
2145 linear_term[i] = param->p - prob->y[i];
2149 linear_term[i+l] = param->p + prob->y[i];
2154 s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
2155 alpha2, param->C, param->C, param->eps, si, param->shrinking, param->use_bias);
2160 alpha[i] = alpha2[i] - alpha2[i+l];
2161 sum_alpha += fabs(alpha[i]);
2163 SG_SINFO(
"nu = %f\n",sum_alpha/(param->C*l));
2170 static void solve_nu_svr(
2171 const svm_problem *prob,
const svm_parameter *param,
2172 float64_t *alpha, Solver::SolutionInfo* si)
2174 int32_t l = prob->l;
2187 linear_term[i] = - prob->y[i];
2190 linear_term[i+l] = prob->y[i];
2195 s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
2196 alpha2, C, C, param->eps, si, param->shrinking, param->use_bias);
2201 alpha[i] = alpha2[i] - alpha2[i+l];
2211 struct decision_function
2218 decision_function svm_train_one(
2219 const svm_problem *prob,
const svm_parameter *param,
2223 Solver::SolutionInfo si;
2224 switch(param->svm_type)
2227 solve_c_svc(prob,param,alpha,&si,Cp,Cn);
2230 solve_nu_svc(prob,param,alpha,&si);
2233 solve_one_class(prob,param,alpha,&si);
2236 solve_epsilon_svr(prob,param,alpha,&si);
2239 solve_nu_svr(prob,param,alpha,&si);
2243 SG_SINFO(
"obj = %.16f, rho = %.16f\n",si.obj,si.rho);
2246 if (param->svm_type != ONE_CLASS)
2250 for(int32_t i=0;i<prob->l;i++)
2252 if(fabs(alpha[i]) > 0)
2257 if(fabs(alpha[i]) >= si.upper_bound_p)
2262 if(fabs(alpha[i]) >= si.upper_bound_n)
2267 SG_SINFO(
"nSV = %d, nBSV = %d\n",nSV,nBSV);
2270 decision_function f;
2280 void svm_group_classes(
2281 const svm_problem *prob, int32_t *nr_class_ret, int32_t **label_ret,
2282 int32_t **start_ret, int32_t **count_ret, int32_t *perm)
2284 int32_t l = prob->l;
2285 int32_t max_nr_class = 16;
2286 int32_t nr_class = 0;
2287 int32_t *label =
SG_MALLOC(int32_t, max_nr_class);
2288 int32_t *count =
SG_MALLOC(int32_t, max_nr_class);
2289 int32_t *data_label =
SG_MALLOC(int32_t, l);
2294 int32_t this_label=(int32_t) prob->y[i];
2296 for(j=0;j<nr_class;j++)
2298 if(this_label == label[j])
2307 if(nr_class == max_nr_class)
2310 label=
SG_REALLOC(int32_t, label,max_nr_class);
2311 count=
SG_REALLOC(int32_t, count,max_nr_class);
2313 label[nr_class] = this_label;
2314 count[nr_class] = 1;
2319 int32_t *start =
SG_MALLOC(int32_t, nr_class);
2321 for(i=1;i<nr_class;i++)
2322 start[i] = start[i-1]+count[i-1];
2325 perm[start[data_label[i]]] = i;
2326 ++start[data_label[i]];
2329 for(i=1;i<nr_class;i++)
2330 start[i] = start[i-1]+count[i-1];
2332 *nr_class_ret = nr_class;
2342 svm_model *svm_train(
const svm_problem *prob,
const svm_parameter *param)
2344 svm_model *model =
SG_MALLOC(svm_model,1);
2345 model->param = *param;
2348 if(param->svm_type == ONE_CLASS ||
2349 param->svm_type == EPSILON_SVR ||
2350 param->svm_type == NU_SVR)
2352 SG_SINFO(
"training one class svm or doing epsilon sv regression\n");
2355 model->nr_class = 2;
2356 model->label = NULL;
2359 decision_function f = svm_train_one(prob,param,0,0);
2361 model->rho[0] = f.rho;
2362 model->objective = f.objective;
2366 for(i=0;i<prob->l;i++)
2367 if(fabs(f.alpha[i]) > 0) ++nSV;
2372 for(i=0;i<prob->l;i++)
2373 if(fabs(f.alpha[i]) > 0)
2375 model->SV[j] = prob->x[i];
2376 model->sv_coef[0][j] = f.alpha[i];
2382 else if(param->svm_type == NU_MULTICLASS_SVC)
2384 Solver::SolutionInfo si;
2385 solve_nu_multiclass_svc(prob,param,&si,model);
2386 SG_SINFO(
"obj = %.16f, rho = %.16f\n",si.obj,si.rho);
2391 int32_t l = prob->l;
2393 int32_t *label = NULL;
2394 int32_t *start = NULL;
2395 int32_t *count = NULL;
2399 svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
2407 x[i] = prob->x[perm[i]];
2408 C[i] = prob->C[perm[i]];
2412 pv[i] = prob->pv[perm[i]];
2425 for(i=0;i<nr_class;i++)
2426 weighted_C[i] = param->C;
2427 for(i=0;i<param->nr_weight;i++)
2430 for(j=0;j<nr_class;j++)
2431 if(param->weight_label[i] == label[j])
2434 SG_SWARNING(
"warning: class label %d specified in weight is not found\n", param->weight_label[i]);
2436 weighted_C[j] *= param->weight[i];
2444 decision_function *f =
SG_MALLOC(decision_function,nr_class*(nr_class-1)/2);
2447 for(i=0;i<nr_class;i++)
2448 for(int32_t j=i+1;j<nr_class;j++)
2450 svm_problem sub_prob;
2451 int32_t si = start[i], sj = start[j];
2452 int32_t ci = count[i], cj = count[j];
2454 sub_prob.x =
SG_MALLOC(svm_node *,sub_prob.l);
2462 sub_prob.x[k] = x[si+k];
2464 sub_prob.C[k] = C[si+k];
2465 sub_prob.pv[k] = pv[si+k];
2470 sub_prob.x[ci+k] = x[sj+k];
2471 sub_prob.y[ci+k] = -1;
2472 sub_prob.C[ci+k] = C[sj+k];
2473 sub_prob.pv[ci+k] = pv[sj+k];
2475 sub_prob.y[sub_prob.l]=-1;
2476 sub_prob.C[sub_prob.l]=-1;
2477 sub_prob.pv[sub_prob.l]=-1;
2479 f[p] = svm_train_one(&sub_prob,param,weighted_C[i],weighted_C[j]);
2481 if(!nonzero[si+k] && fabs(f[p].alpha[k]) > 0)
2482 nonzero[si+k] =
true;
2484 if(!nonzero[sj+k] && fabs(f[p].alpha[ci+k]) > 0)
2485 nonzero[sj+k] =
true;
2495 model->objective = f[0].objective;
2496 model->nr_class = nr_class;
2498 model->label =
SG_MALLOC(int32_t, nr_class);
2499 for(i=0;i<nr_class;i++)
2500 model->label[i] = label[i];
2503 for(i=0;i<nr_class*(nr_class-1)/2;i++)
2504 model->rho[i] = f[i].rho;
2506 int32_t total_sv = 0;
2507 int32_t *nz_count =
SG_MALLOC(int32_t, nr_class);
2508 model->nSV =
SG_MALLOC(int32_t, nr_class);
2509 for(i=0;i<nr_class;i++)
2512 for(int32_t j=0;j<count[i];j++)
2513 if(nonzero[start[i]+j])
2518 model->nSV[i] = nSV;
2522 SG_SINFO(
"Total nSV = %d\n",total_sv);
2524 model->l = total_sv;
2525 model->SV =
SG_MALLOC(svm_node *,total_sv);
2528 if(nonzero[i]) model->SV[p++] = x[i];
2530 int32_t *nz_start =
SG_MALLOC(int32_t, nr_class);
2532 for(i=1;i<nr_class;i++)
2533 nz_start[i] = nz_start[i-1]+nz_count[i-1];
2536 for(i=0;i<nr_class-1;i++)
2540 for(i=0;i<nr_class;i++)
2541 for(int32_t j=i+1;j<nr_class;j++)
2547 int32_t si = start[i];
2548 int32_t sj = start[j];
2549 int32_t ci = count[i];
2550 int32_t cj = count[j];
2552 int32_t q = nz_start[i];
2556 model->sv_coef[j-1][q++] = f[p].alpha[k];
2560 model->sv_coef[i][q++] = f[p].alpha[ci+k];
2573 for(i=0;i<nr_class*(nr_class-1)/2;i++)
2582 void svm_destroy_model(svm_model* model)
2584 if(model->free_sv && model->l > 0)
2585 SG_FREE((
void *)(model->SV[0]));
2586 for(int32_t i=0;i<model->nr_class-1;i++)
2596 void svm_destroy_param(svm_parameter* param)
2602 const char *svm_check_parameter(
2603 const svm_problem *prob,
const svm_parameter *param)
2607 int32_t svm_type = param->svm_type;
2608 if(svm_type != C_SVC &&
2609 svm_type != NU_SVC &&
2610 svm_type != ONE_CLASS &&
2611 svm_type != EPSILON_SVR &&
2612 svm_type != NU_SVR &&
2613 svm_type != NU_MULTICLASS_SVC)
2614 return "unknown svm type";
2618 int32_t kernel_type = param->kernel_type;
2619 if(kernel_type != LINEAR &&
2620 kernel_type != POLY &&
2621 kernel_type != RBF &&
2622 kernel_type != SIGMOID &&
2623 kernel_type != PRECOMPUTED)
2624 return "unknown kernel type";
2626 if(param->degree < 0)
2627 return "degree of polynomial kernel < 0";
2631 if(param->cache_size <= 0)
2632 return "cache_size <= 0";
2637 if(svm_type == C_SVC ||
2638 svm_type == EPSILON_SVR ||
2643 if(svm_type == NU_SVC ||
2644 svm_type == ONE_CLASS ||
2646 if(param->nu <= 0 || param->nu > 1)
2647 return "nu <= 0 or nu > 1";
2649 if(svm_type == EPSILON_SVR)
2653 if(param->shrinking != 0 &&
2654 param->shrinking != 1)
2655 return "shrinking != 0 and shrinking != 1";
2660 if(svm_type == NU_SVC)
2662 int32_t l = prob->l;
2663 int32_t max_nr_class = 16;
2664 int32_t nr_class = 0;
2665 int32_t *label =
SG_MALLOC(int32_t, max_nr_class);
2666 int32_t *count =
SG_MALLOC(int32_t, max_nr_class);
2671 int32_t this_label = (int32_t) prob->y[i];
2673 for(j=0;j<nr_class;j++)
2674 if(this_label == label[j])
2681 if(nr_class == max_nr_class)
2684 label=
SG_REALLOC(int32_t, label, max_nr_class);
2685 count=
SG_REALLOC(int32_t, count, max_nr_class);
2687 label[nr_class] = this_label;
2688 count[nr_class] = 1;
2693 for(i=0;i<nr_class;i++)
2695 int32_t n1 = count[i];
2696 for(int32_t j=i+1;j<nr_class;j++)
2698 int32_t n2 = count[j];
2703 return "specified nu is infeasible";
2714 #endif // DOXYGEN_SHOULD_SKIP_THIS