liblinear-ruby 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/ext/blasp.h +8 -0
  3. data/ext/daxpy.c +8 -0
  4. data/ext/ddot.c +8 -0
  5. data/ext/dnrm2.c +8 -0
  6. data/ext/dscal.c +8 -0
  7. data/ext/liblinear_wrap.cxx +128 -3
  8. data/ext/linear.cpp +344 -175
  9. data/ext/linear.h +2 -0
  10. data/ext/tron.cpp +14 -8
  11. data/ext/tron.h +2 -1
  12. data/lib/liblinear/version.rb +1 -1
  13. data/{liblinear-1.95 → liblinear-2.1}/COPYRIGHT +1 -1
  14. data/{liblinear-1.95 → liblinear-2.1}/Makefile +1 -1
  15. data/{liblinear-1.95 → liblinear-2.1}/Makefile.win +3 -9
  16. data/{liblinear-1.95 → liblinear-2.1}/README +45 -7
  17. data/{liblinear-1.95 → liblinear-2.1}/blas/Makefile +0 -0
  18. data/{liblinear-1.95 → liblinear-2.1}/blas/blas.h +0 -0
  19. data/{liblinear-1.95 → liblinear-2.1}/blas/blasp.h +0 -0
  20. data/{liblinear-1.95 → liblinear-2.1}/blas/daxpy.c +0 -0
  21. data/{liblinear-1.95 → liblinear-2.1}/blas/ddot.c +0 -0
  22. data/{liblinear-1.95 → liblinear-2.1}/blas/dnrm2.c +0 -0
  23. data/{liblinear-1.95 → liblinear-2.1}/blas/dscal.c +0 -0
  24. data/{liblinear-1.95 → liblinear-2.1}/heart_scale +0 -0
  25. data/{liblinear-1.95 → liblinear-2.1}/linear.cpp +344 -175
  26. data/{liblinear-1.95 → liblinear-2.1}/linear.def +1 -0
  27. data/{liblinear-1.95 → liblinear-2.1}/linear.h +2 -0
  28. data/{liblinear-1.95 → liblinear-2.1}/matlab/Makefile +0 -0
  29. data/{liblinear-1.95 → liblinear-2.1}/matlab/README +12 -2
  30. data/{liblinear-1.95 → liblinear-2.1}/matlab/libsvmread.c +0 -0
  31. data/{liblinear-1.95 → liblinear-2.1}/matlab/libsvmwrite.c +1 -1
  32. data/{liblinear-1.95 → liblinear-2.1}/matlab/linear_model_matlab.c +1 -1
  33. data/{liblinear-1.95 → liblinear-2.1}/matlab/linear_model_matlab.h +0 -0
  34. data/liblinear-2.1/matlab/make.m +22 -0
  35. data/{liblinear-1.95 → liblinear-2.1}/matlab/predict.c +1 -1
  36. data/{liblinear-1.95 → liblinear-2.1}/matlab/train.c +65 -10
  37. data/{liblinear-1.95 → liblinear-2.1}/predict.c +0 -0
  38. data/{liblinear-1.95 → liblinear-2.1}/python/Makefile +0 -0
  39. data/{liblinear-1.95 → liblinear-2.1}/python/README +7 -0
  40. data/{liblinear-1.95 → liblinear-2.1}/python/liblinear.py +27 -8
  41. data/{liblinear-1.95 → liblinear-2.1}/python/liblinearutil.py +16 -2
  42. data/{liblinear-1.95 → liblinear-2.1}/train.c +51 -1
  43. data/{liblinear-1.95 → liblinear-2.1}/tron.cpp +14 -8
  44. data/{liblinear-1.95 → liblinear-2.1}/tron.h +2 -1
  45. data/liblinear-2.1/windows/liblinear.dll +0 -0
  46. data/{liblinear-1.95 → liblinear-2.1}/windows/libsvmread.mexw64 +0 -0
  47. data/{liblinear-1.95 → liblinear-2.1}/windows/libsvmwrite.mexw64 +0 -0
  48. data/liblinear-2.1/windows/predict.exe +0 -0
  49. data/{liblinear-1.95 → liblinear-2.1}/windows/predict.mexw64 +0 -0
  50. data/liblinear-2.1/windows/train.exe +0 -0
  51. data/liblinear-2.1/windows/train.mexw64 +0 -0
  52. data/liblinear-ruby.gemspec +9 -10
  53. metadata +49 -50
  54. data/liblinear-1.95/matlab/make.m +0 -21
  55. data/liblinear-1.95/windows/liblinear.dll +0 -0
  56. data/liblinear-1.95/windows/predict.exe +0 -0
  57. data/liblinear-1.95/windows/train.exe +0 -0
  58. data/liblinear-1.95/windows/train.mexw64 +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7da30519f73e2c8623e55d79bbceba8338cf3f14
4
- data.tar.gz: 765eda167d95dc14cbeb598d1224fcca8be9b2bb
3
+ metadata.gz: a7d1e2c1eeff706b5cd0494d4fc720dec937f710
4
+ data.tar.gz: 3d436efa057c9fa1a68e0e4e884322b4c07dfb10
5
5
  SHA512:
6
- metadata.gz: ca676587ed932b52aceac12795055459c2260596c63f1b417e89adb3f0deba84c0222a0f4b2d418f6145d613b5df8fc196820e6e3a2016ac549d3f6a8b20d595
7
- data.tar.gz: 1e05e2eeccc9405fba3b6b040421156b139e77d39914998d3ca3fa441c0806437304eaf753cc9244510de12f36897f6c5b2b48ffa08a54bd3bd75b0887e2b83f
6
+ metadata.gz: 59d78c950c0d15db0213b6925a56a7aa56b567126fa184ceea744e13c418bedd4cd00638182ac0635f40075041cd96cde6bb1ba1c788440f0fbe70a9e46b128f
7
+ data.tar.gz: fbeaad15badd01d2fea3ebf2ab2a4cf594e7f4b90975e5c88c73f13433f9c3c3282c5d7939dd347355543e2a94216e5e9274d3089a823650cb616507c089bd8b
@@ -3,6 +3,10 @@
3
3
 
4
4
  /* Functions listed in alphabetical order */
5
5
 
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
6
10
  #ifdef F2C_COMPAT
7
11
 
8
12
  void cdotc_(fcomplex *dotval, int *n, fcomplex *cx, int *incx,
@@ -428,3 +432,7 @@ int ztrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
428
432
 
429
433
  int ztrsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a,
430
434
  int *lda, dcomplex *x, int *incx);
435
+
436
+ #ifdef __cplusplus
437
+ }
438
+ #endif
@@ -1,5 +1,9 @@
1
1
  #include "blas.h"
