Index: linear.cpp =================================================================== --- linear.cpp (.../liblinear-1.32/linear.cpp) (revision 239) +++ linear.cpp (.../src/liblinear-1.32/linear.cpp) (working copy) @@ -3,6 +3,49 @@ #include #include #include + +#include +#include +#include +#inlcude + + +#include "handler.h" + +// new: signalhandling for aborting calculations +int canceled = 0; + +#ifdef _WIN32 +#include + +BOOL WINAPI CtrlHandler( DWORD fdwCtrlType ) +{ + fflush(stdout); + canceled = 1; + return TRUE ; +} + +void setup_handler() +{ + canceled = 0; + SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ); +} + +#else +#include + +void sig_die(int ignore__) { canceled = 1; }; + +void setup_handler() +{ + canceled = 0; + signal(SIGINT, sig_die); + signal(SIGTERM, sig_die); + signal(SIGABRT, sig_die); +} + +#endif + #include "linear.h" #include "tron.h" typedef signed char schar; @@ -21,6 +64,10 @@ #define Malloc(type,n) (type *)malloc((n)*sizeof(type)) #define INF HUGE_VAL + + + + #if 1 void info(const char *fmt,...) { @@ -391,7 +438,7 @@ public: Solver_MCSVM_CS(const problem *prob, int nr_class, double *C, double eps=0.1, int max_iter=100000); ~Solver_MCSVM_CS(); - void Solve(double *w); + int Solve(double *w, int verbose); private: void solve_sub_problem(double A_i, int yi, double C_yi, int active_i, double *alpha_new); bool be_shrunken(int m, int yi, double alpha_i, double minG); @@ -466,7 +513,7 @@ return false; } -void Solver_MCSVM_CS::Solve(double *w) +int Solver_MCSVM_CS::Solve(double *w, int verbose) { int i, m, s; int iter = 0; @@ -502,9 +549,13 @@ y_index[i] = prob->y[i]; index[i] = i; } + + setup_handler(); while(iter < max_iter) { + if (canceled) break; + double stopping = -INF; for(i=0;i= max_iter) - info("Warning: reaching max number of iterations\n"); + if (verbose) + { + if (canceled) + info("\nCANCELED !"); + info("\noptimization finished, #iter = %d\n",iter); + if (iter >= max_iter) + info("Warning: reaching max number of iterations\n"); + } + // calculate objective value double v = 0; int nSV = 0; @@ -654,8 +711,10 @@ } for(i=0;iy[i]]; - info("Objective value = %lf\n",v); - info("nSV = %d\n",nSV); + if (verbose) { + info("Objective value = %lf\n",v); + info("nSV = %d\n",nSV); + } delete [] alpha; delete [] alpha_new; @@ -666,6 +725,8 @@ delete [] alpha_index; delete [] y_index; delete [] active_size_i; + + return canceled; } // A coordinate descent algorithm for @@ -692,9 +753,9 @@ // // solution will be put in w -static void solve_linear_c_svc( +static int solve_linear_c_svc( const problem *prob, double *w, double eps, - double Cp, double Cn, int solver_type) + double Cp, double Cn, int solver_type, int verbose) { int l = prob->l; int n = prob->n; @@ -747,8 +808,10 @@ index[i] = i; } + setup_handler(); while (iter < max_iter) { + if (canceled) break; PGmax_new = -INF; PGmin_new = INF; @@ -829,7 +892,7 @@ } iter++; - if(iter % 10 == 0) + if(iter % 10 == 0 && verbose) { info("."); info_flush(); @@ -842,7 +905,7 @@ else { active_size = l; - info("*"); info_flush(); + if (verbose) { info("*"); info_flush(); } PGmax_old = INF; PGmin_old = -INF; continue; @@ -856,9 +919,12 @@ PGmin_old = -INF; } - info("\noptimization finished, #iter = %d\n",iter); - if (iter >= max_iter) + if (verbose) { + if (canceled) info("\nCANCELED"); + info("\noptimization finished, #iter = %d\n",iter); + if (iter >= max_iter) info("Warning: reaching max number of iterations\n"); + } // calculate objective value @@ -875,13 +941,16 @@ if(alpha[i] > 0) ++nSV; } - info("Objective value = %lf\n",v/2); - info("nSV = %d\n",nSV); + if (verbose) { + info("Objective value = %lf\n",v/2); + info("nSV = %d\n",nSV); + } delete [] QD; delete [] alpha; delete [] y; delete [] index; + return canceled; } // label: label name, start: begin of each class, count: #data of classes, perm: indices to the original data @@ -943,7 +1012,7 @@ free(data_label); } -void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn) +void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn, int verbose) { double eps=param->eps; int pos = 0; @@ -959,7 +1028,7 @@ case L2_LR: { fun_obj=new l2_lr_fun(prob, Cp, Cn); - TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l); + TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l, 1000, verbose); tron_obj.tron(w); delete fun_obj; break; @@ -967,16 +1036,16 @@ case L2LOSS_SVM: { fun_obj=new l2loss_svm_fun(prob, Cp, Cn); - TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l); + TRON tron_obj(fun_obj, eps*min(pos,neg)/prob->l, 1000, verbose); tron_obj.tron(w); delete fun_obj; break; } case L2LOSS_SVM_DUAL: - solve_linear_c_svc(prob, w, eps, Cp, Cn, L2LOSS_SVM_DUAL); - break; + solve_linear_c_svc(prob, w, eps, Cp, Cn, L2LOSS_SVM_DUAL, verbose); + break; case L1LOSS_SVM_DUAL: - solve_linear_c_svc(prob, w, eps, Cp, Cn, L1LOSS_SVM_DUAL); + solve_linear_c_svc(prob, w, eps, Cp, Cn, L1LOSS_SVM_DUAL, verbose); break; default: fprintf(stderr, "Error: unknown solver_type\n"); @@ -987,8 +1056,9 @@ // // Interface functions // -model* train(const problem *prob, const parameter *param) +model* train(const problem *prob, const parameter *param, int verbose) { + int i,j; int l = prob->l; int n = prob->n; @@ -1053,7 +1123,7 @@ for(j=start[i];jeps); - Solver.Solve(model_->w); + Solver.Solve(model_->w, verbose); } else { @@ -1068,7 +1138,7 @@ for(; kw[0], weighted_C[0], weighted_C[1]); + train_one(&sub_prob, param, &model_->w[0], weighted_C[0], weighted_C[1], verbose); } else { @@ -1087,7 +1157,7 @@ for(; kC); + train_one(&sub_prob, param, w, weighted_C[i], param->C, verbose); for(int j=0;jw[j*nr_class+i] = w[j]; @@ -1122,7 +1192,7 @@ "L2_LR", "L2LOSS_SVM_DUAL", "L2LOSS_SVM","L1LOSS_SVM_DUAL","MCSVM_CS", NULL }; -int save_model(const char *model_file_name, const struct model *model_) +int to_stream( std::ostream &os, const struct model *model_) { int i; int nr_feature=model_->nr_feature; @@ -1133,44 +1203,67 @@ n=nr_feature+1; else n=nr_feature; - FILE *fp = fopen(model_file_name,"w"); - if(fp==NULL) return -1; - + int nr_w; if(model_->nr_class==2 && model_->param.solver_type != MCSVM_CS) nr_w=1; else nr_w=model_->nr_class; - fprintf(fp, "solver_type %s\n", solver_type_table[param.solver_type]); - fprintf(fp, "nr_class %d\n", model_->nr_class); - fprintf(fp, "label"); + os << "solver_type " << solver_type_table[param.solver_type] << std::endl; + + os << "nr_class " << model_->nr_class << std::endl; + os << "label "; + for(i=0; inr_class; i++) - fprintf(fp, " %d", model_->label[i]); - fprintf(fp, "\n"); + os << model_->label[i] << " "; + os << std::endl; - fprintf(fp, "nr_feature %d\n", nr_feature); + os << "nr_feature " << nr_feature << std::endl; + + os << std::setprecision(16); + os << "bias " << model_->bias << std::endl; - fprintf(fp, "bias %.16g\n", model_->bias); - - fprintf(fp, "w\n"); + os << "w " << std::endl; + for(i=0; iw[i*nr_w+j]); - fprintf(fp, "\n"); + os << model_->w[i*nr_w+j]<<" "; + + os << std::endl; } + os << std::endl ; + return os.fail(); + +} - if (ferror(fp) != 0 || fclose(fp) != 0) return -1; - else return 0; +char * to_string(const struct model *model_) +{ + std::stringstream ss; + + if (!to_stream(ss, model_)) + return NULL; + + const char * res = ss.str().c_str(); + + int len = strlen(res); + char * rv = (char *) malloc((len+1)*sizeof(char)); + strncpy(rv, res, len); + return rv; } -struct model *load_model(const char *model_file_name) + +int save_model(const char *model_file_name, const struct model *model_) { - FILE *fp = fopen(model_file_name,"r"); - if(fp==NULL) return NULL; + std::ofstream os = std::ofstream(model_file_name); + return to_stream(os, model_); +} + +struct model *from_stream(std::istream &is) +{ int i; int nr_feature; int n; @@ -1181,13 +1274,14 @@ model_->label = NULL; - char cmd[81]; + char cmd[1000]; while(1) { - fscanf(fp,"%80s",cmd); + is >> cmd; + if(strcmp(cmd,"solver_type")==0) { - fscanf(fp,"%80s",cmd); + is >> cmd; int i; for(i=0;solver_type_table[i];i++) { @@ -1207,17 +1301,17 @@ } else if(strcmp(cmd,"nr_class")==0) { - fscanf(fp,"%d",&nr_class); + is >> nr_class; model_->nr_class=nr_class; } else if(strcmp(cmd,"nr_feature")==0) { - fscanf(fp,"%d",&nr_feature); + is >> nr_feature; model_->nr_feature=nr_feature; } else if(strcmp(cmd,"bias")==0) { - fscanf(fp,"%lf",&bias); + is >> bias; model_->bias=bias; } else if(strcmp(cmd,"w")==0) @@ -1229,7 +1323,7 @@ int nr_class = model_->nr_class; model_->label = Malloc(int,nr_class); for(int i=0;ilabel[i]); + is >> model_->label[i]; } else { @@ -1237,8 +1331,10 @@ free(model_); return NULL; } + } + nr_feature=model_->nr_feature; if(model_->bias>=0) n=nr_feature+1; @@ -1256,14 +1352,30 @@ { int j; for(j=0; jw[i*nr_w+j]); - fscanf(fp, "\n"); + is >> model_->w[i*nr_w+j]; + } - if (ferror(fp) != 0 || fclose(fp) != 0) return NULL; - + if (is.fail()) return NULL; + return model_; } + +struct model *from_string(char *inp) +{ + std::stringstream ss(inp); + return from_stream(ss); +} + + +struct model *load_model(const char *model_file_name) +{ + + std::ifstream is = std::ifstream(model_file_name) + return from_strean(is); +} + + int predict_values(const struct model *model_, const struct feature_node *x, double *dec_values) { int idx; @@ -1377,7 +1489,7 @@ return NULL; } -void cross_validation(const problem *prob, const parameter *param, int nr_fold, int *target) +void cross_validation(const problem *prob, const parameter *param, int nr_fold, int *target, int verbose) { int i; int *fold_start = Malloc(int,nr_fold+1); @@ -1387,11 +1499,12 @@ for(i=0;iy[perm[j]]; ++k; } - struct model *submodel = train(&subprob,param); + struct model *submodel = train(&subprob,param, verbose); for(j=begin;jx[perm[j]]); destroy_model(submodel);