rumale 0.19.0 → 0.20.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -29
  3. data/CHANGELOG.md +28 -0
  4. data/lib/rumale.rb +7 -10
  5. data/lib/rumale/clustering/hdbscan.rb +3 -3
  6. data/lib/rumale/clustering/k_means.rb +1 -1
  7. data/lib/rumale/clustering/k_medoids.rb +1 -1
  8. data/lib/rumale/clustering/mini_batch_k_means.rb +139 -0
  9. data/lib/rumale/dataset.rb +4 -4
  10. data/lib/rumale/decomposition/nmf.rb +2 -2
  11. data/lib/rumale/ensemble/random_forest_classifier.rb +1 -1
  12. data/lib/rumale/ensemble/random_forest_regressor.rb +1 -1
  13. data/lib/rumale/feature_extraction/feature_hasher.rb +1 -1
  14. data/lib/rumale/feature_extraction/hash_vectorizer.rb +1 -1
  15. data/lib/rumale/feature_extraction/tfidf_transformer.rb +113 -0
  16. data/lib/rumale/kernel_approximation/nystroem.rb +1 -1
  17. data/lib/rumale/kernel_machine/kernel_svc.rb +1 -1
  18. data/lib/rumale/linear_model/base_sgd.rb +1 -1
  19. data/lib/rumale/manifold/tsne.rb +1 -1
  20. data/lib/rumale/model_selection/cross_validation.rb +3 -2
  21. data/lib/rumale/model_selection/group_k_fold.rb +93 -0
  22. data/lib/rumale/model_selection/group_shuffle_split.rb +115 -0
  23. data/lib/rumale/model_selection/k_fold.rb +1 -1
  24. data/lib/rumale/model_selection/shuffle_split.rb +5 -5
  25. data/lib/rumale/model_selection/stratified_k_fold.rb +1 -1
  26. data/lib/rumale/model_selection/stratified_shuffle_split.rb +13 -9
  27. data/lib/rumale/multiclass/one_vs_rest_classifier.rb +2 -2
  28. data/lib/rumale/nearest_neighbors/vp_tree.rb +1 -1
  29. data/lib/rumale/neural_network/adam.rb +1 -1
  30. data/lib/rumale/neural_network/base_mlp.rb +1 -1
  31. data/lib/rumale/preprocessing/binarizer.rb +60 -0
  32. data/lib/rumale/preprocessing/l1_normalizer.rb +62 -0
  33. data/lib/rumale/preprocessing/l2_normalizer.rb +2 -1
  34. data/lib/rumale/preprocessing/max_normalizer.rb +62 -0
  35. data/lib/rumale/probabilistic_output.rb +1 -1
  36. data/lib/rumale/version.rb +1 -1
  37. metadata +12 -15
  38. data/lib/rumale/linear_model/base_linear_model.rb +0 -102
  39. data/lib/rumale/optimizer/ada_grad.rb +0 -42
  40. data/lib/rumale/optimizer/adam.rb +0 -56
  41. data/lib/rumale/optimizer/nadam.rb +0 -67
  42. data/lib/rumale/optimizer/rmsprop.rb +0 -50
  43. data/lib/rumale/optimizer/sgd.rb +0 -46
  44. data/lib/rumale/optimizer/yellow_fin.rb +0 -104
  45. data/lib/rumale/polynomial_model/base_factorization_machine.rb +0 -125
  46. data/lib/rumale/polynomial_model/factorization_machine_classifier.rb +0 -220
  47. data/lib/rumale/polynomial_model/factorization_machine_regressor.rb +0 -134
