SHOGUN
v1.1.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Written (W) 2007-2009 Soeren Sonnenburg 00008 * Written (W) 2007-2008 Vojtech Franc 00009 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 */ 00011 00012 #include <shogun/lib/config.h> 00013 00014 #ifdef USE_CPLEX 00015 00016 #include <shogun/mathematics/Math.h> 00017 #include <shogun/lib/Signal.h> 00018 #include <shogun/lib/Time.h> 00019 #include <shogun/machine/LinearMachine.h> 00020 #include <shogun/classifier/SubGradientLPM.h> 00021 #include <shogun/classifier/svm/qpbsvmlib.h> 00022 #include <shogun/features/DotFeatures.h> 00023 #include <shogun/features/Labels.h> 00024 00025 using namespace shogun; 00026 00027 #define DEBUG_SUBGRADIENTLPM 00028 00029 CSubGradientLPM::CSubGradientLPM() 00030 : CLinearClassifier(), C1(1), C2(1), epsilon(1e-5), qpsize(42), 00031 qpsize_max(2000), use_bias(false), delta_active(0), delta_bound(0) 00032 { 00033 } 00034 00035 CSubGradientLPM::CSubGradientLPM( 00036 float64_t C, CDotFeatures* traindat, CLabels* trainlab) 00037 : CLinearClassifier(), C1(C), C2(C), epsilon(1e-5), qpsize(42), 00038 qpsize_max(2000), use_bias(false), delta_active(0), delta_bound(0) 00039 { 00040 CLinearClassifier::features=traindat; 00041 CClassifier::labels=trainlab; 00042 } 00043 00044 00045 CSubGradientLPM::~CSubGradientLPM() 00046 { 00047 cleanup(); 00048 } 00049 00050 int32_t CSubGradientLPM::find_active( 00051 int32_t num_feat, int32_t num_vec, int32_t& num_active, int32_t& num_bound) 00052 { 00053 //delta_active=0; 00054 //num_active=0; 00055 //num_bound=0; 00056 00057 //for (int32_t i=0; i<num_vec; i++) 00058 //{ 00059 // active[i]=0; 00060 00061 // //within margin/wrong side 00062 // if (proj[i] < 1-work_epsilon) 00063 // { 00064 // idx_active[num_active++]=i; 00065 // active[i]=1; 00066 // } 00067 00068 // //on margin 00069 // if (CMath::abs(proj[i]-1) <= work_epsilon) 00070 // { 00071 // idx_bound[num_bound++]=i; 00072 // active[i]=2; 00073 // } 00074 00075 // if (active[i]!=old_active[i]) 00076 // delta_active++; 00077 //} 00078 00079 delta_bound=0; 00080 delta_active=0; 00081 num_active=0; 00082 num_bound=0; 00083 00084 for (int32_t i=0; i<num_vec; i++) 00085 { 00086 active[i]=0; 00087 00088 //within margin/wrong side 00089 if (proj[i] < 1-autoselected_epsilon) 00090 { 00091 idx_active[num_active++]=i; 00092 active[i]=1; 00093 } 00094 00095 //on margin 00096 if (CMath::abs(proj[i]-1) <= autoselected_epsilon) 00097 { 00098 idx_bound[num_bound++]=i; 00099 active[i]=2; 00100 } 00101 00102 if (active[i]!=old_active[i]) 00103 delta_active++; 00104 00105 if (active[i]==2 && old_active[i]==2) 00106 delta_bound++; 00107 } 00108 00109 00110 if (delta_active==0 && work_epsilon<=epsilon) //we converged 00111 return 0; 00112 else if (delta_active==0) //lets decrease work_epsilon 00113 { 00114 work_epsilon=CMath::min(work_epsilon/2, autoselected_epsilon); 00115 work_epsilon=CMath::max(work_epsilon, epsilon); 00116 num_bound=qpsize; 00117 } 00118 00119 delta_bound=0; 00120 delta_active=0; 00121 num_active=0; 00122 num_bound=0; 00123 00124 for (int32_t i=0; i<num_vec; i++) 00125 { 00126 tmp_proj[i]=CMath::abs(proj[i]-1); 00127 tmp_proj_idx[i]=i; 00128 } 00129 00130 CMath::qsort_index(tmp_proj, tmp_proj_idx, num_vec); 00131 00132 autoselected_epsilon=tmp_proj[CMath::min(qpsize,num_vec)]; 00133 00134 #ifdef DEBUG_SUBGRADIENTSVM 00135 //SG_PRINT("autoseleps: %15.15f\n", autoselected_epsilon); 00136 #endif 00137 00138 if (autoselected_epsilon>work_epsilon) 00139 autoselected_epsilon=work_epsilon; 00140 00141 if (autoselected_epsilon<epsilon) 00142 { 00143 autoselected_epsilon=epsilon; 00144 00145 int32_t i=0; 00146 while (i < num_vec && tmp_proj[i] <= autoselected_epsilon) 00147 i++; 00148 00149 //SG_PRINT("lower bound on epsilon requires %d variables in qp\n", i); 00150 00151 if (i>=qpsize_max && autoselected_epsilon>epsilon) //qpsize limit 00152 { 00153 SG_PRINT("qpsize limit (%d) reached\n", qpsize_max); 00154 int32_t num_in_qp=i; 00155 while (--i>=0 && num_in_qp>=qpsize_max) 00156 { 00157 if (tmp_proj[i] < autoselected_epsilon) 00158 { 00159 autoselected_epsilon=tmp_proj[i]; 00160 num_in_qp--; 00161 } 00162 } 00163 00164 //SG_PRINT("new qpsize will be %d, autoeps:%15.15f\n", num_in_qp, autoselected_epsilon); 00165 } 00166 } 00167 00168 for (int32_t i=0; i<num_vec; i++) 00169 { 00170 active[i]=0; 00171 00172 //within margin/wrong side 00173 if (proj[i] < 1-autoselected_epsilon) 00174 { 00175 idx_active[num_active++]=i; 00176 active[i]=1; 00177 } 00178 00179 //on margin 00180 if (CMath::abs(proj[i]-1) <= autoselected_epsilon) 00181 { 00182 idx_bound[num_bound++]=i; 00183 active[i]=2; 00184 } 00185 00186 if (active[i]!=old_active[i]) 00187 delta_active++; 00188 00189 if (active[i]==2 && old_active[i]==2) 00190 delta_bound++; 00191 } 00192 00193 pos_idx=0; 00194 neg_idx=0; 00195 zero_idx=0; 00196 00197 for (int32_t i=0; i<num_feat; i++) 00198 { 00199 if (w[i]>work_epsilon) 00200 { 00201 w_pos[pos_idx++]=i; 00202 grad_w[i]=1; 00203 } 00204 else if (w[i]<-work_epsilon) 00205 { 00206 w_neg[neg_idx++]=i; 00207 grad_w[i]=-1; 00208 } 00209 00210 if (CMath::abs(w[i])<=work_epsilon) 00211 { 00212 w_zero[zero_idx++]=i; 00213 grad_w[i]=-1; 00214 } 00215 } 00216 00217 return delta_active; 00218 } 00219 00220 00221 void CSubGradientLPM::update_active(int32_t num_feat, int32_t num_vec) 00222 { 00223 for (int32_t i=0; i<num_vec; i++) 00224 { 00225 if (active[i]==1 && old_active[i]!=1) 00226 { 00227 features->add_to_dense_vec(C1*get_label(i), i, sum_CXy_active, num_feat); 00228 if (use_bias) 00229 sum_Cy_active+=C1*get_label(i); 00230 } 00231 else if (old_active[i]==1 && active[i]!=1) 00232 { 00233 features->add_to_dense_vec(-C1*get_label(i), i, sum_CXy_active, num_feat); 00234 if (use_bias) 00235 sum_Cy_active-=C1*get_label(i); 00236 } 00237 } 00238 00239 CMath::swap(active,old_active); 00240 } 00241 00242 float64_t CSubGradientLPM::line_search(int32_t num_feat, int32_t num_vec) 00243 { 00244 int32_t num_hinge=0; 00245 float64_t alpha=0; 00246 float64_t sgrad=0; 00247 00248 float64_t* A=SG_MALLOC(float64_t, num_feat+num_vec); 00249 float64_t* B=SG_MALLOC(float64_t, num_feat+num_vec); 00250 float64_t* C=SG_MALLOC(float64_t, num_feat+num_vec); 00251 float64_t* D=SG_MALLOC(float64_t, num_feat+num_vec); 00252 00253 for (int32_t i=0; i<num_feat+num_vec; i++) 00254 { 00255 if (i<num_feat) 00256 { 00257 A[i]=-grad_w[i]; 00258 B[i]=w[i]; 00259 C[i]=+grad_w[i]; 00260 D[i]=-w[i]; 00261 } 00262 else 00263 { 00264 float64_t p=get_label(i-num_feat)*(features->dense_dot(i-num_feat, grad_w, num_feat)+grad_b); 00265 grad_proj[i-num_feat]=p; 00266 00267 A[i]=0; 00268 B[i]=0; 00269 C[i]=C1*p; 00270 D[i]=C1*(1-proj[i-num_feat]); 00271 } 00272 00273 if (A[i]==C[i] && B[i]>D[i]) 00274 sgrad+=A[i]+C[i]; 00275 else if (A[i]==C[i] && B[i]==D[i]) 00276 sgrad+=CMath::max(A[i],C[i]); 00277 else if (A[i]!=C[i]) 00278 { 00279 hinge_point[num_hinge]=(D[i]-B[i])/(A[i]-C[i]); 00280 hinge_idx[num_hinge]=i; // index into A,B,C,D arrays 00281 num_hinge++; 00282 00283 if (A[i]>C[i]) 00284 sgrad+=C[i]; 00285 if (A[i]<C[i]) 00286 sgrad+=A[i]; 00287 } 00288 } 00289 00290 //SG_PRINT("sgrad:%f\n", sgrad); 00291 //CMath::display_vector(A, num_feat+num_vec, "A"); 00292 //CMath::display_vector(B, num_feat+num_vec, "B"); 00293 //CMath::display_vector(C, num_feat+num_vec, "C"); 00294 //CMath::display_vector(D, num_feat+num_vec, "D"); 00295 //CMath::display_vector(hinge_point, num_feat+num_vec, "hinge_point"); 00296 //CMath::display_vector(hinge_idx, num_feat+num_vec, "hinge_idx"); 00297 //ASSERT(0); 00298 00299 CMath::qsort_index(hinge_point, hinge_idx, num_hinge); 00300 //CMath::display_vector(hinge_point, num_feat+num_vec, "hinge_point_sorted"); 00301 00302 00303 int32_t i=-1; 00304 while (i < num_hinge-1 && sgrad < 0) 00305 { 00306 i+=1; 00307 00308 if (A[hinge_idx[i]] > C[hinge_idx[i]]) 00309 sgrad += A[hinge_idx[i]] - C[hinge_idx[i]]; 00310 else 00311 sgrad += C[hinge_idx[i]] - A[hinge_idx[i]]; 00312 } 00313 00314 alpha = hinge_point[i]; 00315 00316 SG_FREE(D); 00317 SG_FREE(C); 00318 SG_FREE(B); 00319 SG_FREE(A); 00320 00321 //SG_PRINT("alpha=%f\n", alpha); 00322 return alpha; 00323 } 00324 00325 float64_t CSubGradientLPM::compute_min_subgradient( 00326 int32_t num_feat, int32_t num_vec, int32_t num_active, int32_t num_bound) 00327 { 00328 float64_t dir_deriv=0; 00329 solver->init(E_QP); 00330 00331 if (zero_idx+num_bound > 0) 00332 { 00333 //SG_PRINT("num_var:%d (zero:%d, bound:%d) num_feat:%d\n", zero_idx+num_bound, zero_idx,num_bound, num_feat); 00334 //CMath::display_vector(grad_w, num_feat+1, "grad_w"); 00335 CMath::add(grad_w, 1.0, grad_w, -1.0, sum_CXy_active, num_feat); 00336 grad_w[num_feat]= -sum_Cy_active; 00337 00338 grad_b = -sum_Cy_active; 00339 00340 //CMath::display_vector(sum_CXy_active, num_feat, "sum_CXy_active"); 00341 //SG_PRINT("sum_Cy_active=%10.10f\n", sum_Cy_active); 00342 00343 //CMath::display_vector(grad_w, num_feat+1, "grad_w"); 00344 00345 solver->setup_subgradientlpm_QP(C1, labels, (CSparseFeatures<float64_t>*) features, idx_bound, num_bound, 00346 w_zero, zero_idx, 00347 grad_w, num_feat+1, 00348 use_bias); 00349 00350 solver->optimize(beta); 00351 //CMath::display_vector(beta, num_feat+1, "v"); 00352 00353 //compute dir_deriv here, variable grad_w constains still 'v' and beta 00354 //contains the future gradient 00355 dir_deriv = CMath::dot(beta, grad_w, num_feat); 00356 dir_deriv-=beta[num_feat]*sum_Cy_active; 00357 00358 for (int32_t i=0; i<num_bound; i++) 00359 { 00360 float64_t val= C1*get_label(idx_bound[i])*(features->dense_dot(idx_bound[i], beta, num_feat)+ beta[num_feat]); 00361 dir_deriv += CMath::max(0.0, val); 00362 } 00363 00364 for (int32_t i=0; i<num_feat; i++) 00365 grad_w[i]=beta[i]; 00366 00367 if (use_bias) 00368 grad_b=beta[num_feat]; 00369 00370 //for (int32_t i=0; i<zero_idx+num_bound; i++) 00371 // beta[i]=beta[i+num_feat+1]; 00372 00373 //CMath::display_vector(beta, zero_idx+num_bound, "beta"); 00374 //SG_PRINT("beta[0]=%10.16f\n", beta[0]); 00375 //ASSERT(0); 00376 00377 //for (int32_t i=0; i<zero_idx+num_bound; i++) 00378 //{ 00379 // if (i<zero_idx) 00380 // grad_w[w_zero[i]]+=beta[w_zero[i]]; 00381 // else 00382 // { 00383 // features->add_to_dense_vec(-C1*beta[i]*get_label(idx_bound[i-zero_idx]), idx_bound[i-zero_idx], grad_w, num_feat); 00384 // if (use_bias) 00385 // grad_b -= C1 * get_label(idx_bound[i-zero_idx])*beta[i-zero_idx]; 00386 // } 00387 //} 00388 00389 //CMath::display_vector(w_zero, zero_idx, "w_zero"); 00390 //CMath::display_vector(grad_w, num_feat, "grad_w"); 00391 //SG_PRINT("grad_b=%f\n", grad_b); 00392 // 00393 } 00394 else 00395 { 00396 CMath::add(grad_w, 1.0, w, -1.0, sum_CXy_active, num_feat); 00397 grad_b = -sum_Cy_active; 00398 00399 dir_deriv = CMath::dot(grad_w, grad_w, num_feat)+ grad_b*grad_b; 00400 } 00401 00402 solver->cleanup(); 00403 00404 00405 //SG_PRINT("Gradient : |subgrad_W|^2=%f, |subgrad_b|^2=%f\n", 00406 // CMath::dot(grad_w, grad_w, num_feat), grad_b*grad_b); 00407 00408 return dir_deriv; 00409 } 00410 00411 float64_t CSubGradientLPM::compute_objective(int32_t num_feat, int32_t num_vec) 00412 { 00413 float64_t result= CMath::sum_abs(w, num_feat); 00414 00415 for (int32_t i=0; i<num_vec; i++) 00416 { 00417 if (proj[i]<1.0) 00418 result += C1 * (1.0-proj[i]); 00419 } 00420 00421 return result; 00422 } 00423 00424 void CSubGradientLPM::compute_projection(int32_t num_feat, int32_t num_vec) 00425 { 00426 for (int32_t i=0; i<num_vec; i++) 00427 proj[i]=get_label(i)*(features->dense_dot(i, w, num_feat) + bias); 00428 } 00429 00430 void CSubGradientLPM::update_projection(float64_t alpha, int32_t num_vec) 00431 { 00432 CMath::vec1_plus_scalar_times_vec2(proj,-alpha, grad_proj, num_vec); 00433 } 00434 00435 void CSubGradientLPM::init(int32_t num_vec, int32_t num_feat) 00436 { 00437 // alloc normal and bias inited with 0 00438 SG_FREE(w); 00439 w=SG_MALLOC(float64_t, num_feat); 00440 w_dim=num_feat; 00441 for (int32_t i=0; i<num_feat; i++) 00442 w[i]=1.0; 00443 //CMath::random_vector(w, num_feat, -1.0, 1.0); 00444 bias=0; 00445 num_it_noimprovement=0; 00446 grad_b=0; 00447 00448 w_pos=SG_MALLOC(int32_t, num_feat); 00449 memset(w_pos,0,sizeof(int32_t)*num_feat); 00450 00451 w_zero=SG_MALLOC(int32_t, num_feat); 00452 memset(w_zero,0,sizeof(int32_t)*num_feat); 00453 00454 w_neg=SG_MALLOC(int32_t, num_feat); 00455 memset(w_neg,0,sizeof(int32_t)*num_feat); 00456 00457 grad_w=SG_MALLOC(float64_t, num_feat+1); 00458 memset(grad_w,0,sizeof(float64_t)*(num_feat+1)); 00459 00460 sum_CXy_active=SG_MALLOC(float64_t, num_feat); 00461 memset(sum_CXy_active,0,sizeof(float64_t)*num_feat); 00462 00463 sum_Cy_active=0; 00464 00465 proj=SG_MALLOC(float64_t, num_vec); 00466 memset(proj,0,sizeof(float64_t)*num_vec); 00467 00468 tmp_proj=SG_MALLOC(float64_t, num_vec); 00469 memset(proj,0,sizeof(float64_t)*num_vec); 00470 00471 tmp_proj_idx=SG_MALLOC(int32_t, num_vec); 00472 memset(tmp_proj_idx,0,sizeof(int32_t)*num_vec); 00473 00474 grad_proj=SG_MALLOC(float64_t, num_vec); 00475 memset(grad_proj,0,sizeof(float64_t)*num_vec); 00476 00477 hinge_point=SG_MALLOC(float64_t, num_vec+num_feat); 00478 memset(hinge_point,0,sizeof(float64_t)*(num_vec+num_feat)); 00479 00480 hinge_idx=SG_MALLOC(int32_t, num_vec+num_feat); 00481 memset(hinge_idx,0,sizeof(int32_t)*(num_vec+num_feat)); 00482 00483 active=SG_MALLOC(uint8_t, num_vec); 00484 memset(active,0,sizeof(uint8_t)*num_vec); 00485 00486 old_active=SG_MALLOC(uint8_t, num_vec); 00487 memset(old_active,0,sizeof(uint8_t)*num_vec); 00488 00489 idx_bound=SG_MALLOC(int32_t, num_vec); 00490 memset(idx_bound,0,sizeof(int32_t)*num_vec); 00491 00492 idx_active=SG_MALLOC(int32_t, num_vec); 00493 memset(idx_active,0,sizeof(int32_t)*num_vec); 00494 00495 beta=SG_MALLOC(float64_t, num_feat+1+num_feat+num_vec); 00496 memset(beta,0,sizeof(float64_t)*num_feat+1+num_feat+num_vec); 00497 00498 solver=new CCplex(); 00499 } 00500 00501 void CSubGradientLPM::cleanup() 00502 { 00503 SG_FREE(hinge_idx); 00504 SG_FREE(hinge_point); 00505 SG_FREE(grad_proj); 00506 SG_FREE(proj); 00507 SG_FREE(tmp_proj); 00508 SG_FREE(tmp_proj_idx); 00509 SG_FREE(active); 00510 SG_FREE(old_active); 00511 SG_FREE(idx_bound); 00512 SG_FREE(idx_active); 00513 SG_FREE(sum_CXy_active); 00514 SG_FREE(w_pos); 00515 SG_FREE(w_zero); 00516 SG_FREE(w_neg); 00517 SG_FREE(grad_w); 00518 SG_FREE(beta); 00519 00520 hinge_idx=NULL; 00521 hinge_point=NULL; 00522 grad_proj=NULL; 00523 proj=NULL; 00524 tmp_proj=NULL; 00525 tmp_proj_idx=NULL; 00526 active=NULL; 00527 old_active=NULL; 00528 idx_bound=NULL; 00529 idx_active=NULL; 00530 sum_CXy_active=NULL; 00531 w_pos=NULL; 00532 w_zero=NULL; 00533 w_neg=NULL; 00534 grad_w=NULL; 00535 beta=NULL; 00536 00537 delete solver; 00538 solver=NULL; 00539 } 00540 00541 bool CSubGradientLPM::train_machine(CFeatures* data) 00542 { 00543 lpmtim=0; 00544 SG_INFO("C=%f epsilon=%f\n", C1, epsilon); 00545 ASSERT(labels); 00546 if (data) 00547 { 00548 if (!data->has_property(FP_DOT)) 00549 SG_ERROR("Specified features are not of type CDotFeatures\n"); 00550 set_features((CDotFeatures*) data); 00551 } 00552 ASSERT(features); 00553 00554 int32_t num_iterations=0; 00555 int32_t num_train_labels=labels->get_num_labels(); 00556 int32_t num_feat=features->get_dim_feature_space(); 00557 int32_t num_vec=features->get_num_vectors(); 00558 00559 ASSERT(num_vec==num_train_labels); 00560 00561 init(num_vec, num_feat); 00562 00563 int32_t num_active=0; 00564 int32_t num_bound=0; 00565 float64_t alpha=0; 00566 float64_t dir_deriv=0; 00567 float64_t obj=0; 00568 delta_active=num_vec; 00569 last_it_noimprovement=-1; 00570 00571 work_epsilon=0.99; 00572 autoselected_epsilon=work_epsilon; 00573 00574 compute_projection(num_feat, num_vec); 00575 00576 CTime time; 00577 float64_t loop_time=0; 00578 while (!(CSignal::cancel_computations())) 00579 { 00580 CTime t; 00581 delta_active=find_active(num_feat, num_vec, num_active, num_bound); 00582 00583 update_active(num_feat, num_vec); 00584 00585 #ifdef DEBUG_SUBGRADIENTLPM 00586 SG_PRINT("==================================================\niteration: %d ", num_iterations); 00587 obj=compute_objective(num_feat, num_vec); 00588 SG_PRINT("objective:%.10f alpha: %.10f dir_deriv: %f num_bound: %d num_active: %d work_eps: %10.10f eps: %10.10f auto_eps: %10.10f time:%f\n", 00589 obj, alpha, dir_deriv, num_bound, num_active, work_epsilon, epsilon, autoselected_epsilon, loop_time); 00590 #else 00591 SG_ABS_PROGRESS(work_epsilon, -CMath::log10(work_epsilon), -CMath::log10(0.99999999), -CMath::log10(epsilon), 6); 00592 #endif 00593 //CMath::display_vector(w, w_dim, "w"); 00594 //SG_PRINT("bias: %f\n", bias); 00595 //CMath::display_vector(proj, num_vec, "proj"); 00596 //CMath::display_vector(idx_active, num_active, "idx_active"); 00597 //SG_PRINT("num_active: %d\n", num_active); 00598 //CMath::display_vector(idx_bound, num_bound, "idx_bound"); 00599 //SG_PRINT("num_bound: %d\n", num_bound); 00600 //CMath::display_vector(sum_CXy_active, num_feat, "sum_CXy_active"); 00601 //SG_PRINT("sum_Cy_active: %f\n", sum_Cy_active); 00602 //CMath::display_vector(grad_w, num_feat, "grad_w"); 00603 //SG_PRINT("grad_b:%f\n", grad_b); 00604 00605 dir_deriv=compute_min_subgradient(num_feat, num_vec, num_active, num_bound); 00606 00607 alpha=line_search(num_feat, num_vec); 00608 00609 if (num_it_noimprovement==10 || num_bound<qpsize_max) 00610 { 00611 float64_t norm_grad=CMath::dot(grad_w, grad_w, num_feat) + 00612 grad_b*grad_b; 00613 00614 SG_PRINT("CHECKING OPTIMALITY CONDITIONS: " 00615 "work_epsilon: %10.10f delta_active:%d alpha: %10.10f norm_grad: %10.10f a*norm_grad:%10.16f\n", 00616 work_epsilon, delta_active, alpha, norm_grad, CMath::abs(alpha*norm_grad)); 00617 00618 if (work_epsilon<=epsilon && delta_active==0 && CMath::abs(alpha*norm_grad)<1e-6) 00619 break; 00620 else 00621 num_it_noimprovement=0; 00622 } 00623 00624 //if (work_epsilon<=epsilon && delta_active==0 && num_it_noimprovement) 00625 if ((dir_deriv<0 || alpha==0) && (work_epsilon<=epsilon && delta_active==0)) 00626 { 00627 if (last_it_noimprovement==num_iterations-1) 00628 { 00629 SG_PRINT("no improvement...\n"); 00630 num_it_noimprovement++; 00631 } 00632 else 00633 num_it_noimprovement=0; 00634 00635 last_it_noimprovement=num_iterations; 00636 } 00637 00638 CMath::vec1_plus_scalar_times_vec2(w, -alpha, grad_w, num_feat); 00639 bias-=alpha*grad_b; 00640 00641 update_projection(alpha, num_vec); 00642 00643 t.stop(); 00644 loop_time=t.time_diff_sec(); 00645 num_iterations++; 00646 00647 if (get_max_train_time()>0 && time.cur_time_diff()>get_max_train_time()) 00648 break; 00649 } 00650 00651 SG_INFO("converged after %d iterations\n", num_iterations); 00652 00653 obj=compute_objective(num_feat, num_vec); 00654 SG_INFO("objective: %f alpha: %f dir_deriv: %f num_bound: %d num_active: %d\n", 00655 obj, alpha, dir_deriv, num_bound, num_active); 00656 00657 #ifdef DEBUG_SUBGRADIENTLPM 00658 CMath::display_vector(w, w_dim, "w"); 00659 SG_PRINT("bias: %f\n", bias); 00660 #endif 00661 SG_PRINT("solver time:%f s\n", lpmtim); 00662 00663 cleanup(); 00664 00665 return true; 00666 } 00667 #endif //USE_CPLEX