liblinear-ruby 0.0.1

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +46 -0
  6. data/Rakefile +1 -0
  7. data/ext/Makefile +237 -0
  8. data/ext/blas.h +25 -0
  9. data/ext/blasp.h +430 -0
  10. data/ext/daxpy.c +49 -0
  11. data/ext/ddot.c +50 -0
  12. data/ext/dnrm2.c +62 -0
  13. data/ext/dscal.c +44 -0
  14. data/ext/extconf.rb +12 -0
  15. data/ext/liblinear_wrap.cxx +4646 -0
  16. data/ext/linear.cpp +2811 -0
  17. data/ext/linear.h +74 -0
  18. data/ext/linear.rb +357 -0
  19. data/ext/tron.cpp +235 -0
  20. data/ext/tron.h +34 -0
  21. data/lib/liblinear.rb +89 -0
  22. data/lib/liblinear/error.rb +4 -0
  23. data/lib/liblinear/model.rb +66 -0
  24. data/lib/liblinear/parameter.rb +42 -0
  25. data/lib/liblinear/problem.rb +55 -0
  26. data/lib/liblinear/version.rb +3 -0
  27. data/liblinear-1.93/COPYRIGHT +31 -0
  28. data/liblinear-1.93/Makefile +37 -0
  29. data/liblinear-1.93/Makefile.win +30 -0
  30. data/liblinear-1.93/README +531 -0
  31. data/liblinear-1.93/blas/Makefile +22 -0
  32. data/liblinear-1.93/blas/blas.a +0 -0
  33. data/liblinear-1.93/blas/blas.h +25 -0
  34. data/liblinear-1.93/blas/blasp.h +430 -0
  35. data/liblinear-1.93/blas/daxpy.c +49 -0
  36. data/liblinear-1.93/blas/daxpy.o +0 -0
  37. data/liblinear-1.93/blas/ddot.c +50 -0
  38. data/liblinear-1.93/blas/ddot.o +0 -0
  39. data/liblinear-1.93/blas/dnrm2.c +62 -0
  40. data/liblinear-1.93/blas/dnrm2.o +0 -0
  41. data/liblinear-1.93/blas/dscal.c +44 -0
  42. data/liblinear-1.93/blas/dscal.o +0 -0
  43. data/liblinear-1.93/heart_scale +270 -0
  44. data/liblinear-1.93/linear.cpp +2811 -0
  45. data/liblinear-1.93/linear.def +18 -0
  46. data/liblinear-1.93/linear.h +74 -0
  47. data/liblinear-1.93/linear.o +0 -0
  48. data/liblinear-1.93/matlab/Makefile +58 -0
  49. data/liblinear-1.93/matlab/README +197 -0
  50. data/liblinear-1.93/matlab/libsvmread.c +212 -0
  51. data/liblinear-1.93/matlab/libsvmwrite.c +106 -0
  52. data/liblinear-1.93/matlab/linear_model_matlab.c +176 -0
  53. data/liblinear-1.93/matlab/linear_model_matlab.h +2 -0
  54. data/liblinear-1.93/matlab/make.m +21 -0
  55. data/liblinear-1.93/matlab/predict.c +331 -0
  56. data/liblinear-1.93/matlab/train.c +418 -0
  57. data/liblinear-1.93/predict +0 -0
  58. data/liblinear-1.93/predict.c +245 -0
  59. data/liblinear-1.93/python/Makefile +4 -0
  60. data/liblinear-1.93/python/README +343 -0
  61. data/liblinear-1.93/python/liblinear.py +277 -0
  62. data/liblinear-1.93/python/liblinearutil.py +250 -0
  63. data/liblinear-1.93/ruby/liblinear.i +41 -0
  64. data/liblinear-1.93/ruby/liblinear_wrap.cxx +4646 -0
  65. data/liblinear-1.93/ruby/linear.h +74 -0
  66. data/liblinear-1.93/ruby/linear.o +0 -0
  67. data/liblinear-1.93/train +0 -0
  68. data/liblinear-1.93/train.c +399 -0
  69. data/liblinear-1.93/tron.cpp +235 -0
  70. data/liblinear-1.93/tron.h +34 -0
  71. data/liblinear-1.93/tron.o +0 -0
  72. data/liblinear-1.93/windows/liblinear.dll +0 -0
  73. data/liblinear-1.93/windows/libsvmread.mexw64 +0 -0
  74. data/liblinear-1.93/windows/libsvmwrite.mexw64 +0 -0
  75. data/liblinear-1.93/windows/predict.exe +0 -0
  76. data/liblinear-1.93/windows/predict.mexw64 +0 -0
  77. data/liblinear-1.93/windows/train.exe +0 -0
  78. data/liblinear-1.93/windows/train.mexw64 +0 -0
  79. data/liblinear-ruby.gemspec +24 -0
  80. metadata +152 -0