@@ -1,220 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rumale/base/classifier'
4
- require 'rumale/polynomial_model/base_factorization_machine'
5
-
6
- module Rumale
7
- # This module consists of the classes that implement polynomial models.
8
- module PolynomialModel
9
- # FactorizationMachineClassifier is a class that implements Factorization Machine
10
- # with stochastic gradient descent (SGD) optimization.
11
- # For multiclass classification problem, it uses one-vs-the-rest strategy.
12
- #
13
- # @deprecated
14
- # FactorizationMachineClassifier will be deleted in version 0.20.0.
15
- # The Ruamle author recommends using the xlearn gem instead.
16
- #
17
- # @example
18
- # estimator =
19
- # Rumale::PolynomialModel::FactorizationMachineClassifier.new(
20
- # n_factors: 10, loss: 'hinge', reg_param_linear: 0.001, reg_param_factor: 0.001,
21
- # max_iter: 500, batch_size: 50, random_seed: 1)
22
- # estimator.fit(training_samples, traininig_labels)
23
- # results = estimator.predict(testing_samples)
24
- #
25
- # *Reference*
26
- # - Rendle, S., "Factorization Machines with libFM," ACM TIST, vol. 3 (3), pp. 57:1--57:22, 2012.
27
- # - Rendle, S., "Factorization Machines," Proc. ICDM'10, pp. 995--1000, 2010.
28
- class FactorizationMachineClassifier < BaseFactorizationMachine
29
- include Base::Classifier
30
-
31
- # Return the factor matrix for Factorization Machine.
32
- # @return [Numo::DFloat] (shape: [n_classes, n_factors, n_features])
33
- attr_reader :factor_mat
34
-
35
- # Return the weight vector for Factorization Machine.
36
- # @return [Numo::DFloat] (shape: [n_classes, n_features])
37
- attr_reader :weight_vec
38
-
39
- # Return the bias term for Factoriazation Machine.
40
- # @return [Numo::DFloat] (shape: [n_classes])
41
- attr_reader :bias_term
42
-
43
- # Return the class labels.
44
- # @return [Numo::Int32] (shape: [n_classes])
45
- attr_reader :classes
46
-
47
- # Return the random generator for random sampling.
48
- # @return [Random]
49
- attr_reader :rng
50
-
51
- # Create a new classifier with Factorization Machine.
52
- #
53
- # @param n_factors [Integer] The maximum number of iterations.
54
- # @param loss [String] The loss function ('hinge' or 'logistic').
55
- # @param reg_param_linear [Float] The regularization parameter for linear model.
56
- # @param reg_param_factor [Float] The regularization parameter for factor matrix.
57
- # @param max_iter [Integer] The maximum number of epochs that indicates
58
- # how many times the whole data is given to the training process.
59
- # @param batch_size [Integer] The size of the mini batches.
60
- # @param tol [Float] The tolerance of loss for terminating optimization.
61
- # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
62
- # If nil is given, Nadam is used.
63
- # @param n_jobs [Integer] The number of jobs for running the fit and predict methods in parallel.
64
- # If nil is given, the methods do not execute in parallel.
65
- # If zero or less is given, it becomes equal to the number of processors.
66
- # This parameter is ignored if the Parallel gem is not loaded.
67
- # @param verbose [Boolean] The flag indicating whether to output loss during iteration.
68
- # @param random_seed [Integer] The seed value using to initialize the random generator.
69
- def initialize(n_factors: 2, loss: 'hinge', reg_param_linear: 1.0, reg_param_factor: 1.0,
70
- max_iter: 200, batch_size: 50, tol: 1e-4,
71
- optimizer: nil, n_jobs: nil, verbose: false, random_seed: nil)
72
- warn 'warning: FactorizationMachineClassifier is deprecated. This class will be deleted in version 0.20.0.'
73
- check_params_numeric(reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor,
74
- n_factors: n_factors, max_iter: max_iter, batch_size: batch_size, tol: tol)
75
- check_params_string(loss: loss)
76
- check_params_boolean(verbose: verbose)
77
- check_params_numeric_or_nil(n_jobs: n_jobs, random_seed: random_seed)
78
- check_params_positive(n_factors: n_factors,
79
- reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor,
80
- max_iter: max_iter, batch_size: batch_size)
81
- super
82
- @classes = nil
83
- end
84
-
85
- # Fit the model with given training data.
86
- #
87
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
88
- # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
89
- # @return [FactorizationMachineClassifier] The learned classifier itself.
90
- def fit(x, y)
91
- x = check_convert_sample_array(x)
92
- y = check_convert_label_array(y)
93
- check_sample_label_size(x, y)
94
-
95
- @classes = Numo::Int32[*y.to_a.uniq.sort]
96
-
97
- if multiclass_problem?
98
- n_classes = @classes.size
99
- n_features = x.shape[1]
100
- @factor_mat = Numo::DFloat.zeros(n_classes, @params[:n_factors], n_features)
101
- @weight_vec = Numo::DFloat.zeros(n_classes, n_features)
102
- @bias_term = Numo::DFloat.zeros(n_classes)
103
- if enable_parallel?
104
- # :nocov:
105
- models = parallel_map(n_classes) do |n|
106
- bin_y = Numo::Int32.cast(y.eq(@classes[n])) * 2 - 1
107
- partial_fit(x, bin_y)
108
- end
109
- # :nocov:
110
- n_classes.times { |n| @factor_mat[n, true, true], @weight_vec[n, true], @bias_term[n] = models[n] }
111
- else
112
- n_classes.times do |n|
113
- bin_y = Numo::Int32.cast(y.eq(@classes[n])) * 2 - 1
114
- @factor_mat[n, true, true], @weight_vec[n, true], @bias_term[n] = partial_fit(x, bin_y)
115
- end
116
- end
117
- else
118
- negative_label = @classes[0]
119
- bin_y = Numo::Int32.cast(y.ne(negative_label)) * 2 - 1
120
- @factor_mat, @weight_vec, @bias_term = partial_fit(x, bin_y)
121
- end
122
-
123
- self
124
- end
125
-
126
- # Calculate confidence scores for samples.
127
- #
128
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
129
- # @return [Numo::DFloat] (shape: [n_samples]) Confidence score per sample.
130
- def decision_function(x)
131
- x = check_convert_sample_array(x)
132
- linear_term = @bias_term + x.dot(@weight_vec.transpose)
133
- factor_term = if multiclass_problem?
134
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(1).transpose
135
- else
136
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(0)
137
- end
138
- linear_term + factor_term
139
- end
140
-
141
- # Predict class labels for samples.
142
- #
143
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
144
- # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
145
- def predict(x)
146
- x = check_convert_sample_array(x)
147
-
148
- n_samples = x.shape[0]
149
- predicted = if multiclass_problem?
150
- decision_values = decision_function(x)
151
- if enable_parallel?
152
- parallel_map(n_samples) { |n| @classes[decision_values[n, true].max_index] }
153
- else
154
- Array.new(n_samples) { |n| @classes[decision_values[n, true].max_index] }
155
- end
156
- else
157
- decision_values = decision_function(x).ge(0.0).to_a
158
- Array.new(n_samples) { |n| @classes[decision_values[n]] }
159
- end
160
- Numo::Int32.asarray(predicted)
161
- end
162
-
163
- # Predict probability for samples.
164
- #
165
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
166
- # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
167
- def predict_proba(x)
168
- x = check_convert_sample_array(x)
169
- proba = 1.0 / (Numo::NMath.exp(-decision_function(x)) + 1.0)
170
- return (proba.transpose / proba.sum(axis: 1)).transpose.dup if multiclass_problem?
171
-
172
- n_samples, = x.shape
173
- probs = Numo::DFloat.zeros(n_samples, 2)
174
- probs[true, 1] = proba
175
- probs[true, 0] = 1.0 - proba
176
- probs
177
- end
178
-
179
- private
180
-
181
- def bin_decision_function(x, ex_x, factor, weight)
182
- ex_x.dot(weight) + 0.5 * (factor.dot(x.transpose)**2 - (factor**2).dot(x.transpose**2)).sum(0)
183
- end
184
-
185
- def loss_func(x, ex_x, y, factor, weight)
186
- z = bin_decision_function(x, ex_x, factor, weight)
187
- if @params[:loss] == 'hinge'
188
- z.class.maximum(0.0, 1 - y * z).sum.fdiv(y.shape[0])
189
- else
190
- Numo::NMath.log(1 + Numo::NMath.exp(-y * z)).sum.fdiv(y.shape[0])
191
- end
192
- end
193
-
194
- def hinge_loss_gradient(x, ex_x, y, factor, weight)
195
- evaluated = y * bin_decision_function(x, ex_x, factor, weight)
196
- gradient = Numo::DFloat.zeros(evaluated.size)
197
- gradient[evaluated < 1.0] = -y[evaluated < 1.0]
198
- gradient
199
- end
200
-
201
- def logistic_loss_gradient(x, ex_x, y, factor, weight)
202
- evaluated = y * bin_decision_function(x, ex_x, factor, weight)
203
- sigmoid_func = 1.0 / (Numo::NMath.exp(-evaluated) + 1.0)
204
- (sigmoid_func - 1.0) * y
205
- end
206
-
207
- def loss_gradient(x, ex_x, y, factor, weight)
208
- if @params[:loss] == 'hinge'
209
- hinge_loss_gradient(x, ex_x, y, factor, weight)
210
- else
211
- logistic_loss_gradient(x, ex_x, y, factor, weight)
212
- end
213
- end
214
-
215
- def multiclass_problem?
216
- @classes.size > 2
217
- end
218
- end
219
- end
220
- end
@@ -1,134 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rumale/base/regressor'
4
- require 'rumale/polynomial_model/base_factorization_machine'
5
-
6
- module Rumale
7
- module PolynomialModel
8
- # FactorizationMachineRegressor is a class that implements Factorization Machine
9
- # with stochastic gradient descent (SGD) optimization.
10
- #
11
- # @deprecated
12
- # FactorizationMachineRegressor will be deleted in version 0.20.0.
13
- # The Ruamle author recommends using the xlearn gem instead.
14
- #
15
- # @example
16
- # estimator =
17
- # Rumale::PolynomialModel::FactorizationMachineRegressor.new(
18
- # n_factors: 10, reg_param_linear: 0.1, reg_param_factor: 0.1,
19
- # max_iter: 500, batch_size: 50, random_seed: 1)
20
- # estimator.fit(training_samples, traininig_values)
21
- # results = estimator.predict(testing_samples)
22
- #
23
- # *Reference*
24
- # - Rendle, S., "Factorization Machines with libFM," ACM TIST, vol. 3 (3), pp. 57:1--57:22, 2012.
25
- # - Rendle, S., "Factorization Machines," Proc. ICDM'10, pp. 995--1000, 2010.
26
- class FactorizationMachineRegressor < BaseFactorizationMachine
27
- include Base::Regressor
28
-
29
- # Return the factor matrix for Factorization Machine.
30
- # @return [Numo::DFloat] (shape: [n_outputs, n_factors, n_features])
31
- attr_reader :factor_mat
32
-
33
- # Return the weight vector for Factorization Machine.
34
- # @return [Numo::DFloat] (shape: [n_outputs, n_features])
35
- attr_reader :weight_vec
36
-
37
- # Return the bias term for Factoriazation Machine.
38
- # @return [Numo::DFloat] (shape: [n_outputs])
39
- attr_reader :bias_term
40
-
41
- # Return the random generator for random sampling.
42
- # @return [Random]
43
- attr_reader :rng
44
-
45
- # Create a new regressor with Factorization Machine.
46
- #
47
- # @param n_factors [Integer] The maximum number of iterations.
48
- # @param reg_param_linear [Float] The regularization parameter for linear model.
49
- # @param reg_param_factor [Float] The regularization parameter for factor matrix.
50
- # @param max_iter [Integer] The maximum number of epochs that indicates
51
- # how many times the whole data is given to the training process.
52
- # @param batch_size [Integer] The size of the mini batches.
53
- # @param tol [Float] The tolerance of loss for terminating optimization.
54
- # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
55
- # If nil is given, Nadam is used.
56
- # @param n_jobs [Integer] The number of jobs for running the fit method in parallel.
57
- # If nil is given, the method does not execute in parallel.
58
- # If zero or less is given, it becomes equal to the number of processors.
59
- # This parameter is ignored if the Parallel gem is not loaded.
60
- # @param verbose [Boolean] The flag indicating whether to output loss during iteration.
61
- # @param random_seed [Integer] The seed value using to initialize the random generator.
62
- def initialize(n_factors: 2, reg_param_linear: 1.0, reg_param_factor: 1.0,
63
- max_iter: 200, batch_size: 50, tol: 1e-4,
64
- optimizer: nil, n_jobs: nil, verbose: false, random_seed: nil)
65
- warn 'warning: FactorizationMachineClassifier is deprecated. This class will be deleted in version 0.20.0.'
66
- check_params_numeric(reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor,
67
- n_factors: n_factors, max_iter: max_iter, batch_size: batch_size, tol: tol)
68
- check_params_boolean(verbose: verbose)
69
- check_params_numeric_or_nil(n_jobs: n_jobs, random_seed: random_seed)
70
- check_params_positive(n_factors: n_factors, reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor,
71
- max_iter: max_iter, batch_size: batch_size)
72
- keywd_args = method(:initialize).parameters.map { |_t, arg| [arg, binding.local_variable_get(arg)] }.to_h.merge(loss: nil)
73
- super(**keywd_args)
74
- end
75
-
76
- # Fit the model with given training data.
77
- #
78
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
79
- # @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
80
- # @return [FactorizationMachineRegressor] The learned regressor itself.
81
- def fit(x, y)
82
- x = check_convert_sample_array(x)
83
- y = check_convert_tvalue_array(y)
84
- check_sample_tvalue_size(x, y)
85
-
86
- n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
87
- _n_samples, n_features = x.shape
88
-
89
- if n_outputs > 1
90
- @factor_mat = Numo::DFloat.zeros(n_outputs, @params[:n_factors], n_features)
91
- @weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
92
- @bias_term = Numo::DFloat.zeros(n_outputs)
93
- if enable_parallel?
94
- models = parallel_map(n_outputs) { |n| partial_fit(x, y[true, n]) }
95
- n_outputs.times { |n| @factor_mat[n, true, true], @weight_vec[n, true], @bias_term[n] = models[n] }
96
- else
97
- n_outputs.times { |n| @factor_mat[n, true, true], @weight_vec[n, true], @bias_term[n] = partial_fit(x, y[true, n]) }
98
- end
99
- else
100
- @factor_mat, @weight_vec, @bias_term = partial_fit(x, y)
101
- end
102
-
103
- self
104
- end
105
-
106
- # Predict values for samples.
107
- #
108
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
109
- # @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
110
- def predict(x)
111
- x = check_convert_sample_array(x)
112
- linear_term = @bias_term + x.dot(@weight_vec.transpose)
113
- factor_term = if @weight_vec.shape[1].nil?
114
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(0)
115
- else
116
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(1).transpose
117
- end
118
- linear_term + factor_term
119
- end
120
-
121
- private
122
-
123
- def loss_func(x, ex_x, y, factor, weight)
124
- z = ex_x.dot(weight) + 0.5 * (factor.dot(x.transpose)**2 - (factor**2).dot(x.transpose**2)).sum(0)
125
- ((z - y)**2).sum.fdiv(y.shape[0])
126
- end
127
-
128
- def loss_gradient(x, ex_x, y, factor, weight)
129
- z = ex_x.dot(weight) + 0.5 * (factor.dot(x.transpose)**2 - (factor**2).dot(x.transpose**2)).sum(0)
130
- 2.0 * (z - y)
131
- end
132
- end
133
- end
134
- end