2
2
 
3
+ #ifdef __cplusplus
4
+ extern "C" {
5
+ #endif
6
+
3
7
  int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
4
8
  int *incy)
5
9
  {
@@ -47,3 +51,7 @@ int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
47
51
 
48
52
  return 0;
49
53
  } /* daxpy_ */
54
+
55
+ #ifdef __cplusplus
56
+ }
57
+ #endif
data/ext/ddot.c CHANGED
@@ -1,5 +1,9 @@
1
1
  #include "blas.h"
2
2
 
3
+ #ifdef __cplusplus
4
+ extern "C" {
5
+ #endif
6
+
3
7
  double ddot_(int *n, double *sx, int *incx, double *sy, int *incy)
4
8
  {
5
9
  long int i, m, nn, iincx, iincy;
@@ -48,3 +52,7 @@ double ddot_(int *n, double *sx, int *incx, double *sy, int *incy)
48
52
 
49
53
  return stemp;
50
54
  } /* ddot_ */
55
+
56
+ #ifdef __cplusplus
57
+ }
58
+ #endif
@@ -1,6 +1,10 @@
1
1
  #include <math.h> /* Needed for fabs() and sqrt() */
2
2
  #include "blas.h"
3
3
 
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
4
8
  double dnrm2_(int *n, double *x, int *incx)
5
9
  {
6
10
  long int ix, nn, iincx;
@@ -60,3 +64,7 @@ double dnrm2_(int *n, double *x, int *incx)
60
64
  return norm;
61
65
 
62
66
  } /* dnrm2_ */
67
+
68
+ #ifdef __cplusplus
69
+ }
70
+ #endif
@@ -1,5 +1,9 @@
1
1
  #include "blas.h"
2
2
 
3
+ #ifdef __cplusplus
4
+ extern "C" {
5
+ #endif
6
+
3
7
  int dscal_(int *n, double *sa, double *sx, int *incx)
4
8
  {
5
9
  long int i, m, nincx, nn, iincx;
@@ -42,3 +46,7 @@ int dscal_(int *n, double *sa, double *sx, int *incx)
42
46
 
43
47
  return 0;
44
48
  } /* dscal_ */
49
+
50
+ #ifdef __cplusplus
51
+ }
52
+ #endif
@@ -1870,7 +1870,7 @@ SWIG_ruby_failed(void)
1870
1870
  }
1871
1871
 
1872
1872
 
1873
- /*@SWIG:/usr/share/swig2.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
1873
+ /*@SWIG:/usr/local/share/swig/2.0.4/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
1874
1874
  SWIGINTERN VALUE SWIG_AUX_NUM2LONG(VALUE *args)
1875
1875
  {
1876
1876
  VALUE obj = args[0];
@@ -1925,7 +1925,7 @@ SWIG_From_int (int value)
1925
1925
  }
1926
1926
 
1927
1927
 
1928
- /*@SWIG:/usr/share/swig2.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
1928
+ /*@SWIG:/usr/local/share/swig/2.0.4/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
1929
1929
  SWIGINTERN VALUE SWIG_AUX_NUM2DBL(VALUE *args)
1930
1930
  {
1931
1931
  VALUE obj = args[0];
@@ -2051,7 +2051,7 @@ SWIG_FromCharPtr(const char *cptr)
2051
2051
  }
2052
2052
 
2053
2053
 
2054
- /*@SWIG:/usr/share/swig2.0/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
2054
+ /*@SWIG:/usr/local/share/swig/2.0.4/ruby/rubyprimtypes.swg,19,%ruby_aux_method@*/
2055
2055
  SWIGINTERN VALUE SWIG_AUX_NUM2ULONG(VALUE *args)
2056
2056
  {
2057
2057
  VALUE obj = args[0];
@@ -2959,6 +2959,59 @@ fail:
2959
2959
  }
2960
2960
 
2961
2961
 
2962
+ SWIGINTERN VALUE
2963
+ _wrap_parameter_init_sol_set(int argc, VALUE *argv, VALUE self) {
2964
+ parameter *arg1 = (parameter *) 0 ;
2965
+ double *arg2 = (double *) 0 ;
2966
+ void *argp1 = 0 ;
2967
+ int res1 = 0 ;
2968
+ void *argp2 = 0 ;
2969
+ int res2 = 0 ;
2970
+
2971
+ if ((argc < 1) || (argc > 1)) {
2972
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
2973
+ }
2974
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_parameter, 0 | 0 );
2975
+ if (!SWIG_IsOK(res1)) {
2976
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "parameter *","init_sol", 1, self ));
2977
+ }
2978
+ arg1 = reinterpret_cast< parameter * >(argp1);
2979
+ res2 = SWIG_ConvertPtr(argv[0], &argp2,SWIGTYPE_p_double, SWIG_POINTER_DISOWN | 0 );
2980
+ if (!SWIG_IsOK(res2)) {
2981
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "double *","init_sol", 2, argv[0] ));
2982
+ }
2983
+ arg2 = reinterpret_cast< double * >(argp2);
2984
+ if (arg1) (arg1)->init_sol = arg2;
2985
+ return Qnil;
2986
+ fail:
2987
+ return Qnil;
2988
+ }
2989
+
2990
+
2991
+ SWIGINTERN VALUE
2992
+ _wrap_parameter_init_sol_get(int argc, VALUE *argv, VALUE self) {
2993
+ parameter *arg1 = (parameter *) 0 ;
2994
+ void *argp1 = 0 ;
2995
+ int res1 = 0 ;
2996
+ double *result = 0 ;
2997
+ VALUE vresult = Qnil;
2998
+
2999
+ if ((argc < 0) || (argc > 0)) {
3000
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0)",argc); SWIG_fail;
3001
+ }
3002
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_parameter, 0 | 0 );
3003
+ if (!SWIG_IsOK(res1)) {
3004
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "parameter *","init_sol", 1, self ));
3005
+ }
3006
+ arg1 = reinterpret_cast< parameter * >(argp1);
3007
+ result = (double *) ((arg1)->init_sol);
3008
+ vresult = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_double, 0 | 0 );
3009
+ return vresult;
3010
+ fail:
3011
+ return Qnil;
3012
+ }
3013
+
3014
+
2962
3015
  #ifdef HAVE_RB_DEFINE_ALLOC_FUNC
2963
3016
  SWIGINTERN VALUE
2964
3017
  _wrap_parameter_allocate(VALUE self) {
@@ -3430,6 +3483,75 @@ fail:
3430
3483
  }
3431
3484
 
3432
3485
 