data/ext/tron.h ADDED
@@ -0,0 +1,34 @@
1
+ #ifndef _TRON_H
2
+ #define _TRON_H
3
+
4
+ class function
5
+ {
6
+ public:
7
+ virtual double fun(double *w) = 0 ;
8
+ virtual void grad(double *w, double *g) = 0 ;
9
+ virtual void Hv(double *s, double *Hs) = 0 ;
10
+
11
+ virtual int get_nr_variable(void) = 0 ;
12
+ virtual ~function(void){}
13
+ };
14
+
15
+ class TRON
16
+ {
17
+ public:
18
+ TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000);
19
+ ~TRON();
20
+
21
+ void tron(double *w);
22
+ void set_print_string(void (*i_print) (const char *buf));
23
+
24
+ private:
25
+ int trcg(double delta, double *g, double *s, double *r);
26
+ double norm_inf(int n, double *x);
27
+
28
+ double eps;
29
+ int max_iter;
30
+ function *fun_obj;
31
+ void info(const char *fmt,...);
32
+ void (*tron_print_string)(const char *buf);
33
+ };
34
+ #endif
data/lib/liblinear.rb ADDED
@@ -0,0 +1,89 @@
1
+ $: << File.expand_path(File.join(__FILE__, '..', '..', 'ext'))
2
+
3
+ require 'liblinearswig'
4
+ require 'liblinear/error'
5
+ require 'liblinear/model'
6
+ require 'liblinear/parameter'
7
+ require 'liblinear/problem'
8
+ require 'liblinear/version'
9
+
10
+ module Liblinear
11
+ #include Liblinearswig
12
+ # @param ruby_array [Array<Integer>]
13
+ # @return [SWIG::TYPE_p_int]
14
+ def new_int_array(ruby_array)
15
+ c_int_array = Liblinearswig.new_int(ruby_array.size)
16
+ ruby_array.size.times do |index|
17
+ Liblinearswig.int_setitem(c_int_array, index, ruby_array[index])
18
+ end
19
+ c_int_array
20
+ end
21
+
22
+ # @param c_array [SWIG::TYPE_p_int]
23
+ def free_int_array(c_array)
24
+ delete_int(c_array) unless c_array.nil?
25
+ end
26
+
27
+ # @param ruby_array [Array<Double>]
28
+ # @return [SWIG::TYPE_p_double]
29
+ def new_double_array(ruby_array)
30
+ c_double_array = Liblinearswig.new_double(ruby_array.size)
31
+ ruby_array.size.times do |index|
32
+ Liblinearswig.double_setitem(c_double_array, index, ruby_array[index])
33
+ end
34
+ c_double_array
35
+ end
36
+
37
+ # @param c_array [SWIG::TYPE_p_double]
38
+ def free_double_array(c_array)
39
+ delete_double(c_array) unless c_array.nil?
40
+ end
41
+
42
+ # @param c_array [SWIG::TYPE_p_int]
43
+ # @param size [Integer]
44
+ def int_array_c_to_ruby(c_array, size)
45
+ size.times.map {|index| int_getitem(c_array, index)}
46
+ end
47
+
48
+ # @param c_array [SWIG::TYPE_p_double]
49
+ # @param size [Integer]
50
+ def double_array_c_to_ruby(c_array, size)
51
+ size.times.map {|index| double_getitem(c_array, index)}
52
+ end
53
+
54
+ # @param example [Hash, Array]
55
+ # @param max_value_index [Integer]
56
+ # @param bias [Double]
57
+ # @return [Liblinearswig::Feature_node]
58
+ def convert_to_feature_node_array(example, max_value_index, bias = -1)
59
+ example_indexes = []
60
+ if example.is_a?(Hash)
61
+ example.each_key do |key|
62
+ example_indexes << key
63
+ end
64
+ elsif example.is_a?(Array)
65
+ example.each_index do |index|
66
+ example_indexes << index
67
+ end
68
+ else
69
+ raise TypeError, 'data must be a Hash or an Array'
70
+ end
71
+ example_indexes.sort!
72
+
73
+ if bias >= 0
74
+ feature_nodes = Liblinearswig.feature_node_array(example_indexes.size + 2)
75
+ Liblinearswig.feature_node_array_set(feature_nodes, example_indexes.size, max_value_index + 1, bias)
76
+ Liblinearswig.feature_node_array_set(feature_nodes, example_indexes.size + 1, -1, 0)
77
+ else
78
+ feature_nodes = Liblinearswig.feature_node_array(example_indexes.size + 1)
79
+ Liblinearswig.feature_node_array_set(feature_nodes, example_indexes.size, -1, 0)
80
+ end
81
+
82
+ f_index = 0
83
+ example_indexes.each do |e_index|
84
+ Liblinearswig.feature_node_array_set(feature_nodes, f_index, e_index, example[e_index])
85
+ f_index += 1
86
+ end
87
+ feature_nodes
88
+ end
89
+ end
@@ -0,0 +1,4 @@
1
+ module Liblinear
2
+ class InvalidParameter < StandardError
3
+ end
4
+ end
@@ -0,0 +1,66 @@
1
+ module Liblinear
2
+ class Model
3
+ include Liblinear
4
+ include Liblinearswig
5
+ attr_accessor :model
6
+
7
+ # @param arg_1 [LibLinear::Problem, String]
8
+ # @param arg_2 [Liblinear::Parameter]
9
+ def initialize(arg_1, arg_2 = nil)
10
+ if arg_2
11
+ unless arg_1.is_a?(Liblinear::Problem) && arg_2.is_a?(Liblinear::Parameter)
12
+ raise ArgumentError, 'arguments must be Liblinear::Problem and Liblinear::Parameter'
13
+ end
14
+ error_msg = check_parameter(arg_1.prob, arg_2.params)
15
+ raise InvalidParameter, error_msg if error_msg
16
+ @model = train(arg_1.prob, arg_2.params)
17
+ else
18
+ raise ArgumentError, 'argument must be String' unless arg_1.is_a?(String)
19
+ @model = load_model(arg_1)
20
+ end
21
+ end
22
+
23
+ # return [Integer]
24
+ def nr_class
25
+ get_nr_class(@model)
26
+ end
27
+
28
+ # return [Array<Integer>]
29
+ def labels
30
+ c_int_array = new_int(nr_class)
31
+ get_labels(@model, c_int_array)
32
+ labels = int_array_c_to_ruby(c_int_array, nr_class)
33
+ delete_int(c_int_array)
34
+ labels
35
+ end
36
+
37
+ # @param example [Array, Hash]
38
+ def predict(example)
39
+ feature_nodes = convert_to_feature_node_array(example, @model.nr_feature, @model.bias)
40
+ prediction = Liblinearswig.predict(@model, feature_nodes)
41
+ feature_node_array_destroy(feature_nodes)
42
+ prediction
43
+ end
44
+
45
+ # @param example [Array, Hash]
46
+ # @return [Hash]
47
+ def predict_probability(example)
48
+ feature_nodes = convert_to_feature_node_array(example, @model.nr_feature, @model.bias)
49
+ c_double_array = new_double_array(nr_class)
50
+ Liblinearswig.predict_probability(@model, feature_nodes, c_double_array)
51
+ probabilities = double_array_c_to_ruby(c_double_array, nr_class)
52
+ delete_double(c_double_array)
53
+ feature_node_array_destroy(feature_nodes)
54
+ probability_list = {}
55
+ labels.size.times do |i|
56
+ probability_list[labels[i]] = probabilities[i]
57
+ end
58
+ probability_list
59
+ end
60
+
61
+ # @param filename [String]
62
+ def save(filename)
63
+ save_model(filename, @model)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,42 @@
1
+ module Liblinear
2
+ class Parameter
3
+ include Liblinear
4
+ include Liblinearswig
5
+ attr_accessor :params
6
+
7
+ # @param params [Hash]
8
+ def initialize(params = {})
9
+ @params = Liblinearswig::Parameter.new
10
+ self.solver_type = 1
11
+ self.C = 1
12
+ self.eps = 0.1
13
+ self.p = 0.1
14
+ self.nr_weight = 0
15
+ self.weight_label = []
16
+ self.weight = []
17
+ params.each do |k, v|
18
+ self.send("#{k}=", v)
19
+ end
20
+ end
21
+
22
+ # @params weigt_label [Array<Integer>]
23
+ def weight_label=(weight_label)
24
+ free_int_array(@params.weight_label)
25
+ @params.weight_label = new_int_array(weight_label)
26
+ end
27
+
28
+ # @params weight [Array<Double>]
29
+ def weight=(weight)
30
+ free_double_array(@params.weight)
31
+ @params.weight = new_double_array(weight)
32
+ end
33
+
34
+ def method_missing(m, *args)
35
+ if m.to_s.index('=')
36
+ @params.send(m.to_sym, args.first)
37
+ else
38
+ @params.send(m.to_sym)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ module Liblinear
2
+ class Problem
3
+ include Liblinear
4
+ include Liblinearswig
5
+ attr_accessor :prob
6
+
7
+ # @param labels [Array<Double>]
8
+ # @param examples [Array<Double>, Array<Hash>]
9
+ # @param bias [Double]
10
+ def initialize(labels, examples, bias)
11
+ unless labels.size == examples.size
12
+ raise ArgumentError, 'labels and examples must be same size'
13
+ end
14
+ @prob = Liblinearswig::Problem.new
15
+ @c_label = new_double_array(labels)
16
+ @examples = examples
17
+ @bias = bias
18
+ @max_example_index = max_example_index
19
+ @example_matrix = feature_node_matrix(examples.size)
20
+ @c_example_array = []
21
+
22
+ set_example_matrix
23
+
24
+ @prob.tap do |p|
25
+ p.y = @c_label
26
+ p.x = @example_matrix
27
+ p.bias = bias
28
+ p.l = examples.size
29
+ p.n = @max_example_index
30
+ p.n += 1 if bias >= 0
31
+ end
32
+ end
33
+
34
+ # @return [Integer]
35
+ def max_example_index
36
+ max_example_index = 0
37
+ @examples.each do |example|
38
+ if example.is_a?(Hash)
39
+ max_example_index = [max_example_index, example.keys.max].max if example.size > 0
40
+ else
41
+ max_example_index = [max_example_index, example.size].max
42
+ end
43
+ end
44
+ max_example_index
45
+ end
46
+
47
+ def set_example_matrix
48
+ @examples.size.times do |index|
49
+ c_example = convert_to_feature_node_array(@examples[index], @max_example_index, @bias)
50
+ @c_example_array << c_example
51
+ feature_node_matrix_set(@example_matrix, index, c_example)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module Liblinear
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,31 @@
1
+
2
+ Copyright (c) 2007-2013 The LIBLINEAR Project.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in the
14
+ documentation and/or other materials provided with the distribution.
15
+
16
+ 3. Neither name of copyright holders nor the names of its contributors
17
+ may be used to endorse or promote products derived from this software
18
+ without specific prior written permission.
19
+
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
25
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,37 @@
1
+ CXX ?= g++
2
+ CC ?= gcc
3
+ CFLAGS = -Wall -Wconversion -O3 -fPIC
4
+ LIBS = blas/blas.a
5
+ SHVER = 1
6
+ OS = $(shell uname)
7
+ #LIBS = -lblas
8
+
9
+ all: train predict
10
+
11
+ lib: linear.o tron.o blas/blas.a
12
+ if [ "$(OS)" = "Darwin" ]; then \
13
+ SHARED_LIB_FLAG="-dynamiclib -Wl,-install_name,liblinear.so.$(SHVER)"; \
14
+ else \
15
+ SHARED_LIB_FLAG="-shared -Wl,-soname,liblinear.so.$(SHVER)"; \
16
+ fi; \
17
+ $(CXX) $${SHARED_LIB_FLAG} linear.o tron.o blas/blas.a -o liblinear.so.$(SHVER)
18
+
19
+ train: tron.o linear.o train.c blas/blas.a
20
+ $(CXX) $(CFLAGS) -o train train.c tron.o linear.o $(LIBS)
21
+
22
+ predict: tron.o linear.o predict.c blas/blas.a
23
+ $(CXX) $(CFLAGS) -o predict predict.c tron.o linear.o $(LIBS)
24
+
25
+ tron.o: tron.cpp tron.h
26
+ $(CXX) $(CFLAGS) -c -o tron.o tron.cpp
27
+
28
+ linear.o: linear.cpp linear.h
29
+ $(CXX) $(CFLAGS) -c -o linear.o linear.cpp
30
+
31
+ blas/blas.a: blas/*.c blas/*.h
32
+ make -C blas OPTFLAGS='$(CFLAGS)' CC='$(CC)';
33
+
34
+ clean:
35
+ make -C blas clean
36
+ make -C matlab clean
37
+ rm -f *~ tron.o linear.o train predict liblinear.so.$(SHVER)
@@ -0,0 +1,30 @@
1
+ #You must ensure nmake.exe, cl.exe, link.exe are in system path.
2
+ #VCVARS32.bat
3
+ #Under dosbox prompt
4
+ #nmake -f Makefile.win
5
+
6
+ ##########################################
7
+ CXX = cl.exe
8
+ CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE
9
+ TARGET = windows
10
+
11
+ all: $(TARGET)\train.exe $(TARGET)\predict.exe
12
+
13
+ $(TARGET)\train.exe: tron.obj linear.obj train.c blas\*.c
14
+ $(CXX) $(CFLAGS) -Fe$(TARGET)\train.exe tron.obj linear.obj train.c blas\*.c
15
+
16
+ $(TARGET)\predict.exe: tron.obj linear.obj predict.c blas\*.c
17
+ $(CXX) $(CFLAGS) -Fe$(TARGET)\predict.exe tron.obj linear.obj predict.c blas\*.c
18
+
19
+ linear.obj: linear.cpp linear.h
20
+ $(CXX) $(CFLAGS) -c linear.cpp
21
+
22
+ tron.obj: tron.cpp tron.h
23
+ $(CXX) $(CFLAGS) -c tron.cpp
24
+
25
+ lib: linear.cpp linear.h linear.def tron.obj
26
+ $(CXX) $(CFLAGS) -LD linear.cpp tron.obj blas\*.c -Fe$(TARGET)\liblinear -link -DEF:linear.def
27
+
28
+ clean:
29
+ -erase /Q *.obj $(TARGET)\.
30
+
@@ -0,0 +1,531 @@
1
+ LIBLINEAR is a simple package for solving large-scale regularized linear
2
+ classification and regression. It currently supports
3
+ - L2-regularized logistic regression/L2-loss support vector classification/L1-loss support vector classification
4
+ - L1-regularized L2-loss support vector classification/L1-regularized logistic regression
5
+ - L2-regularized L2-loss support vector regression/L1-loss support vector regression.
6
+ This document explains the usage of LIBLINEAR.
7
+
8
+ To get started, please read the ``Quick Start'' section first.
9
+ For developers, please check the ``Library Usage'' section to learn
10
+ how to integrate LIBLINEAR in your software.
11
+
12
+ Table of Contents
13
+ =================
14
+
15
+ - When to use LIBLINEAR but not LIBSVM
16
+ - Quick Start
17
+ - Installation
18
+ - `train' Usage
19
+ - `predict' Usage
20
+ - Examples
21
+ - Library Usage
22
+ - Building Windows Binaries
23
+ - Additional Information
24
+ - MATLAB/OCTAVE interface
25
+ - PYTHON interface
26
+
27
+ When to use LIBLINEAR but not LIBSVM
28
+ ====================================
29
+
30
+ There are some large data for which with/without nonlinear mappings
31
+ gives similar performances. Without using kernels, one can
32
+ efficiently train a much larger set via linear classification/regression.
33
+ These data usually have a large number of features. Document classification
34
+ is an example.
35
+
36
+ Warning: While generally liblinear is very fast, its default solver
37
+ may be slow under certain situations (e.g., data not scaled or C is
38
+ large). See Appendix B of our SVM guide about how to handle such
39
+ cases.
40
+ http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf
41
+
42
+ Warning: If you are a beginner and your data sets are not large, you
43
+ should consider LIBSVM first.
44
+
45
+ LIBSVM page:
46
+ http://www.csie.ntu.edu.tw/~cjlin/libsvm
47
+
48
+
49
+ Quick Start
50
+ ===========
51
+
52
+ See the section ``Installation'' for installing LIBLINEAR.
53
+
54
+ After installation, there are programs `train' and `predict' for
55
+ training and testing, respectively.
56
+
57
+ About the data format, please check the README file of LIBSVM. Note
58
+ that feature index must start from 1 (but not 0).
59
+
60
+ A sample classification data included in this package is `heart_scale'.
61
+
62
+ Type `train heart_scale', and the program will read the training
63
+ data and output the model file `heart_scale.model'. If you have a test
64
+ set called heart_scale.t, then type `predict heart_scale.t
65
+ heart_scale.model output' to see the prediction accuracy. The `output'
66
+ file contains the predicted class labels.
67
+
68
+ For more information about `train' and `predict', see the sections
69
+ `train' Usage and `predict' Usage.
70
+
71
+ To obtain good performances, sometimes one needs to scale the
72
+ data. Please check the program `svm-scale' of LIBSVM. For large and
73
+ sparse data, use `-l 0' to keep the sparsity.
74
+
75
+ Installation
76
+ ============
77
+
78
+ On Unix systems, type `make' to build the `train' and `predict'
79
+ programs. Run them without arguments to show the usages.
80
+
81
+ On other systems, consult `Makefile' to build them (e.g., see
82
+ 'Building Windows binaries' in this file) or use the pre-built
83
+ binaries (Windows binaries are in the directory `windows').
84
+
85
+ This software uses some level-1 BLAS subroutines. The needed functions are
86
+ included in this package. If a BLAS library is available on your
87
+ machine, you may use it by modifying the Makefile: Unmark the following line
88
+
89
+ #LIBS ?= -lblas
90
+
91
+ and mark
92
+
93
+ LIBS ?= blas/blas.a
94
+
95
+ `train' Usage
96
+ =============
97
+
98
+ Usage: train [options] training_set_file [model_file]
99
+ options:
100
+ -s type : set type of solver (default 1)
101
+ for multi-class classification
102
+ 0 -- L2-regularized logistic regression (primal)
103
+ 1 -- L2-regularized L2-loss support vector classification (dual)
104
+ 2 -- L2-regularized L2-loss support vector classification (primal)
105
+ 3 -- L2-regularized L1-loss support vector classification (dual)
106
+ 4 -- support vector classification by Crammer and Singer
107
+ 5 -- L1-regularized L2-loss support vector classification
108
+ 6 -- L1-regularized logistic regression
109
+ 7 -- L2-regularized logistic regression (dual)
110
+ for regression
111
+ 11 -- L2-regularized L2-loss support vector regression (primal)
112
+ 12 -- L2-regularized L2-loss support vector regression (dual)
113
+ 13 -- L2-regularized L1-loss support vector regression (dual)
114
+ -c cost : set the parameter C (default 1)
115
+ -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
116
+ -e epsilon : set tolerance of termination criterion
117
+ -s 0 and 2
118
+ |f'(w)|_2 <= eps*min(pos,neg)/l*|f'(w0)|_2,
119
+ where f is the primal function and pos/neg are # of
120
+ positive/negative data (default 0.01)
121
+ -s 11
122
+ |f'(w)|_2 <= eps*|f'(w0)|_2 (default 0.001)
123
+ -s 1, 3, 4 and 7
124
+ Dual maximal violation <= eps; similar to libsvm (default 0.1)
125
+ -s 5 and 6
126
+ |f'(w)|_inf <= eps*min(pos,neg)/l*|f'(w0)|_inf,
127
+ where f is the primal function (default 0.01)
128
+ -s 12 and 13\n"
129
+ |f'(alpha)|_1 <= eps |f'(alpha0)|,
130
+ where f is the dual function (default 0.1)
131
+ -B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)
132
+ -wi weight: weights adjust the parameter C of different classes (see README for details)
133
+ -v n: n-fold cross validation mode
134
+ -q : quiet mode (no outputs)
135
+
136
+ Option -v randomly splits the data into n parts and calculates cross
137
+ validation accuracy on them.
138
+
139
+ Formulations:
140
+
141
+ For L2-regularized logistic regression (-s 0), we solve
142
+
143
+ min_w w^Tw/2 + C \sum log(1 + exp(-y_i w^Tx_i))
144
+
145
+ For L2-regularized L2-loss SVC dual (-s 1), we solve
146
+
147
+ min_alpha 0.5(alpha^T (Q + I/2/C) alpha) - e^T alpha
148
+ s.t. 0 <= alpha_i,
149
+
150
+ For L2-regularized L2-loss SVC (-s 2), we solve
151
+
152
+ min_w w^Tw/2 + C \sum max(0, 1- y_i w^Tx_i)^2
153
+
154
+ For L2-regularized L1-loss SVC dual (-s 3), we solve
155
+
156
+ min_alpha 0.5(alpha^T Q alpha) - e^T alpha
157
+ s.t. 0 <= alpha_i <= C,
158
+
159
+ For L1-regularized L2-loss SVC (-s 5), we solve
160
+
161
+ min_w \sum |w_j| + C \sum max(0, 1- y_i w^Tx_i)^2
162
+
163
+ For L1-regularized logistic regression (-s 6), we solve
164
+
165
+ min_w \sum |w_j| + C \sum log(1 + exp(-y_i w^Tx_i))
166
+
167
+ For L2-regularized logistic regression (-s 7), we solve
168
+
169
+ min_alpha 0.5(alpha^T Q alpha) + \sum alpha_i*log(alpha_i) + \sum (C-alpha_i)*log(C-alpha_i) - a constant
170
+ s.t. 0 <= alpha_i <= C,
171
+
172
+ where
173
+
174
+ Q is a matrix with Q_ij = y_i y_j x_i^T x_j.
175
+
176
+ For L2-regularized L2-loss SVR (-s 11), we solve
177
+
178
+ min_w w^Tw/2 + C \sum max(0, |y_i-w^Tx_i|-epsilon)^2
179
+
180
+ For L2-regularized L2-loss SVR dual (-s 12), we solve
181
+
182
+ min_beta 0.5(beta^T (Q + lambda I/2/C) beta) - y^T beta + \sum |beta_i|
183
+
184
+ For L2-regularized L1-loss SVR dual (-s 13), we solve
185
+
186
+ min_beta 0.5(beta^T Q beta) - y^T beta + \sum |beta_i|
187
+ s.t. -C <= beta_i <= C,
188
+
189
+ where
190
+
191
+ Q is a matrix with Q_ij = x_i^T x_j.
192
+
193
+ If bias >= 0, w becomes [w; w_{n+1}] and x becomes [x; bias].
194
+
195
+ The primal-dual relationship implies that -s 1 and -s 2 give the same
196
+ model, -s 0 and -s 7 give the same, and -s 11 and -s 12 give the same.
197
+
198
+ We implement 1-vs-the rest multi-class strategy for classification.
199
+ In training i vs. non_i, their C parameters are (weight from -wi)*C
200
+ and C, respectively. If there are only two classes, we train only one
201
+ model. Thus weight1*C vs. weight2*C is used. See examples below.
202
+
203
+ We also implement multi-class SVM by Crammer and Singer (-s 4):
204
+
205
+ min_{w_m, \xi_i} 0.5 \sum_m ||w_m||^2 + C \sum_i \xi_i
206
+ s.t. w^T_{y_i} x_i - w^T_m x_i >= \e^m_i - \xi_i \forall m,i
207
+
208
+ where e^m_i = 0 if y_i = m,
209
+ e^m_i = 1 if y_i != m,
210
+
211
+ Here we solve the dual problem:
212
+
213
+ min_{\alpha} 0.5 \sum_m ||w_m(\alpha)||^2 + \sum_i \sum_m e^m_i alpha^m_i
214
+ s.t. \alpha^m_i <= C^m_i \forall m,i , \sum_m \alpha^m_i=0 \forall i
215
+
216
+ where w_m(\alpha) = \sum_i \alpha^m_i x_i,
217
+ and C^m_i = C if m = y_i,
218
+ C^m_i = 0 if m != y_i.
219
+
220
+ `predict' Usage
221
+ ===============
222
+
223
+ Usage: predict [options] test_file model_file output_file
224
+ options:
225
+ -b probability_estimates: whether to output probability estimates, 0 or 1 (default 0); currently for logistic regression only
226
+ -q : quiet mode (no outputs)
227
+
228
+ Note that -b is only needed in the prediction phase. This is different
229
+ from the setting of LIBSVM.
230
+
231
+ Examples
232
+ ========
233
+
234
+ > train data_file
235
+
236
+ Train linear SVM with L2-loss function.
237
+
238
+ > train -s 0 data_file
239
+
240
+ Train a logistic regression model.
241
+
242
+ > train -v 5 -e 0.001 data_file
243
+
244
+ Do five-fold cross-validation using L2-loss svm.
245
+ Use a smaller stopping tolerance 0.001 than the default
246
+ 0.1 if you want more accurate solutions.
247
+
248
+ > train -c 10 -w1 2 -w2 5 -w3 2 four_class_data_file
249
+
250
+ Train four classifiers:
251
+ positive negative Cp Cn
252
+ class 1 class 2,3,4. 20 10
253
+ class 2 class 1,3,4. 50 10
254
+ class 3 class 1,2,4. 20 10
255
+ class 4 class 1,2,3. 10 10
256
+
257
+ > train -c 10 -w3 1 -w2 5 two_class_data_file
258
+
259
+ If there are only two classes, we train ONE model.
260
+ The C values for the two classes are 10 and 50.
261
+
262
+ > predict -b 1 test_file data_file.model output_file
263
+
264
+ Output probability estimates (for logistic regression only).
265
+
266
+ Library Usage
267
+ =============
268
+
269
+ - Function: model* train(const struct problem *prob,
270
+ const struct parameter *param);
271
+
272
+ This function constructs and returns a linear classification
273
+ or regression model according to the given training data and
274
+ parameters.
275
+
276
+ struct problem describes the problem:
277
+
278
+ struct problem
279
+ {
280
+ int l, n;
281
+ int *y;
282
+ struct feature_node **x;
283
+ double bias;
284
+ };
285
+
286
+ where `l' is the number of training data. If bias >= 0, we assume
287
+ that one additional feature is added to the end of each data
288
+ instance. `n' is the number of feature (including the bias feature
289
+ if bias >= 0). `y' is an array containing the target values. (integers
290
+ in classification, real numbers in regression) And `x' is an array
291
+ of pointers, each of which points to a sparse representation (array
292
+ of feature_node) of one training vector.
293
+
294
+ For example, if we have the following training data:
295
+
296
+ LABEL ATTR1 ATTR2 ATTR3 ATTR4 ATTR5
297
+ ----- ----- ----- ----- ----- -----
298
+ 1 0 0.1 0.2 0 0
299
+ 2 0 0.1 0.3 -1.2 0
300
+ 1 0.4 0 0 0 0
301
+ 2 0 0.1 0 1.4 0.5
302
+ 3 -0.1 -0.2 0.1 1.1 0.1
303
+
304
+ and bias = 1, then the components of problem are:
305
+
306
+ l = 5
307
+ n = 6
308
+
309
+ y -> 1 2 1 2 3
310
+
311
+ x -> [ ] -> (2,0.1) (3,0.2) (6,1) (-1,?)
312
+ [ ] -> (2,0.1) (3,0.3) (4,-1.2) (6,1) (-1,?)
313
+ [ ] -> (1,0.4) (6,1) (-1,?)
314
+ [ ] -> (2,0.1) (4,1.4) (5,0.5) (6,1) (-1,?)
315
+ [ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (6,1) (-1,?)
316
+
317
+ struct parameter describes the parameters of a linear classification
318
+ or regression model:
319
+
320
+ struct parameter
321
+ {
322
+ int solver_type;
323
+
324
+ /* these are for training only */
325
+ double eps; /* stopping criteria */
326
+ double C;
327
+ int nr_weight;
328
+ int *weight_label;
329
+ double* weight;
330
+ double p;
331
+ };
332
+
333
+ solver_type can be one of L2R_LR, L2R_L2LOSS_SVC_DUAL, L2R_L2LOSS_SVC, L2R_L1LOSS_SVC_DUAL, MCSVM_CS, L1R_L2LOSS_SVC, L1R_LR, L2R_LR_DUAL, L2R_L2LOSS_SVR, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL.
334
+ for classification
335
+ L2R_LR L2-regularized logistic regression (primal)
336
+ L2R_L2LOSS_SVC_DUAL L2-regularized L2-loss support vector classification (dual)
337
+ L2R_L2LOSS_SVC L2-regularized L2-loss support vector classification (primal)
338
+ L2R_L1LOSS_SVC_DUAL L2-regularized L1-loss support vector classification (dual)
339
+ MCSVM_CS support vector classification by Crammer and Singer
340
+ L1R_L2LOSS_SVC L1-regularized L2-loss support vector classification
341
+ L1R_LR L1-regularized logistic regression
342
+ L2R_LR_DUAL L2-regularized logistic regression (dual)
343
+ for regression
344
+ L2R_L2LOSS_SVR L2-regularized L2-loss support vector regression (primal)
345
+ L2R_L2LOSS_SVR_DUAL L2-regularized L2-loss support vector regression (dual)
346
+ L2R_L1LOSS_SVR_DUAL L2-regularized L1-loss support vector regression (dual)
347
+
348
+ C is the cost of constraints violation.
349
+ p is the sensitiveness of loss of support vector regression.
350
+ eps is the stopping criterion.
351
+
352
+ nr_weight, weight_label, and weight are used to change the penalty
353
+ for some classes (If the weight for a class is not changed, it is
354
+ set to 1). This is useful for training classifier using unbalanced
355
+ input data or with asymmetric misclassification cost.
356
+
357
+ nr_weight is the number of elements in the array weight_label and
358
+ weight. Each weight[i] corresponds to weight_label[i], meaning that
359
+ the penalty of class weight_label[i] is scaled by a factor of weight[i].
360
+
361
+ If you do not want to change penalty for any of the classes,
362
+ just set nr_weight to 0.
363
+
364
+ *NOTE* To avoid wrong parameters, check_parameter() should be
365
+ called before train().
366
+
367
+ struct model stores the model obtained from the training procedure:
368
+
369
+ struct model
370
+ {
371
+ struct parameter param;
372
+ int nr_class; /* number of classes */
373
+ int nr_feature;
374
+ double *w;
375
+ int *label; /* label of each class */
376
+ double bias;
377
+ };
378
+
379
+ param describes the parameters used to obtain the model.
380
+
381
+ nr_class and nr_feature are the number of classes and features,
382
+ respectively. nr_class = 2 for regression.
383
+
384
+ The nr_feature*nr_class array w gives feature weights. We use one
385
+ against the rest for multi-class classification, so each feature
386
+ index corresponds to nr_class weight values. Weights are
387
+ organized in the following way
388
+
389
+ +------------------+------------------+------------+
390
+ | nr_class weights | nr_class weights | ...
391
+ | for 1st feature | for 2nd feature |
392
+ +------------------+------------------+------------+
393
+
394
+ If bias >= 0, x becomes [x; bias]. The number of features is
395
+ increased by one, so w is a (nr_feature+1)*nr_class array. The
396
+ value of bias is stored in the variable bias.
397
+
398
+ The array label stores class labels.
399
+
400
+ - Function: void cross_validation(const problem *prob, const parameter *param, int nr_fold, double *target);
401
+
402
+ This function conducts cross validation. Data are separated to
403
+ nr_fold folds. Under given parameters, sequentially each fold is
404
+ validated using the model from training the remaining. Predicted
405
+ labels in the validation process are stored in the array called
406
+ target.
407
+
408
+ The format of prob is same as that for train().
409
+
410
+ - Function: double predict(const model *model_, const feature_node *x);
411
+
412
+ For a classification model, the predicted class for x is returned.
413
+ For a regression model, the function value of x calculated using
414
+ the model is returned.
415
+
416
+ - Function: double predict_values(const struct model *model_,
417
+ const struct feature_node *x, double* dec_values);
418
+
419
+ This function gives nr_w decision values in the array dec_values.
420
+ nr_w=1 if regression is applied or the number of classes is two. An exception is
421
+ multi-class svm by Crammer and Singer (-s 4), where nr_w = 2 if there are two classes. For all other situations, nr_w is the
422
+ number of classes.
423
+
424
+ We implement one-vs-the rest multi-class strategy (-s 0,1,2,3,5,6,7)
425
+ and multi-class svm by Crammer and Singer (-s 4) for multi-class SVM.
426
+ The class with the highest decision value is returned.
427
+
428
+ - Function: double predict_probability(const struct model *model_,
429
+ const struct feature_node *x, double* prob_estimates);
430
+
431
+ This function gives nr_class probability estimates in the array
432
+ prob_estimates. nr_class can be obtained from the function
433
+ get_nr_class. The class with the highest probability is
434
+ returned. Currently, we support only the probability outputs of
435
+ logistic regression.
436
+
437
+ - Function: int get_nr_feature(const model *model_);
438
+
439
+ The function gives the number of attributes of the model.
440
+
441
+ - Function: int get_nr_class(const model *model_);
442
+
443
+ The function gives the number of classes of the model.
444
+ For a regression model, 2 is returned.
445
+
446
+ - Function: void get_labels(const model *model_, int* label);
447
+
448
+ This function outputs the name of labels into an array called label.
449
+ For a regression model, label is unchanged.
450
+
451
+ - Function: const char *check_parameter(const struct problem *prob,
452
+ const struct parameter *param);
453
+
454
+ This function checks whether the parameters are within the feasible
455
+ range of the problem. This function should be called before calling
456
+ train() and cross_validation(). It returns NULL if the
457
+ parameters are feasible, otherwise an error message is returned.
458
+
459
+ - Function: int save_model(const char *model_file_name,
460
+ const struct model *model_);
461
+
462
+ This function saves a model to a file; returns 0 on success, or -1
463
+ if an error occurs.
464
+
465
+ - Function: struct model *load_model(const char *model_file_name);
466
+
467
+ This function returns a pointer to the model read from the file,
468
+ or a null pointer if the model could not be loaded.
469
+
470
+ - Function: void free_model_content(struct model *model_ptr);
471
+
472
+ This function frees the memory used by the entries in a model structure.
473
+
474
+ - Function: void free_and_destroy_model(struct model **model_ptr_ptr);
475
+
476
+ This function frees the memory used by a model and destroys the model
477
+ structure.
478
+
479
+ - Function: void destroy_param(struct parameter *param);
480
+
481
+ This function frees the memory used by a parameter set.
482
+
483
+ - Function: void set_print_string_function(void (*print_func)(const char *));
484
+
485
+ Users can specify their output format by a function. Use
486
+ set_print_string_function(NULL);
487
+ for default printing to stdout.
488
+
489
+ Building Windows Binaries
490
+ =========================
491
+
492
+ Windows binaries are in the directory `windows'. To build them via
493
+ Visual C++, use the following steps:
494
+
495
+ 1. Open a dos command box and change to liblinear directory. If
496
+ environment variables of VC++ have not been set, type
497
+
498
+ "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
499
+
500
+ You may have to modify the above command according which version of
501
+ VC++ or where it is installed.
502
+
503
+ 2. Type
504
+
505
+ nmake -f Makefile.win clean all
506
+
507
+
508
+ MATLAB/OCTAVE Interface
509
+ =======================
510
+
511
+ Please check the file README in the directory `matlab'.
512
+
513
+ PYTHON Interface
514
+ ================
515
+
516
+ Please check the file README in the directory `python'.
517
+
518
+ Additional Information
519
+ ======================
520
+
521
+ If you find LIBLINEAR helpful, please cite it as
522
+
523
+ R.-E. Fan, K.-W. Chang, C.-J. Hsieh, X.-R. Wang, and C.-J. Lin.
524
+ LIBLINEAR: A Library for Large Linear Classification, Journal of
525
+ Machine Learning Research 9(2008), 1871-1874. Software available at
526
+ http://www.csie.ntu.edu.tw/~cjlin/liblinear
527
+
528
+ For any questions and comments, please send your email to
529
+ cjlin@csie.ntu.edu.tw
530
+
531
+