16 #include <shogun/lib/external/libqp.h>
22 static const uint32_t QPSolverMaxIter=0xFFFFFFFF;
30 static const float64_t *get_col( uint32_t i)
32 return( &H2[ BufSize*i ] );
35 BmrmStatistics svm_p3bm_solver(
36 CDualLibQPBMSOSVM *machine,
49 BmrmStatistics p3bmrm;
50 libqp_state_T qp_exitflag={0, 0, 0, 0}, qp_exitflag_good={0, 0, 0, 0};
51 float64_t *b, *b2, *beta, *beta_good, *beta_start, *diag_H, *diag_H2;
52 float64_t R, *Rt, **subgrad_t, *A, QPSolverTolRel, *C=NULL;
53 float64_t *prevW, *wt, alpha, alpha_start, alpha_good=0.0, Fd_alpha0=0.0;
55 floatmax_t rsum, sq_norm_W, sq_norm_Wdiff, sq_norm_prevW, eps;
56 uint32_t *I, *I2, *I_start, *I_good;
59 bmrm_ll *CPList_head, *CPList_tail, *cp_ptr, *cp_ptr2, *cp_list=NULL;
61 bool *map=NULL, tuneAlpha=
true, flag=
true;
62 bool alphaChanged=
false, isThereGoodSolution=
false;
63 TMultipleCPinfo **info=NULL;
64 CStructuredModel* model=machine->get_model();
65 CSOSVMHelper* helper = NULL;
66 uint32_t nDim=model->get_dim();
67 uint32_t to=0, N=0, cp_i=0;
73 tstart=ttime.cur_time_diff(
false);
75 BufSize=_BufSize*cp_models;
112 I= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
114 cp_list= (bmrm_ll*) LIBBMRM_CALLOC(1, bmrm_ll);
122 S= (uint8_t*) LIBBMRM_CALLOC(cp_models, uint8_t);
124 info= (TMultipleCPinfo**) LIBBMRM_CALLOC(cp_models, TMultipleCPinfo*);
126 CFeatures* features = model->get_features();
127 int32_t num_feats = features->get_num_vectors();
132 icp_stats.maxCPs = BufSize;
133 icp_stats.ICPcounter= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
135 icp_stats.ACPs= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
138 if (H==NULL || A==NULL || b==NULL || beta==NULL || subgrad_t==NULL ||
139 diag_H==NULL || I==NULL || icp_stats.ICPcounter==NULL ||
140 icp_stats.ICPs==NULL || icp_stats.ACPs==NULL ||
141 cp_list==NULL || prevW==NULL || wt==NULL || Rt==NULL || C==NULL ||
142 S==NULL || info==NULL || icp_stats.H_buff==NULL)
153 for (uint32_t p=0; p<cp_models; ++p)
157 info[p]=(TMultipleCPinfo*)LIBBMRM_CALLOC(1, TMultipleCPinfo);
160 if (subgrad_t[p]==NULL || info[p]==NULL)
167 to=((p+1)*N > (uint32_t)num_feats) ? (uint32_t)num_feats : (p+1)*N;
168 info[p]->m_N=to-info[p]->m_from;
171 map= (
bool*) LIBBMRM_CALLOC(BufSize,
bool);
179 memset( (
bool*) map,
true, BufSize);
192 I_start= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
194 I_good= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
196 I2= (uint32_t*) LIBBMRM_CALLOC(BufSize, uint32_t);
198 if (beta_start==NULL || beta_good==NULL || b2==NULL || diag_H2==NULL ||
199 I_start==NULL || I_good==NULL || I2==NULL || H2==NULL)
205 p3bmrm.hist_Fp.resize_vector(BufSize);
206 p3bmrm.hist_Fd.resize_vector(BufSize);
207 p3bmrm.hist_wdist.resize_vector(BufSize);
210 Rt[0] = machine->risk(subgrad_t[0], W, info[0]);
219 LIBBMRM_MEMCPY(A, subgrad_t[0], nDim*
sizeof(
float64_t));
221 cp_list->address=&A[0];
228 for (uint32_t p=1; p<cp_models; ++p)
230 Rt[p] = machine->risk(subgrad_t[p], W, info[p]);
231 b[p]=
CMath::dot(subgrad_t[p], W, nDim) - Rt[p];
232 add_cutting_plane(&CPList_tail, map, A, find_free_idx(map, BufSize), subgrad_t[p], nDim);
238 for (uint32_t p=0; p<cp_models; ++p)
244 for (uint32_t j=0; j<nDim; ++j)
246 sq_norm_Wdiff+=(W[j]-prevW[j])*(W[j]-prevW[j]);
251 p3bmrm.Fp=R+0.5*_lambda*sq_norm_W + alpha*sq_norm_Wdiff;
252 p3bmrm.Fd=-LIBBMRM_PLUS_INF;
256 K = (sq_norm_W == 0.0) ? 0.4 : 0.01*
CMath::sqrt(sq_norm_W);
258 LIBBMRM_MEMCPY(prevW, W, nDim*
sizeof(
float64_t));
260 tstop=ttime.cur_time_diff(
false);
263 p3bmrm.hist_Fp[0]=p3bmrm.Fp;
264 p3bmrm.hist_Fd[0]=p3bmrm.Fd;
265 p3bmrm.hist_wdist[0]=wdist;
269 SG_SDEBUG(
"%4d: tim=%.3lf, Fp=%lf, Fd=%lf, R=%lf, K=%lf, CPmodels=%d\n",
270 p3bmrm.nIter, tstop-tstart, p3bmrm.Fp, p3bmrm.Fd, R, K, cp_models);
273 helper = machine->get_helper();
276 while (p3bmrm.exitflag==0)
278 tstart=ttime.cur_time_diff(
false);
286 for (cp_i=0; cp_i<cp_models; ++cp_i)
288 A_1=get_cutting_plane(cp_ptr);
290 for (uint32_t p=0; p<cp_models; ++p)
294 H[LIBBMRM_INDEX(p, cp_i, BufSize)]=rsum;
304 for (cp_i=0; cp_i<p3bmrm.nCP+cp_models; ++cp_i)
306 A_1=get_cutting_plane(cp_ptr);
308 for (uint32_t p=0; p<cp_models; ++p)
312 H[LIBBMRM_INDEX(p3bmrm.nCP+p, cp_i, BufSize)]=rsum;
318 for (uint32_t i=0; i<p3bmrm.nCP; ++i)
319 for (uint32_t j=0; j<cp_models; ++j)
320 H[LIBBMRM_INDEX(i, p3bmrm.nCP+j, BufSize)]=
321 H[LIBBMRM_INDEX(p3bmrm.nCP+j, i, BufSize)];
324 for (uint32_t p=0; p<cp_models; ++p)
325 diag_H[p3bmrm.nCP+p]=H[LIBBMRM_INDEX(p3bmrm.nCP+p, p3bmrm.nCP+p, BufSize)];
327 p3bmrm.nCP+=cp_models;
332 isThereGoodSolution=
false;
334 for (uint32_t p=0; p<cp_models; ++p)
336 I[p3bmrm.nCP-cp_models+p]=p+1;
337 beta[p3bmrm.nCP-cp_models+p]=0.0;
340 LIBBMRM_MEMCPY(beta_start, beta, p3bmrm.nCP*
sizeof(
float64_t));
341 LIBBMRM_MEMCPY(I_start, I, p3bmrm.nCP*
sizeof(uint32_t));
346 alpha_start=alpha; alpha=0.0;
347 LIBBMRM_MEMCPY(I2, I_start, p3bmrm.nCP*
sizeof(uint32_t));
352 for (uint32_t i=0; i<p3bmrm.nCP; ++i)
354 A_1=get_cutting_plane(cp_ptr);
359 b2[i]=b[i]-((2*alpha)/(_lambda+2*alpha))*rsum;
360 diag_H2[i]=diag_H[i]/(_lambda+2*alpha);
362 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
363 H2[LIBBMRM_INDEX(i, j, BufSize)]=
364 H[LIBBMRM_INDEX(i, j, BufSize)]/(_lambda+2*alpha);
369 qp_exitflag=libqp_splx_solver(&get_col, diag_H2, b2, C, I2, S, beta,
370 p3bmrm.nCP, QPSolverMaxIter, 0.0, QPSolverTolRel, -LIBBMRM_PLUS_INF, 0);
371 p3bmrm.qp_exitflag=qp_exitflag.exitflag;
373 Fd_alpha0=-qp_exitflag.QP;
379 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
381 A_1=get_cutting_plane(cp_ptr);
388 for (uint32_t i=0; i<nDim; ++i)
389 sq_norm_Wdiff+=(wt[i]-prevW[i])*(wt[i]-prevW[i]);
395 if (alpha!=alpha_start)
405 LIBBMRM_MEMCPY(I2, I_start, p3bmrm.nCP*
sizeof(uint32_t));
406 LIBBMRM_MEMCPY(beta, beta_start, p3bmrm.nCP*
sizeof(
float64_t));
411 for (uint32_t i=0; i<p3bmrm.nCP; ++i)
413 A_1=get_cutting_plane(cp_ptr);
418 b2[i]=b[i]-((2*alpha)/(_lambda+2*alpha))*rsum;
419 diag_H2[i]=diag_H[i]/(_lambda+2*alpha);
421 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
422 H2[LIBBMRM_INDEX(i, j, BufSize)]=H[LIBBMRM_INDEX(i, j, BufSize)]/(_lambda+2*alpha);
426 qp_exitflag=libqp_splx_solver(&get_col, diag_H2, b2, C, I2, S, beta,
427 p3bmrm.nCP, QPSolverMaxIter, 0.0, QPSolverTolRel, -LIBBMRM_PLUS_INF, 0);
428 p3bmrm.qp_exitflag=qp_exitflag.exitflag;
435 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
437 A_1=get_cutting_plane(cp_ptr);
444 for (uint32_t i=0; i<nDim; ++i)
445 sq_norm_Wdiff+=(wt[i]-prevW[i])*(wt[i]-prevW[i]);
451 if (isThereGoodSolution)
453 LIBBMRM_MEMCPY(beta, beta_good, p3bmrm.nCP*
sizeof(
float64_t));
454 LIBBMRM_MEMCPY(I2, I_good, p3bmrm.nCP*
sizeof(uint32_t));
456 qp_exitflag=qp_exitflag_good;
478 LIBBMRM_MEMCPY(beta_good, beta, p3bmrm.nCP*
sizeof(
float64_t));
479 LIBBMRM_MEMCPY(I_good, I2, p3bmrm.nCP*
sizeof(uint32_t));
481 qp_exitflag_good=qp_exitflag;
482 isThereGoodSolution=
true;
505 LIBBMRM_MEMCPY(I2, I_start, p3bmrm.nCP*
sizeof(uint32_t));
506 LIBBMRM_MEMCPY(beta, beta_start, p3bmrm.nCP*
sizeof(
float64_t));
511 for (uint32_t i=0; i<p3bmrm.nCP; ++i)
513 A_1=get_cutting_plane(cp_ptr);
518 b2[i]=b[i]-((2*alpha)/(_lambda+2*alpha))*rsum;
519 diag_H2[i]=diag_H[i]/(_lambda+2*alpha);
521 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
522 H2[LIBBMRM_INDEX(i, j, BufSize)]=H[LIBBMRM_INDEX(i, j, BufSize)]/(_lambda+2*alpha);
526 qp_exitflag=libqp_splx_solver(&get_col, diag_H2, b2, C, I2, S, beta,
527 p3bmrm.nCP, QPSolverMaxIter, 0.0, QPSolverTolRel, -LIBBMRM_PLUS_INF, 0);
528 p3bmrm.qp_exitflag=qp_exitflag.exitflag;
536 for (uint32_t aaa=0; aaa<p3bmrm.nCP; ++aaa)
538 if (beta[aaa]>epsilon)
541 icp_stats.ICPcounter[aaa]=0;
545 icp_stats.ICPcounter[aaa]+=1;
553 for (uint32_t j=0; j<p3bmrm.nCP; ++j)
555 A_1=get_cutting_plane(cp_ptr);
563 for (uint32_t p=0; p<cp_models; ++p)
565 Rt[p] = machine->risk(subgrad_t[p], W, info[p]);
566 b[p3bmrm.nCP+p] =
CMath::dot(subgrad_t[p], W, nDim) - Rt[p];
567 add_cutting_plane(&CPList_tail, map, A, find_free_idx(map, BufSize), subgrad_t[p], nDim);
575 for (uint32_t j=0; j<nDim; ++j)
577 sq_norm_Wdiff+=(W[j]-prevW[j])*(W[j]-prevW[j]);
581 p3bmrm.Fp=R+0.5*_lambda*sq_norm_W + alpha*sq_norm_Wdiff;
582 p3bmrm.Fd=-qp_exitflag.QP + ((alpha*_lambda)/(_lambda + 2*alpha))*sq_norm_prevW;
587 eps=1.0-(p3bmrm.Fd/p3bmrm.Fp);
588 gamma=(lastFp*(1-eps)-Fd_alpha0)/(Tmax*(1-eps));
591 if ((lastFp-p3bmrm.Fp) <= gamma)
603 if (p3bmrm.Fp-p3bmrm.Fd<=TolRel*LIBBMRM_ABS(p3bmrm.Fp))
606 if (p3bmrm.Fp-p3bmrm.Fd<=TolAbs)
610 if (p3bmrm.nCP>=BufSize)
613 tstop=ttime.cur_time_diff(
false);
618 for (uint32_t i=0; i<nDim; ++i)
620 sq_norm_Wdiff+=(W[i]-prevW[i])*(W[i]-prevW[i]);
626 p3bmrm.hist_Fp[p3bmrm.nIter]=p3bmrm.Fp;
627 p3bmrm.hist_Fd[p3bmrm.nIter]=p3bmrm.Fd;
628 p3bmrm.hist_wdist[p3bmrm.nIter]=wdist;
632 SG_SDEBUG(
"%4d: tim=%.3lf, Fp=%lf, Fd=%lf, (Fp-Fd)=%lf, (Fp-Fd)/Fp=%lf, R=%lf, nCP=%d, nzA=%d, wdist=%lf, alpha=%lf, qp_cnt=%d, gamma=%lf, tuneAlpha=%d\n",
633 p3bmrm.nIter, tstop-tstart, p3bmrm.Fp, p3bmrm.Fd, p3bmrm.Fp-p3bmrm.Fd,
634 (p3bmrm.Fp-p3bmrm.Fd)/p3bmrm.Fp, R, p3bmrm.nCP, p3bmrm.nzA, wdist, alpha,
635 qp_cnt, gamma, tuneAlpha);
638 if (p3bmrm.nCP>=BufSize)
645 LIBBMRM_MEMCPY(prevW, W, nDim*
sizeof(
float64_t));
651 clean_icp(&icp_stats, p3bmrm, &CPList_head,
652 &CPList_tail, H, diag_H, beta, map,
653 cleanAfter, b, I, cp_models);
657 if (p3bmrm.nCP+1 >= BufSize)
663 SGVector<float64_t> w_debug(W, nDim,
false);
666 helper->add_debug_info(primal, p3bmrm.nIter, train_error);
676 p3bmrm.hist_Fp.resize_vector(p3bmrm.nIter);
677 p3bmrm.hist_Fd.resize_vector(p3bmrm.nIter);
678 p3bmrm.hist_wdist.resize_vector(p3bmrm.nIter);
686 LIBBMRM_FREE(cp_ptr2);
698 LIBBMRM_FREE(diag_H);
700 LIBBMRM_FREE(icp_stats.ICPcounter);
701 LIBBMRM_FREE(icp_stats.ICPs);
702 LIBBMRM_FREE(icp_stats.ACPs);
703 LIBBMRM_FREE(icp_stats.H_buff);
707 LIBBMRM_FREE(beta_start);
708 LIBBMRM_FREE(beta_good);
709 LIBBMRM_FREE(I_start);
710 LIBBMRM_FREE(I_good);
713 LIBBMRM_FREE(diag_H2);
720 LIBBMRM_FREE(cp_list);
722 for (uint32_t p=0; p<cp_models; ++p)
724 LIBBMRM_FREE(subgrad_t[p]);
725 LIBBMRM_FREE(info[p]);
728 LIBBMRM_FREE(subgrad_t);
736 #endif //USE_GPL_SHOGUN
static float64_t primal_objective(SGVector< float64_t > w, CStructuredModel *model, float64_t lbda)
static float64_t dot(const bool *v1, const bool *v2, int32_t n)
Compute dot product between v1 and v2 (blas optimized)
static float64_t average_loss(SGVector< float64_t > w, CStructuredModel *model, bool is_ub=false)
static void vec1_plus_scalar_times_vec2(T *vec1, const T scalar, const T *vec2, int32_t n)
x=x+alpha*y
all of classes and functions are contained in the shogun namespace
static float32_t sqrt(float32_t x)