3486
+ SWIGINTERN VALUE
3487
+ _wrap_find_parameter_C(int argc, VALUE *argv, VALUE self) {
3488
+ problem *arg1 = (problem *) 0 ;
3489
+ parameter *arg2 = (parameter *) 0 ;
3490
+ int arg3 ;
3491
+ double arg4 ;
3492
+ double arg5 ;
3493
+ double *arg6 = (double *) 0 ;
3494
+ double *arg7 = (double *) 0 ;
3495
+ void *argp1 = 0 ;
3496
+ int res1 = 0 ;
3497
+ void *argp2 = 0 ;
3498
+ int res2 = 0 ;
3499
+ int val3 ;
3500
+ int ecode3 = 0 ;
3501
+ double val4 ;
3502
+ int ecode4 = 0 ;
3503
+ double val5 ;
3504
+ int ecode5 = 0 ;
3505
+ void *argp6 = 0 ;
3506
+ int res6 = 0 ;
3507
+ void *argp7 = 0 ;
3508
+ int res7 = 0 ;
3509
+
3510
+ if ((argc < 7) || (argc > 7)) {
3511
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 7)",argc); SWIG_fail;
3512
+ }
3513
+ res1 = SWIG_ConvertPtr(argv[0], &argp1,SWIGTYPE_p_problem, 0 | 0 );
3514
+ if (!SWIG_IsOK(res1)) {
3515
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "problem const *","find_parameter_C", 1, argv[0] ));
3516
+ }
3517
+ arg1 = reinterpret_cast< problem * >(argp1);
3518
+ res2 = SWIG_ConvertPtr(argv[1], &argp2,SWIGTYPE_p_parameter, 0 | 0 );
3519
+ if (!SWIG_IsOK(res2)) {
3520
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "parameter const *","find_parameter_C", 2, argv[1] ));
3521
+ }
3522
+ arg2 = reinterpret_cast< parameter * >(argp2);
3523
+ ecode3 = SWIG_AsVal_int(argv[2], &val3);
3524
+ if (!SWIG_IsOK(ecode3)) {
3525
+ SWIG_exception_fail(SWIG_ArgError(ecode3), Ruby_Format_TypeError( "", "int","find_parameter_C", 3, argv[2] ));
3526
+ }
3527
+ arg3 = static_cast< int >(val3);
3528
+ ecode4 = SWIG_AsVal_double(argv[3], &val4);
3529
+ if (!SWIG_IsOK(ecode4)) {
3530
+ SWIG_exception_fail(SWIG_ArgError(ecode4), Ruby_Format_TypeError( "", "double","find_parameter_C", 4, argv[3] ));
3531
+ }
3532
+ arg4 = static_cast< double >(val4);
3533
+ ecode5 = SWIG_AsVal_double(argv[4], &val5);
3534
+ if (!SWIG_IsOK(ecode5)) {
3535
+ SWIG_exception_fail(SWIG_ArgError(ecode5), Ruby_Format_TypeError( "", "double","find_parameter_C", 5, argv[4] ));
3536
+ }
3537
+ arg5 = static_cast< double >(val5);
3538
+ res6 = SWIG_ConvertPtr(argv[5], &argp6,SWIGTYPE_p_double, 0 | 0 );
3539
+ if (!SWIG_IsOK(res6)) {
3540
+ SWIG_exception_fail(SWIG_ArgError(res6), Ruby_Format_TypeError( "", "double *","find_parameter_C", 6, argv[5] ));
3541
+ }
3542
+ arg6 = reinterpret_cast< double * >(argp6);
3543
+ res7 = SWIG_ConvertPtr(argv[6], &argp7,SWIGTYPE_p_double, 0 | 0 );
3544
+ if (!SWIG_IsOK(res7)) {
3545
+ SWIG_exception_fail(SWIG_ArgError(res7), Ruby_Format_TypeError( "", "double *","find_parameter_C", 7, argv[6] ));
3546
+ }
3547
+ arg7 = reinterpret_cast< double * >(argp7);
3548
+ find_parameter_C((problem const *)arg1,(parameter const *)arg2,arg3,arg4,arg5,arg6,arg7);
3549
+ return Qnil;
3550
+ fail:
3551
+ return Qnil;
3552
+ }
3553
+
3554
+
3433
3555
  SWIGINTERN VALUE
