rumale-svm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'numo/libsvm'
4
+ require 'rumale/base/base_estimator'
5
+ require 'rumale/base/regressor'
6
+
7
+ module Rumale
8
+ module SVM
9
+ # NuSVR is a class that provides Kernel Nu-Support Vector Regressor in LIBSVM with Rumale interface.
10
+ #
11
+ # @example
12
+ # estimator = Rumale::SVM::NuSVR.new(nu: 0.5, kernel: 'rbf', gamma: 10.0, random_seed: 1)
13
+ # estimator.fit(training_samples, traininig_target_values)
14
+ # results = estimator.predict(testing_samples)
15
+ class NuSVR
16
+ include Base::BaseEstimator
17
+ include Base::Regressor
18
+
19
+ # Create a new regressor with Kernel Nu-Support Vector Regressor.
20
+ #
21
+ # @param nu [Float] The regularization parameter. The interval of nu is (0, 1].
22
+ # @param kernel [String] The type of kernel function ('rbf', 'linear', 'poly', 'sigmoid', and 'precomputed').
23
+ # @param degree [Integer] The degree parameter in polynomial kernel function.
24
+ # @param gamma [Float] The gamma parameter in rbf/poly/sigmoid kernel function.
25
+ # @param coef0 [Float] The coefficient in poly/sigmoid kernel function.
26
+ # @param shrinking [Boolean] The flag indicating whether to use the shrinking heuristics.
27
+ # @param cache_size [Float] The cache memory size in MB.
28
+ # @param tol [Float] The tolerance of termination criterion.
29
+ # @param verbose [Boolean] The flag indicating whether to output learning process message
30
+ # @param random_seed [Integer/Nil] The seed value using to initialize the random generator.
31
+ def initialize(nu: 0.5, kernel: 'rbf', degree: 3, gamma: 1.0, coef0: 0.0,
32
+ shrinking: true, cache_size: 200.0, tol: 1e-3, verbose: false, random_seed: nil)
33
+ check_params_float(nu: nu, gamma: gamma, coef0: coef0, cache_size: cache_size, tol: tol)
34
+ check_params_integer(degree: degree)
35
+ check_params_boolean(shrinking: shrinking, verbose: verbose)
36
+ check_params_type_or_nil(Integer, random_seed: random_seed)
37
+ @params = {}
38
+ @params[:nu] = nu
39
+ @params[:kernel] = kernel
40
+ @params[:degree] = degree
41
+ @params[:gamma] = gamma
42
+ @params[:coef0] = coef0
43
+ @params[:shrinking] = shrinking
44
+ @params[:cache_size] = cache_size
45
+ @params[:tol] = tol
46
+ @params[:verbose] = verbose
47
+ @params[:random_seed] = random_seed
48
+ @model = nil
49
+ end
50
+
51
+ # Fit the model with given training data.
52
+ #
53
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
54
+ # If the kernel is 'precomputed', x must be a square distance matrix (shape: [n_samples, n_samples]).
55
+ # @param y [Numo::DFloat] (shape: [n_samples]) The target values to be used for fitting the model.
56
+ # @return [NuSVR] The learned regressor itself.
57
+ def fit(x, y)
58
+ check_sample_array(x)
59
+ check_tvalue_array(y)
60
+ check_sample_tvalue_size(x, y)
61
+ xx = precomputed_kernel? ? add_index_col(x) : x
62
+ @model = Numo::Libsvm.train(xx, y, libsvm_params)
63
+ self
64
+ end
65
+
66
+ # Predict values for samples.
67
+ #
68
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
69
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
70
+ # @return [Numo::DFloat] (shape: [n_samples]) Predicted value per sample.
71
+ def predict(x)
72
+ check_sample_array(x)
73
+ xx = precomputed_kernel? ? add_index_col(x) : x
74
+ Numo::Libsvm.predict(xx, libsvm_params, @model)
75
+ end
76
+
77
+ # Dump marshal data.
78
+ # @return [Hash] The marshal data about SVR.
79
+ def marshal_dump
80
+ { params: @params,
81
+ model: @model }
82
+ end
83
+
84
+ # Load marshal data.
85
+ # @return [nil]
86
+ def marshal_load(obj)
87
+ @params = obj[:params]
88
+ @model = obj[:model]
89
+ nil
90
+ end
91
+
92
+ # Return the indices of support vectors.
93
+ # @return [Numo::Int32] (shape: [n_support_vectors])
94
+ def support
95
+ @model[:sv_indices]
96
+ end
97
+
98
+ # Return the support_vectors.
99
+ # @return [Numo::DFloat] (shape: [n_support_vectors, n_features])
100
+ def support_vectors
101
+ precomputed_kernel? ? del_index_col(@model[:SV]) : @model[:SV]
102
+ end
103
+
104
+ # Return the number of support vectors.
105
+ # @return [Integer]
106
+ def n_support
107
+ support.size
108
+ end
109
+
110
+ # Return the coefficients of the support vector in decision function.
111
+ # @return [Numo::DFloat] (shape: [1, n_support_vectors])
112
+ def duel_coef
113
+ @model[:sv_coef]
114
+ end
115
+
116
+ # Return the intercepts in decision function.
117
+ # @return [Numo::DFloat] (shape: [1])
118
+ def intercept
119
+ @model[:rho]
120
+ end
121
+
122
+ private
123
+
124
+ def add_index_col(x)
125
+ idx = Numo::Int32.new(x.shape[0]).seq + 1
126
+ Numo::NArray.hstack([idx.expand_dims(1), x])
127
+ end
128
+
129
+ def del_index_col(x)
130
+ x[true, 1..-1].dup
131
+ end
132
+
133
+ def precomputed_kernel?
134
+ @params[:kernel] == 'precomputed'
135
+ end
136
+
137
+ def libsvm_params
138
+ res = @params.merge(svm_type: Numo::Libsvm::SvmType::EPSILON_SVR)
139
+ res[:kernel_type] = case res.delete(:kernel)
140
+ when 'linear'
141
+ Numo::Libsvm::KernelType::LINEAR
142
+ when 'poly'
143
+ Numo::Libsvm::KernelType::POLY
144
+ when 'sigmoid'
145
+ Numo::Libsvm::KernelType::SIGMOID
146
+ when 'precomputed'
147
+ Numo::Libsvm::KernelType::PRECOMPUTED
148
+ else
149
+ Numo::Libsvm::KernelType::RBF
150
+ end
151
+ res[:eps] = res.delete(:tol)
152
+ res
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'numo/libsvm'
4
+ require 'rumale/base/base_estimator'
5
+ require 'rumale/validation'
6
+
7
+ module Rumale
8
+ module SVM
9
+ # OneClassSVM is a class that provides One-class Support Vector Machine in LIBSVM with Rumale interface.
10
+ #
11
+ # @example
12
+ # estimator = Rumale::SVM::OneClassSVM.new(nu: 0.5, kernel: 'rbf', gamma: 10.0, random_seed: 1)
13
+ # estimator.fit(training_samples, traininig_labels)
14
+ # results = estimator.predict(testing_samples)
15
+ class OneClassSVM
16
+ include Base::BaseEstimator
17
+ include Validation
18
+
19
+ # Create a new estimator with One-class Support Vector Machine.
20
+ #
21
+ # @param nu [Float] The regularization parameter. The interval of nu is (0, 1].
22
+ # @param kernel [String] The type of kernel function ('rbf', 'linear', 'poly', 'sigmoid', and 'precomputed').
23
+ # @param degree [Integer] The degree parameter in polynomial kernel function.
24
+ # @param gamma [Float] The gamma parameter in rbf/poly/sigmoid kernel function.
25
+ # @param coef0 [Float] The coefficient in poly/sigmoid kernel function.
26
+ # @param shrinking [Boolean] The flag indicating whether to use the shrinking heuristics.
27
+ # @param cache_size [Float] The cache memory size in MB.
28
+ # @param tol [Float] The tolerance of termination criterion.
29
+ # @param verbose [Boolean] The flag indicating whether to output learning process message
30
+ # @param random_seed [Integer/Nil] The seed value using to initialize the random generator.
31
+ def initialize(nu: 1.0, kernel: 'rbf', degree: 3, gamma: 1.0, coef0: 0.0,
32
+ shrinking: true, cache_size: 200.0, tol: 1e-3, verbose: false, random_seed: nil)
33
+ check_params_float(nu: nu, gamma: gamma, coef0: coef0, cache_size: cache_size, tol: tol)
34
+ check_params_integer(degree: degree)
35
+ check_params_boolean(shrinking: shrinking, verbose: verbose)
36
+ check_params_type_or_nil(Integer, random_seed: random_seed)
37
+ @params = {}
38
+ @params[:nu] = nu
39
+ @params[:kernel] = kernel
40
+ @params[:degree] = degree
41
+ @params[:gamma] = gamma
42
+ @params[:coef0] = coef0
43
+ @params[:shrinking] = shrinking
44
+ @params[:cache_size] = cache_size
45
+ @params[:tol] = tol
46
+ @params[:verbose] = verbose
47
+ @params[:random_seed] = random_seed
48
+ @model = nil
49
+ end
50
+
51
+ # Fit the model with given training data.
52
+ #
53
+ # @overload fit(x) -> OneClassSVM
54
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
55
+ # If the kernel is 'precomputed', x must be a square distance matrix (shape: [n_samples, n_samples]).
56
+ # @return [OneClassSVM] The learned estimator itself.
57
+ def fit(x, _y = nil)
58
+ check_sample_array(x)
59
+ dummy = Numo::DFloat.ones(x.shape[0])
60
+ @model = Numo::Libsvm.train(x, dummy, libsvm_params)
61
+ self
62
+ end
63
+
64
+ # Calculate confidence scores for samples.
65
+ #
66
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
67
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
68
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Confidence score per sample.
69
+ def decision_function(x)
70
+ check_sample_array(x)
71
+ Numo::Libsvm.decision_function(x, libsvm_params, @model)
72
+ end
73
+
74
+ # Predict class labels for samples.
75
+ #
76
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
77
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
78
+ # @return [Numo::Int32] (shape: [n_samples]) Predicted label per sample.
79
+ def predict(x)
80
+ check_sample_array(x)
81
+ Numo::Int32.cast(Numo::Libsvm.predict(x, libsvm_params, @model))
82
+ end
83
+
84
+ # Dump marshal data.
85
+ # @return [Hash] The marshal data about SVC.
86
+ def marshal_dump
87
+ { params: @params,
88
+ model: @model }
89
+ end
90
+
91
+ # Load marshal data.
92
+ # @return [nil]
93
+ def marshal_load(obj)
94
+ @params = obj[:params]
95
+ @model = obj[:model]
96
+ nil
97
+ end
98
+
99
+ # Return the indices of support vectors.
100
+ # @return [Numo::Int32] (shape: [n_support_vectors])
101
+ def support
102
+ @model[:sv_indices]
103
+ end
104
+
105
+ # Return the support_vectors.
106
+ # @return [Numo::DFloat] (shape: [n_support_vectors, n_features])
107
+ def support_vectors
108
+ @model[:SV]
109
+ end
110
+
111
+ # Return the number of support vectors.
112
+ # @return [Integer]
113
+ def n_support
114
+ @model[:sv_indices].size
115
+ end
116
+
117
+ # Return the coefficients of the support vector in decision function.
118
+ # @return [Numo::DFloat] (shape: [1, n_support_vectors])
119
+ def duel_coef
120
+ @model[:sv_coef]
121
+ end
122
+
123
+ # Return the intercepts in decision function.
124
+ # @return [Numo::DFloat] (shape: [1])
125
+ def intercept
126
+ @model[:rho]
127
+ end
128
+
129
+ private
130
+
131
+ def libsvm_params
132
+ res = @params.merge(svm_type: Numo::Libsvm::SvmType::ONE_CLASS)
133
+ res[:kernel_type] = case res.delete(:kernel)
134
+ when 'linear'
135
+ Numo::Libsvm::KernelType::LINEAR
136
+ when 'poly'
137
+ Numo::Libsvm::KernelType::POLY
138
+ when 'sigmoid'
139
+ Numo::Libsvm::KernelType::SIGMOID
140
+ when 'precomputed'
141
+ Numo::Libsvm::KernelType::PRECOMPUTED
142
+ else
143
+ Numo::Libsvm::KernelType::RBF
144
+ end
145
+ res[:eps] = res.delete(:tol)
146
+ res
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'numo/libsvm'
4
+ require 'rumale/base/base_estimator'
5
+ require 'rumale/base/classifier'
6
+
7
+ module Rumale
8
+ module SVM
9
+ # SVC is a class that provides Kernel C-Support Vector Classifier in LIBSVM with Rumale interface.
10
+ #
11
+ # @example
12
+ # estimator = Rumale::SVM::SVC.new(reg_param: 1.0, kernel: 'rbf', gamma: 10.0, random_seed: 1)
13
+ # estimator.fit(training_samples, traininig_labels)
14
+ # results = estimator.predict(testing_samples)
15
+ class SVC
16
+ include Base::BaseEstimator
17
+ include Base::Classifier
18
+
19
+ # Create a new classifier with Kernel C-Support Vector Classifier.
20
+ #
21
+ # @param reg_param [Float] The regularization parameter.
22
+ # @param kernel [String] The type of kernel function ('rbf', 'linear', 'poly', 'sigmoid', and 'precomputed').
23
+ # @param degree [Integer] The degree parameter in polynomial kernel function.
24
+ # @param gamma [Float] The gamma parameter in rbf/poly/sigmoid kernel function.
25
+ # @param coef0 [Float] The coefficient in poly/sigmoid kernel function.
26
+ # @param shrinking [Boolean] The flag indicating whether to use the shrinking heuristics.
27
+ # @param probability [Boolean] The flag indicating whether to train the parameter for probability estimation.
28
+ # @param cache_size [Float] The cache memory size in MB.
29
+ # @param tol [Float] The tolerance of termination criterion.
30
+ # @param verbose [Boolean] The flag indicating whether to output learning process message
31
+ # @param random_seed [Integer/Nil] The seed value using to initialize the random generator.
32
+ def initialize(reg_param: 1.0, kernel: 'rbf', degree: 3, gamma: 1.0, coef0: 0.0,
33
+ shrinking: true, probability: true, cache_size: 200.0, tol: 1e-3, verbose: false, random_seed: nil)
34
+ check_params_float(reg_param: reg_param, gamma: gamma, coef0: coef0, cache_size: cache_size, tol: tol)
35
+ check_params_integer(degree: degree)
36
+ check_params_boolean(shrinking: shrinking, probability: probability, verbose: verbose)
37
+ check_params_type_or_nil(Integer, random_seed: random_seed)
38
+ @params = {}
39
+ @params[:reg_param] = reg_param
40
+ @params[:kernel] = kernel
41
+ @params[:degree] = degree
42
+ @params[:gamma] = gamma
43
+ @params[:coef0] = coef0
44
+ @params[:shrinking] = shrinking
45
+ @params[:probability] = probability
46
+ @params[:cache_size] = cache_size
47
+ @params[:tol] = tol
48
+ @params[:verbose] = verbose
49
+ @params[:random_seed] = random_seed
50
+ @model = nil
51
+ end
52
+
53
+ # Fit the model with given training data.
54
+ #
55
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
56
+ # If the kernel is 'precomputed', x must be a square distance matrix (shape: [n_samples, n_samples]).
57
+ # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
58
+ # @return [SVC] The learned classifier itself.
59
+ def fit(x, y)
60
+ check_sample_array(x)
61
+ check_label_array(y)
62
+ check_sample_label_size(x, y)
63
+ xx = precomputed_kernel? ? add_index_col(x) : x
64
+ @model = Numo::Libsvm.train(xx, y, libsvm_params)
65
+ self
66
+ end
67
+
68
+ # Calculate confidence scores for samples.
69
+ #
70
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
71
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
72
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Confidence score per sample.
73
+ def decision_function(x)
74
+ check_sample_array(x)
75
+ xx = precomputed_kernel? ? add_index_col(x) : x
76
+ Numo::Libsvm.decision_function(xx, libsvm_params, @model)
77
+ end
78
+
79
+ # Predict class labels for samples.
80
+ #
81
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
82
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
83
+ # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
84
+ def predict(x)
85
+ check_sample_array(x)
86
+ xx = precomputed_kernel? ? add_index_col(x) : x
87
+ Numo::Int32.cast(Numo::Libsvm.predict(xx, libsvm_params, @model))
88
+ end
89
+
90
+ # Predict class probability for samples.
91
+ # This method works correctly only if the probability parameter is true.
92
+ #
93
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
94
+ # If the kernel is 'precomputed', the shape of x must be [n_samples, n_training_samples].
95
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
96
+ def predict_proba(x)
97
+ check_sample_array(x)
98
+ xx = precomputed_kernel? ? add_index_col(x) : x
99
+ Numo::Libsvm.predict_proba(xx, libsvm_params, @model)
100
+ end
101
+
102
+ # Dump marshal data.
103
+ # @return [Hash] The marshal data about SVC.
104
+ def marshal_dump
105
+ { params: @params,
106
+ model: @model }
107
+ end
108
+
109
+ # Load marshal data.
110
+ # @return [nil]
111
+ def marshal_load(obj)
112
+ @params = obj[:params]
113
+ @model = obj[:model]
114
+ nil
115
+ end
116
+
117
+ # Return the indices of support vectors.
118
+ # @return [Numo::Int32] (shape: [n_support_vectors])
119
+ def support
120
+ @model[:sv_indices]
121
+ end
122
+
123
+ # Return the support_vectors.
124
+ # @return [Numo::DFloat] (shape: [n_support_vectors, n_features])
125
+ def support_vectors
126
+ precomputed_kernel? ? del_index_col(@model[:SV]) : @model[:SV]
127
+ end
128
+
129
+ # Return the number of support vectors for each class.
130
+ # @return [Numo::Int32] (shape: [n_classes])
131
+ def n_support
132
+ @model[:nSV]
133
+ end
134
+
135
+ # Return the coefficients of the support vector in decision function.
136
+ # @return [Numo::DFloat] (shape: [n_classes - 1, n_support_vectors])
137
+ def duel_coef
138
+ @model[:sv_coef]
139
+ end
140
+
141
+ # Return the intercepts in decision function.
142
+ # @return [Numo::DFloat] (shape: [n_classes * (n_classes - 1) / 2])
143
+ def intercept
144
+ @model[:rho]
145
+ end
146
+
147
+ # Return the probability parameter alpha.
148
+ # @return [Numo::DFloat] (shape: [n_classes * (n_classes - 1) / 2])
149
+ def prob_a
150
+ @model[:probA]
151
+ end
152
+
153
+ # Return the probability parameter beta.
154
+ # @return [Numo::DFloat] (shape: [n_classes * (n_classes - 1) / 2])
155
+ def prob_b
156
+ @model[:probB]
157
+ end
158
+
159
+ private
160
+
161
+ def add_index_col(x)
162
+ idx = Numo::Int32.new(x.shape[0]).seq + 1
163
+ Numo::NArray.hstack([idx.expand_dims(1), x])
164
+ end
165
+
166
+ def del_index_col(x)
167
+ x[true, 1..-1].dup
168
+ end
169
+
170
+ def precomputed_kernel?
171
+ @params[:kernel] == 'precomputed'
172
+ end
173
+
174
+ def libsvm_params
175
+ res = @params.merge(svm_type: Numo::Libsvm::SvmType::C_SVC)
176
+ res[:kernel_type] = case res.delete(:kernel)
177
+ when 'linear'
178
+ Numo::Libsvm::KernelType::LINEAR
179
+ when 'poly'
180
+ Numo::Libsvm::KernelType::POLY
181
+ when 'sigmoid'
182
+ Numo::Libsvm::KernelType::SIGMOID
183
+ when 'precomputed'
184
+ Numo::Libsvm::KernelType::PRECOMPUTED
185
+ else
186
+ Numo::Libsvm::KernelType::RBF
187
+ end
188
+ res[:C] = res.delete(:reg_param)
189
+ res[:eps] = res.delete(:tol)
190
+ res
191
+ end
192
+ end
193
+ end
194
+ end