3434
3556
  _wrap_predict_values(int argc, VALUE *argv, VALUE self) {
3435
3557
  model *arg1 = (model *) 0 ;
@@ -4685,6 +4807,8 @@ SWIGEXPORT void Init_liblinearswig(void) {
4685
4807
  rb_define_method(SwigClassParameter.klass, "weight", VALUEFUNC(_wrap_parameter_weight_get), -1);
4686
4808
  rb_define_method(SwigClassParameter.klass, "p=", VALUEFUNC(_wrap_parameter_p_set), -1);
4687
4809
  rb_define_method(SwigClassParameter.klass, "p", VALUEFUNC(_wrap_parameter_p_get), -1);
4810
+ rb_define_method(SwigClassParameter.klass, "init_sol=", VALUEFUNC(_wrap_parameter_init_sol_set), -1);
4811
+ rb_define_method(SwigClassParameter.klass, "init_sol", VALUEFUNC(_wrap_parameter_init_sol_get), -1);
4688
4812
  SwigClassParameter.mark = 0;
4689
4813
  SwigClassParameter.destroy = (void (*)(void *)) free_parameter;
4690
4814
  SwigClassParameter.trackObjects = 0;
@@ -4710,6 +4834,7 @@ SWIGEXPORT void Init_liblinearswig(void) {
4710
4834
  SwigClassModel.trackObjects = 0;
4711
4835
  rb_define_module_function(mLiblinearswig, "train", VALUEFUNC(_wrap_train), -1);
4712
4836
  rb_define_module_function(mLiblinearswig, "cross_validation", VALUEFUNC(_wrap_cross_validation), -1);
4837
+ rb_define_module_function(mLiblinearswig, "find_parameter_C", VALUEFUNC(_wrap_find_parameter_C), -1);
4713
4838
  rb_define_module_function(mLiblinearswig, "predict_values", VALUEFUNC(_wrap_predict_values), -1);
4714
4839
  rb_define_module_function(mLiblinearswig, "predict", VALUEFUNC(_wrap_predict), -1);
4715
4840
  rb_define_module_function(mLiblinearswig, "predict_probability", VALUEFUNC(_wrap_predict_probability), -1);
@@ -27,6 +27,7 @@ static void print_string_stdout(const char *s)
27
27
  fputs(s,stdout);
28
28
  fflush(stdout);
29
29
  }
30
+ static void print_null(const char *s) {}
30
31
 
31
32
  static void (*liblinear_print_string) (const char *) = &print_string_stdout;
32
33
 
@@ -43,6 +44,40 @@ static void info(const char *fmt,...)
43
44
  #else
44
45
  static void info(const char *fmt,...) {}
45
46
  #endif
47
+ class sparse_operator
48
+ {
49
+ public:
50
+ static double nrm2_sq(const feature_node *x)
51
+ {
52
+ double ret = 0;
53
+ while(x->index != -1)
54
+ {
55
+ ret += x->value*x->value;
56
+ x++;
57
+ }
58
+ return (ret);
59
+ }
60
+
61
+ static double dot(const double *s, const feature_node *x)
62
+ {
63
+ double ret = 0;
64
+ while(x->index != -1)
65
+ {
66
+ ret += s[x->index-1]*x->value;
67
+ x++;
68
+ }
69
+ return (ret);
70
+ }
71
+
72
+ static void axpy(const double a, const feature_node *x, double *y)
73
+ {
74
+ while(x->index != -1)
75
+ {
76
+ y[x->index-1] += a*x->value;
77
+ x++;
78
+ }
79
+ }
80
+ };
46
81
 
47
82
  class l2r_lr_fun: public function
48
83
  {
@@ -139,12 +174,19 @@ void l2r_lr_fun::Hv(double *s, double *Hs)
139
174
  int l=prob->l;
140
175
  int w_size=get_nr_variable();
141
176
  double *wa = new double[l];
177
+ feature_node **x=prob->x;
142
178
 
143
- Xv(s, wa);
179
+ for(i=0;i<w_size;i++)
180
+ Hs[i] = 0;
144
181
  for(i=0;i<l;i++)
182
+ {
183
+ feature_node * const xi=x[i];
184
+ wa[i] = sparse_operator::dot(s, xi);
185
+
145
186
  wa[i] = C[i]*D[i]*wa[i];
146
187
 
147
- XTv(wa, Hs);
188
+ sparse_operator::axpy(wa[i], xi, Hs);
189
+ }
148
190
  for(i=0;i<w_size;i++)
149
191
  Hs[i] = s[i] + Hs[i];
150
192
  delete[] wa;
@@ -157,15 +199,7 @@ void l2r_lr_fun::Xv(double *v, double *Xv)
157
199
  feature_node **x=prob->x;
158
200
 
159
201
  for(i=0;i<l;i++)
160
- {
161
- feature_node *s=x[i];
162
- Xv[i]=0;
163
- while(s->index!=-1)
164
- {
165
- Xv[i]+=v[s->index-1]*s->value;
166
- s++;
167
- }
168
- }
202
+ Xv[i]=sparse_operator::dot(v, x[i]);
169
203
  }
170
204
 
171
205
  void l2r_lr_fun::XTv(double *v, double *XTv)
@@ -178,14 +212,7 @@ void l2r_lr_fun::XTv(double *v, double *XTv)
178
212
  for(i=0;i<w_size;i++)
179
213
  XTv[i]=0;
180
214
  for(i=0;i<l;i++)
181
- {
182
- feature_node *s=x[i];
183
- while(s->index!=-1)
184
- {
185
- XTv[s->index-1]+=v[i]*s->value;
186
- s++;
187
- }
188
- }
215
+ sparse_operator::axpy(v[i], x[i], XTv);
189
216
  }
190
217
 
191
218
  class l2r_l2_svc_fun: public function
@@ -202,7 +229,6 @@ public:
202
229
 
203
230
  protected:
204
231
  void Xv(double *v, double *Xv);
205
- void subXv(double *v, double *Xv);
206
232
  void subXTv(double *v, double *XTv);
207
233
 
208
234
  double *C;
@@ -287,12 +313,19 @@ void l2r_l2_svc_fun::Hv(double *s, double *Hs)
287
313
  int i;
288
314
  int w_size=get_nr_variable();
289
315
  double *wa = new double[sizeI];
316
+ feature_node **x=prob->x;
290
317
 
291
- subXv(s, wa);
318
+ for(i=0;i<w_size;i++)
319
+ Hs[i]=0;
292
320
  for(i=0;i<sizeI;i++)
321
+ {
322
+ feature_node * const xi=x[I[i]];
323
+ wa[i] = sparse_operator::dot(s, xi);
324
+
293
325
  wa[i] = C[I[i]]*wa[i];
294
326
 
295
- subXTv(wa, Hs);
327
+ sparse_operator::axpy(wa[i], xi, Hs);
328
+ }
296
329
  for(i=0;i<w_size;i++)
297
330
  Hs[i] = s[i] + 2*Hs[i];
298
331
  delete[] wa;
@@ -305,32 +338,7 @@ void l2r_l2_svc_fun::Xv(double *v, double *Xv)
305
338
  feature_node **x=prob->x;
306
339
 
307
340
  for(i=0;i<l;i++)
308
- {
309
- feature_node *s=x[i];
310
- Xv[i]=0;
311
- while(s->index!=-1)
312
- {
313
- Xv[i]+=v[s->index-1]*s->value;
314
- s++;
315
- }
316
- }
317
- }
318
-
319
- void l2r_l2_svc_fun::subXv(double *v, double *Xv)
320
- {
321
- int i;
322
- feature_node **x=prob->x;
323
-
324
- for(i=0;i<sizeI;i++)
325
- {
326
- feature_node *s=x[I[i]];
327
- Xv[i]=0;
328
- while(s->index!=-1)
329
- {
330
- Xv[i]+=v[s->index-1]*s->value;
331
- s++;
332
- }
333
- }
341
+ Xv[i]=sparse_operator::dot(v, x[i]);
334
342
  }
335
343
 
336
344
  void l2r_l2_svc_fun::subXTv(double *v, double *XTv)
@@ -342,14 +350,7 @@ void l2r_l2_svc_fun::subXTv(double *v, double *XTv)
342
350
  for(i=0;i<w_size;i++)
343
351
  XTv[i]=0;
344
352
  for(i=0;i<sizeI;i++)
345
- {
346
- feature_node *s=x[I[i]];
347
- while(s->index!=-1)
348
- {
349
- XTv[s->index-1]+=v[i]*s->value;
350
- s++;
351
- }
352
- }
353
+ sparse_operator::axpy(v[i], x[I[i]], XTv);
353
354
  }
354
355
 
355
356
  class l2r_l2_svr_fun: public l2r_l2_svc_fun
@@ -830,14 +831,10 @@ static void solve_l2r_l1l2_svc(
830
831
  {
831
832
  QD[i] = diag[GETI(i)];
832
833
 
833
- feature_node *xi = prob->x[i];
834
- while (xi->index != -1)
835
- {
836
- double val = xi->value;
837
- QD[i] += val*val;
838
- w[xi->index-1] += y[i]*alpha[i]*val;
839
- xi++;
840
- }
834
+ feature_node * const xi = prob->x[i];
835
+ QD[i] += sparse_operator::nrm2_sq(xi);
836
+ sparse_operator::axpy(y[i]*alpha[i], xi, w);
837
+
841
838
  index[i] = i;
842
839
  }
843
840
 
@@ -855,16 +852,10 @@ static void solve_l2r_l1l2_svc(
855
852
  for (s=0; s<active_size; s++)
856
853
  {
857
854
  i = index[s];
858
- G = 0;
859
- schar yi = y[i];
855
+ const schar yi = y[i];
856
+ feature_node * const xi = prob->x[i];
860
857
 
861
- feature_node *xi = prob->x[i];
862
- while(xi->index!= -1)
863
- {
864
- G += w[xi->index-1]*(xi->value);
865
- xi++;
866
- }
867
- G = G*yi-1;
858
+ G = yi*sparse_operator::dot(w, xi)-1;
868
859
 
869
860
  C = upper_bound[GETI(i)];
870
861
  G += alpha[i]*diag[GETI(i)];
@@ -905,12 +896,7 @@ static void solve_l2r_l1l2_svc(
905
896
  double alpha_old = alpha[i];
906
897
  alpha[i] = min(max(alpha[i] - G/QD[i], 0.0), C);
907
898
  d = (alpha[i] - alpha_old)*yi;
908
- xi = prob->x[i];
909
- while (xi->index != -1)
910
- {
911
- w[xi->index-1] += d*xi->value;
912
- xi++;
913
- }
899
+ sparse_operator::axpy(d, xi, w);
914
900
  }
915
901
  }
916
902
 
@@ -1035,15 +1021,9 @@ static void solve_l2r_l1l2_svr(
1035
1021
  w[i] = 0;
1036
1022
  for(i=0; i<l; i++)
1037
1023
  {
1038
- QD[i] = 0;
1039
- feature_node *xi = prob->x[i];
1040
- while(xi->index != -1)
1041
- {
1042
- double val = xi->value;
1043
- QD[i] += val*val;
1044
- w[xi->index-1] += beta[i]*val;
1045
- xi++;
1046
- }
1024
+ feature_node * const xi = prob->x[i];
1025
+ QD[i] = sparse_operator::nrm2_sq(xi);
1026
+ sparse_operator::axpy(beta[i], xi, w);
1047
1027
 
1048
1028
  index[i] = i;
1049
1029
  }
@@ -1066,14 +1046,8 @@ static void solve_l2r_l1l2_svr(
1066
1046
  G = -y[i] + lambda[GETI(i)]*beta[i];
1067
1047
  H = QD[i] + lambda[GETI(i)];
1068
1048
 
1069
- feature_node *xi = prob->x[i];
1070
- while(xi->index != -1)
1071
- {
1072
- int ind = xi->index-1;
1073
- double val = xi->value;
1074
- G += val*w[ind];
1075
- xi++;
1076
- }
1049
+ feature_node * const xi = prob->x[i];
1050
+ G += sparse_operator::dot(w, xi);
1077
1051
 
1078
1052
  double Gp = G+p;
1079
1053
  double Gn = G-p;
@@ -1140,14 +1114,7 @@ static void solve_l2r_l1l2_svr(
1140
1114
  d = beta[i]-beta_old;
1141
1115
 
1142
1116
  if(d != 0)
1143
- {
1144
- xi = prob->x[i];
1145
- while(xi->index != -1)
1146
- {
1147
- w[xi->index-1] += d*xi->value;
1148
- xi++;
1149
- }
1150
- }
1117
+ sparse_operator::axpy(d, xi, w);
1151
1118
  }
1152
1119
 
1153
1120
  if(iter == 0)
@@ -1260,15 +1227,9 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do
1260
1227
  w[i] = 0;
1261
1228
  for(i=0; i<l; i++)
1262
1229
  {
1263
- xTx[i] = 0;
1264
- feature_node *xi = prob->x[i];
1265
- while (xi->index != -1)
1266
- {
1267
- double val = xi->value;
1268
- xTx[i] += val*val;
1269
- w[xi->index-1] += y[i]*alpha[2*i]*val;
1270
- xi++;
1271
- }
1230
+ feature_node * const xi = prob->x[i];
1231
+ xTx[i] = sparse_operator::nrm2_sq(xi);
1232
+ sparse_operator::axpy(y[i]*alpha[2*i], xi, w);
1272
1233
  index[i] = i;
1273
1234
  }
1274
1235
 
@@ -1284,16 +1245,11 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do
1284
1245
  for (s=0; s<l; s++)
1285
1246
  {
1286
1247
  i = index[s];
1287
- schar yi = y[i];
1248
+ const schar yi = y[i];
1288
1249
  double C = upper_bound[GETI(i)];
1289
1250
  double ywTx = 0, xisq = xTx[i];
1290
- feature_node *xi = prob->x[i];
1291
- while (xi->index != -1)
1292
- {
1293
- ywTx += w[xi->index-1]*xi->value;
1294
- xi++;
1295
- }
1296
- ywTx *= y[i];
1251
+ feature_node * const xi = prob->x[i];
1252
+ ywTx = yi*sparse_operator::dot(w, xi);
1297
1253
  double a = xisq, b = ywTx;
1298
1254
 
1299
1255
  // Decide to minimize g_1(z) or g_2(z)
@@ -1335,12 +1291,7 @@ void solve_l2r_lr_dual(const problem *prob, double *w, double eps, double Cp, do
1335
1291
  {
1336
1292
  alpha[ind1] = z;
1337
1293
  alpha[ind2] = C-z;
1338
- xi = prob->x[i];
1339
- while (xi->index != -1)
1340
- {
1341
- w[xi->index-1] += sign*(z-alpha_old)*yi*xi->value;
1342
- xi++;
1343
- }
1294
+ sparse_operator::axpy(sign*(z-alpha_old)*yi, xi, w);
1344
1295
  }
1345
1296
  }
1346
1297
 
@@ -1534,11 +1485,7 @@ static void solve_l1r_l2_svc(
1534
1485
  if(appxcond <= 0)
1535
1486
  {
1536
1487
  x = prob_col->x[j];
1537
- while(x->index != -1)
1538
- {
1539
- b[x->index-1] += d_diff*x->value;
1540
- x++;
1541
- }
1488
+ sparse_operator::axpy(d_diff, x, b);
1542
1489
  break;
1543
1490
  }
1544
1491
 
@@ -1598,11 +1545,7 @@ static void solve_l1r_l2_svc(
1598
1545
  {
1599
1546
  if(w[i]==0) continue;
1600
1547
  x = prob_col->x[i];
1601
- while(x->index != -1)
1602
- {
1603
- b[x->index-1] -= w[i]*x->value;
1604
- x++;
1605
- }
1548
+ sparse_operator::axpy(-w[i], x, b);
1606
1549
  }
1607
1550
  }
1608
1551
  }
@@ -1891,12 +1834,7 @@ static void solve_l1r_lr(
1891
1834
  wpd[j] += z;
1892
1835
 
1893
1836
  x = prob_col->x[j];
1894
- while(x->index != -1)
1895
- {
1896
- int ind = x->index-1;
1897
- xTd[ind] += x->value*z;
1898
- x++;
1899
- }
1837
+ sparse_operator::axpy(z, x, xTd);
1900
1838
  }
1901
1839
 
1902
1840
  iter++;
@@ -1988,11 +1926,7 @@ static void solve_l1r_lr(
1988
1926
  {
1989
1927
  if(w[i]==0) continue;
1990
1928
  x = prob_col->x[i];
1991
- while(x->index != -1)
1992
- {
1993
- exp_wTx[x->index-1] += w[i]*x->value;
1994
- x++;
1995
- }
1929
+ sparse_operator::axpy(w[i], x, exp_wTx);
1996
1930
  }
1997
1931
 
1998
1932
  for(int i=0; i<l; i++)
@@ -2180,14 +2114,18 @@ static void group_classes(const problem *prob, int *nr_class_ret, int **label_re
2180
2114
 
2181
2115
  static void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn)
2182
2116
  {
2183
- double eps=param->eps;
2117
+ //inner and outer tolerances for TRON
2118
+ double eps = param->eps;
2119
+ double eps_cg = 0.1;
2120
+ if(param->init_sol != NULL)
2121
+ eps_cg = 0.5;
2122
+
2184
2123
  int pos = 0;
2185
2124
  int neg = 0;
2186
2125
  for(int i=0;i<prob->l;i++)
2187
2126
  if(prob->y[i] > 0)
2188
2127
  pos++;
2189
2128
  neg = prob->l - pos;
2190
-
2191
2129
  double primal_solver_tol = eps*max(min(pos,neg), 1)/prob->l;
2192
2130
 
2193
2131
  function *fun_obj=NULL;
@@ -2204,7 +2142,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
2204
2142
  C[i] = Cn;
2205
2143
  }
2206
2144
  fun_obj=new l2r_lr_fun(prob, C);
2207
- TRON tron_obj(fun_obj, primal_solver_tol);
2145
+ TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
2208
2146
  tron_obj.set_print_string(liblinear_print_string);
2209
2147
  tron_obj.tron(w);
2210
2148
  delete fun_obj;
@@ -2222,7 +2160,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
2222
2160
  C[i] = Cn;
2223
2161
  }
2224
2162
  fun_obj=new l2r_l2_svc_fun(prob, C);
2225
- TRON tron_obj(fun_obj, primal_solver_tol);
2163
+ TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
2226
2164
  tron_obj.set_print_string(liblinear_print_string);
2227
2165
  tron_obj.tron(w);
2228
2166
  delete fun_obj;
@@ -2287,6 +2225,36 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
2287
2225
  }
2288
2226
  }
2289
2227
 
2228
+ // Calculate the initial C for parameter selection
2229
+ static double calc_start_C(const problem *prob, const parameter *param)
2230
+ {
2231
+ int i;
2232
+ double xTx,max_xTx;
2233
+ max_xTx = 0;
2234
+ for(i=0; i<prob->l; i++)
2235
+ {
2236
+ xTx = 0;
2237
+ feature_node *xi=prob->x[i];
2238
+ while(xi->index != -1)
2239
+ {
2240
+ double val = xi->value;
2241
+ xTx += val*val;
2242
+ xi++;
2243
+ }
2244
+ if(xTx > max_xTx)
2245
+ max_xTx = xTx;
2246
+ }
2247
+
2248
+ double min_C = 1.0;
2249
+ if(param->solver_type == L2R_LR)
2250
+ min_C = 1.0 / (prob->l * max_xTx);
2251
+ else if(param->solver_type == L2R_L2LOSS_SVC)
2252
+ min_C = 1.0 / (2 * prob->l * max_xTx);
2253
+
2254
+ return pow( 2, floor(log(min_C) / log(2.0)) );
2255
+ }
2256
+
2257
+
2290
2258
  //
2291
2259
  // Interface functions
2292
2260
  //
@@ -2308,9 +2276,11 @@ model* train(const problem *prob, const parameter *param)
2308
2276
  if(check_regression_model(model_))
2309
2277
  {
2310
2278
  model_->w = Malloc(double, w_size);
2279
+ for(i=0; i<w_size; i++)
2280
+ model_->w[i] = 0;
2311
2281
  model_->nr_class = 2;
2312
2282
  model_->label = NULL;
2313
- train_one(prob, param, &model_->w[0], 0, 0);
2283
+ train_one(prob, param, model_->w, 0, 0);
2314
2284
  }
2315
2285
  else
2316
2286
  {
@@ -2380,8 +2350,15 @@ model* train(const problem *prob, const parameter *param)
2380
2350
  sub_prob.y[k] = +1;
2381
2351
  for(; k<sub_prob.l; k++)
2382
2352
  sub_prob.y[k] = -1;
2353
+
2354
+ if(param->init_sol != NULL)
2355
+ for(i=0;i<w_size;i++)
2356
+ model_->w[i] = param->init_sol[i];
2357
+ else
2358
+ for(i=0;i<w_size;i++)
2359
+ model_->w[i] = 0;
2383
2360
 
2384
- train_one(&sub_prob, param, &model_->w[0], weighted_C[0], weighted_C[1]);
2361
+ train_one(&sub_prob, param, model_->w, weighted_C[0], weighted_C[1]);
2385
2362
  }
2386
2363
  else
2387
2364
  {
@@ -2400,6 +2377,13 @@ model* train(const problem *prob, const parameter *param)
2400
2377
  for(; k<sub_prob.l; k++)
2401
2378
  sub_prob.y[k] = -1;
2402
2379
 
2380
+ if(param->init_sol != NULL)
2381
+ for(j=0;j<w_size;j++)
2382
+ w[j] = param->init_sol[j*nr_class+i];
2383
+ else
2384
+ for(j=0;j<w_size;j++)
2385
+ w[j] = 0;
2386
+
2403
2387
  train_one(&sub_prob, param, w, weighted_C[i], param->C);
2404
2388
 
2405
2389
  for(int j=0;j<w_size;j++)
@@ -2480,6 +2464,158 @@ void cross_validation(const problem *prob, const parameter *param, int nr_fold,
2480
2464
  free(perm);
2481
2465
  }
2482
2466
 
2467
+ void find_parameter_C(const problem *prob, const parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate)
2468
+ {
2469
+ // variables for CV
2470
+ int i;
2471
+ int *fold_start;
2472
+ int l = prob->l;
2473
+ int *perm = Malloc(int, l);
2474
+ double *target = Malloc(double, prob->l);
2475
+ struct problem *subprob = Malloc(problem,nr_fold);
2476
+
2477
+ // variables for warm start
2478
+ double ratio = 2;
2479
+ double **prev_w = Malloc(double*, nr_fold);
2480
+ for(i = 0; i < nr_fold; i++)
2481
+ prev_w[i] = NULL;
2482
+ int num_unchanged_w = 0;
2483
+ struct parameter param1 = *param;
2484
+ void (*default_print_string) (const char *) = liblinear_print_string;
2485
+
2486
+ if (nr_fold > l)
2487
+ {
2488
+ nr_fold = l;
2489
+ fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
2490
+ }
2491
+ fold_start = Malloc(int,nr_fold+1);
2492
+ for(i=0;i<l;i++) perm[i]=i;
2493
+ for(i=0;i<l;i++)
2494
+ {
2495
+ int j = i+rand()%(l-i);
2496
+ swap(perm[i],perm[j]);
2497
+ }
2498
+ for(i=0;i<=nr_fold;i++)
2499
+ fold_start[i]=i*l/nr_fold;
2500
+
2501
+ for(i=0;i<nr_fold;i++)
2502
+ {
2503
+ int begin = fold_start[i];
2504
+ int end = fold_start[i+1];
2505
+ int j,k;
2506
+
2507
+ subprob[i].bias = prob->bias;
2508
+ subprob[i].n = prob->n;
2509
+ subprob[i].l = l-(end-begin);
2510
+ subprob[i].x = Malloc(struct feature_node*,subprob[i].l);
2511
+ subprob[i].y = Malloc(double,subprob[i].l);
2512
+
2513
+ k=0;
2514
+ for(j=0;j<begin;j++)
2515
+ {
2516
+ subprob[i].x[k] = prob->x[perm[j]];
2517
+ subprob[i].y[k] = prob->y[perm[j]];
2518
+ ++k;
2519
+ }
2520
+ for(j=end;j<l;j++)
2521
+ {
2522
+ subprob[i].x[k] = prob->x[perm[j]];
2523
+ subprob[i].y[k] = prob->y[perm[j]];
2524
+ ++k;
2525
+ }
2526
+
2527
+ }
2528
+
2529
+ *best_rate = 0;
2530
+ if(start_C <= 0)
2531
+ start_C = calc_start_C(prob,param);
2532
+ param1.C = start_C;
2533
+
2534
+ while(param1.C <= max_C)
2535
+ {
2536
+ //Output disabled for running CV at a particular C
2537
+ set_print_string_function(&print_null);
2538
+
2539
+ for(i=0; i<nr_fold; i++)
2540
+ {
2541
+ int j;
2542
+ int begin = fold_start[i];
2543
+ int end = fold_start[i+1];
2544
+
2545
+ param1.init_sol = prev_w[i];
2546
+ struct model *submodel = train(&subprob[i],&param1);
2547
+
2548
+ int total_w_size;
2549
+ if(submodel->nr_class == 2)
2550
+ total_w_size = subprob[i].n;
2551
+ else
2552
+ total_w_size = subprob[i].n * submodel->nr_class;
2553
+
2554
+ if(prev_w[i] == NULL)
2555
+ {
2556
+ prev_w[i] = Malloc(double, total_w_size);
2557
+ for(j=0; j<total_w_size; j++)
2558
+ prev_w[i][j] = submodel->w[j];
2559
+ }
2560
+ else if(num_unchanged_w >= 0)
2561
+ {
2562
+ double norm_w_diff = 0;
2563
+ for(j=0; j<total_w_size; j++)
2564
+ {
2565
+ norm_w_diff += (submodel->w[j] - prev_w[i][j])*(submodel->w[j] - prev_w[i][j]);
2566
+ prev_w[i][j] = submodel->w[j];
2567
+ }
2568
+ norm_w_diff = sqrt(norm_w_diff);
2569
+
2570
+ if(norm_w_diff > 1e-15)
2571
+ num_unchanged_w = -1;
2572
+ }
2573
+ else
2574
+ {
2575
+ for(j=0; j<total_w_size; j++)
2576
+ prev_w[i][j] = submodel->w[j];
2577
+ }
2578
+
2579
+ for(j=begin; j<end; j++)
2580
+ target[perm[j]] = predict(submodel,prob->x[perm[j]]);
2581
+
2582
+ free_and_destroy_model(&submodel);
2583
+ }
2584
+ set_print_string_function(default_print_string);
2585
+
2586
+ int total_correct = 0;
2587
+ for(i=0; i<prob->l; i++)
2588
+ if(target[i] == prob->y[i])
2589
+ ++total_correct;
2590
+ double current_rate = (double)total_correct/prob->l;
2591
+ if(current_rate > *best_rate)
2592
+ {
2593
+ *best_C = param1.C;
2594
+ *best_rate = current_rate;
2595
+ }
2596
+
2597
+ info("log2c=%7.2f\trate=%g\n",log(param1.C)/log(2.0),100.0*current_rate);
2598
+ num_unchanged_w++;
2599
+ if(num_unchanged_w == 3)
2600
+ break;
2601
+ param1.C = param1.C*ratio;
2602
+ }
2603
+
2604
+ if(param1.C > max_C && max_C > start_C)
2605
+ info("warning: maximum C reached.\n");
2606
+ free(fold_start);
2607
+ free(perm);
2608
+ free(target);
2609
+ for(i=0; i<nr_fold; i++)
2610
+ {
2611
+ free(subprob[i].x);
2612
+ free(subprob[i].y);
2613
+ free(prev_w[i]);
2614
+ }
2615
+ free(prev_w);
2616
+ free(subprob);
2617
+ }
2618
+
2483
2619
  double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values)
2484
2620
  {
2485
2621
  int idx;
@@ -2592,7 +2728,11 @@ int save_model(const char *model_file_name, const struct model *model_)
2592
2728
  FILE *fp = fopen(model_file_name,"w");
2593
2729
  if(fp==NULL) return -1;
2594
2730
 
2595
- char *old_locale = strdup(setlocale(LC_ALL, NULL));
2731
+ char *old_locale = setlocale(LC_ALL, NULL);
2732
+ if (old_locale)
2733
+ {
2734
+ old_locale = strdup(old_locale);
2735
+ }
2596
2736
  setlocale(LC_ALL, "C");
2597
2737
 
2598
2738
  int nr_w;
@@ -2632,6 +2772,30 @@ int save_model(const char *model_file_name, const struct model *model_)
2632
2772
  else return 0;
2633
2773
  }
2634
2774
 
2775
+ //
2776
+ // FSCANF helps to handle fscanf failures.
2777
+ // Its do-while block avoids the ambiguity when
2778
+ // if (...)
2779
+ // FSCANF();
2780
+ // is used
2781
+ //
2782
+ #define FSCANF(_stream, _format, _var)do\
2783
+ {\
2784
+ if (fscanf(_stream, _format, _var) != 1)\
2785
+ {\
2786
+ fprintf(stderr, "ERROR: fscanf failed to read the model\n");\
2787
+ EXIT_LOAD_MODEL()\
2788
+ }\
2789
+ }while(0)
2790
+ // EXIT_LOAD_MODEL should NOT end with a semicolon.
2791
+ #define EXIT_LOAD_MODEL()\
2792
+ {\
2793
+ setlocale(LC_ALL, old_locale);\
2794
+ free(model_->label);\
2795
+ free(model_);\
2796
+ free(old_locale);\
2797
+ return NULL;\
2798
+ }
2635
2799
  struct model *load_model(const char *model_file_name)
2636
2800
  {
2637
2801
  FILE *fp = fopen(model_file_name,"r");
@@ -2647,16 +2811,20 @@ struct model *load_model(const char *model_file_name)
2647
2811
 
2648
2812
  model_->label = NULL;
2649
2813
 
2650
- char *old_locale = strdup(setlocale(LC_ALL, NULL));
2814
+ char *old_locale = setlocale(LC_ALL, NULL);
2815
+ if (old_locale)
2816
+ {
2817
+ old_locale = strdup(old_locale);
2818
+ }
2651
2819
  setlocale(LC_ALL, "C");
2652
2820
 
2653
2821
  char cmd[81];
2654
2822
  while(1)
2655
2823
  {
2656
- fscanf(fp,"%80s",cmd);
2824
+ FSCANF(fp,"%80s",cmd);
2657
2825
  if(strcmp(cmd,"solver_type")==0)
2658
2826
  {
2659
- fscanf(fp,"%80s",cmd);
2827
+ FSCANF(fp,"%80s",cmd);
2660
2828
  int i;
2661
2829
  for(i=0;solver_type_table[i];i++)
2662
2830
  {
@@ -2669,27 +2837,22 @@ struct model *load_model(const char *model_file_name)
2669
2837
  if(solver_type_table[i] == NULL)
2670
2838
  {
2671
2839
  fprintf(stderr,"unknown solver type.\n");
2672
-
2673
- setlocale(LC_ALL, old_locale);
2674
- free(model_->label);
2675
- free(model_);
2676
- free(old_locale);
2677
- return NULL;
2840
+ EXIT_LOAD_MODEL()
2678
2841
  }
2679
2842
  }
2680
2843
  else if(strcmp(cmd,"nr_class")==0)
2681
2844
  {
2682
- fscanf(fp,"%d",&nr_class);
2845
+ FSCANF(fp,"%d",&nr_class);
2683
2846
  model_->nr_class=nr_class;
2684
2847
  }
2685
2848
  else if(strcmp(cmd,"nr_feature")==0)
2686
2849
  {
2687
- fscanf(fp,"%d",&nr_feature);
2850
+ FSCANF(fp,"%d",&nr_feature);
2688
2851
  model_->nr_feature=nr_feature;
2689
2852
  }
2690
2853
  else if(strcmp(cmd,"bias")==0)
2691
2854
  {
2692
- fscanf(fp,"%lf",&bias);
2855
+ FSCANF(fp,"%lf",&bias);
2693
2856
  model_->bias=bias;
2694
2857
  }
2695
2858
  else if(strcmp(cmd,"w")==0)
@@ -2701,16 +2864,12 @@ struct model *load_model(const char *model_file_name)
2701
2864
  int nr_class = model_->nr_class;
2702
2865
  model_->label = Malloc(int,nr_class);
2703
2866
  for(int i=0;i<nr_class;i++)
2704
- fscanf(fp,"%d",&model_->label[i]);
2867
+ FSCANF(fp,"%d",&model_->label[i]);
2705
2868
  }
2706
2869
  else
2707
2870
  {
2708
2871
  fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
2709
- setlocale(LC_ALL, old_locale);
2710
- free(model_->label);
2711
- free(model_);
2712
- free(old_locale);
2713
- return NULL;
2872
+ EXIT_LOAD_MODEL()
2714
2873
  }
2715
2874
  }
2716
2875
 
@@ -2731,8 +2890,12 @@ struct model *load_model(const char *model_file_name)
2731
2890
  {
2732
2891
  int j;
2733
2892
  for(j=0; j<nr_w; j++)
2734
- fscanf(fp, "%lf ", &model_->w[i*nr_w+j]);
2735
- fscanf(fp, "\n");
2893
+ FSCANF(fp, "%lf ", &model_->w[i*nr_w+j]);
2894
+ if (fscanf(fp, "\n") !=0)
2895
+ {
2896
+ fprintf(stderr, "ERROR: fscanf failed to read the model\n");
2897
+ EXIT_LOAD_MODEL()
2898
+ }
2736
2899
  }
2737
2900
 
2738
2901
  setlocale(LC_ALL, old_locale);
@@ -2831,6 +2994,8 @@ void destroy_param(parameter* param)
2831
2994
  free(param->weight_label);
2832
2995
  if(param->weight != NULL)
2833
2996
  free(param->weight);
2997
+ if(param->init_sol != NULL)
2998
+ free(param->init_sol);
2834
2999
  }
2835
3000
 
2836
3001
  const char *check_parameter(const problem *prob, const parameter *param)
@@ -2857,6 +3022,10 @@ const char *check_parameter(const problem *prob, const parameter *param)
2857
3022
  && param->solver_type != L2R_L1LOSS_SVR_DUAL)
2858
3023
  return "unknown solver type";
2859
3024
 
3025
+ if(param->init_sol != NULL
3026
+ && param->solver_type != L2R_LR && param->solver_type != L2R_L2LOSS_SVC)
3027
+ return "Initial-solution specification supported only for solver L2R_LR and L2R_L2LOSS_SVC";
3028
+
2860
3029
  return NULL;
2861
3030
  }
2862
3031