svmkit 0.7.3 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -9
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -12
  5. data/LICENSE.txt +1 -1
  6. data/README.md +11 -13
  7. data/lib/svmkit.rb +3 -66
  8. data/svmkit.gemspec +12 -7
  9. metadata +16 -81
  10. data/.coveralls.yml +0 -1
  11. data/.rubocop.yml +0 -47
  12. data/.rubocop_todo.yml +0 -58
  13. data/HISTORY.md +0 -168
  14. data/lib/svmkit/base/base_estimator.rb +0 -13
  15. data/lib/svmkit/base/classifier.rb +0 -34
  16. data/lib/svmkit/base/cluster_analyzer.rb +0 -29
  17. data/lib/svmkit/base/evaluator.rb +0 -13
  18. data/lib/svmkit/base/regressor.rb +0 -34
  19. data/lib/svmkit/base/splitter.rb +0 -17
  20. data/lib/svmkit/base/transformer.rb +0 -18
  21. data/lib/svmkit/clustering/dbscan.rb +0 -127
  22. data/lib/svmkit/clustering/k_means.rb +0 -140
  23. data/lib/svmkit/dataset.rb +0 -109
  24. data/lib/svmkit/decomposition/nmf.rb +0 -147
  25. data/lib/svmkit/decomposition/pca.rb +0 -150
  26. data/lib/svmkit/ensemble/ada_boost_classifier.rb +0 -198
  27. data/lib/svmkit/ensemble/ada_boost_regressor.rb +0 -180
  28. data/lib/svmkit/ensemble/random_forest_classifier.rb +0 -182
  29. data/lib/svmkit/ensemble/random_forest_regressor.rb +0 -143
  30. data/lib/svmkit/evaluation_measure/accuracy.rb +0 -30
  31. data/lib/svmkit/evaluation_measure/f_score.rb +0 -51
  32. data/lib/svmkit/evaluation_measure/log_loss.rb +0 -46
  33. data/lib/svmkit/evaluation_measure/mean_absolute_error.rb +0 -30
  34. data/lib/svmkit/evaluation_measure/mean_squared_error.rb +0 -30
  35. data/lib/svmkit/evaluation_measure/normalized_mutual_information.rb +0 -63
  36. data/lib/svmkit/evaluation_measure/precision.rb +0 -51
  37. data/lib/svmkit/evaluation_measure/precision_recall.rb +0 -91
  38. data/lib/svmkit/evaluation_measure/purity.rb +0 -41
  39. data/lib/svmkit/evaluation_measure/r2_score.rb +0 -44
  40. data/lib/svmkit/evaluation_measure/recall.rb +0 -51
  41. data/lib/svmkit/kernel_approximation/rbf.rb +0 -136
  42. data/lib/svmkit/kernel_machine/kernel_svc.rb +0 -194
  43. data/lib/svmkit/linear_model/lasso.rb +0 -138
  44. data/lib/svmkit/linear_model/linear_regression.rb +0 -112
  45. data/lib/svmkit/linear_model/logistic_regression.rb +0 -161
  46. data/lib/svmkit/linear_model/ridge.rb +0 -112
  47. data/lib/svmkit/linear_model/sgd_linear_estimator.rb +0 -89
  48. data/lib/svmkit/linear_model/svc.rb +0 -184
  49. data/lib/svmkit/linear_model/svr.rb +0 -123
  50. data/lib/svmkit/model_selection/cross_validation.rb +0 -121
  51. data/lib/svmkit/model_selection/grid_search_cv.rb +0 -247
  52. data/lib/svmkit/model_selection/k_fold.rb +0 -77
  53. data/lib/svmkit/model_selection/stratified_k_fold.rb +0 -95
  54. data/lib/svmkit/multiclass/one_vs_rest_classifier.rb +0 -101
  55. data/lib/svmkit/naive_bayes/naive_bayes.rb +0 -316
  56. data/lib/svmkit/nearest_neighbors/k_neighbors_classifier.rb +0 -112
  57. data/lib/svmkit/nearest_neighbors/k_neighbors_regressor.rb +0 -94
  58. data/lib/svmkit/optimizer/nadam.rb +0 -90
  59. data/lib/svmkit/optimizer/rmsprop.rb +0 -69
  60. data/lib/svmkit/optimizer/sgd.rb +0 -65
  61. data/lib/svmkit/optimizer/yellow_fin.rb +0 -144
  62. data/lib/svmkit/pairwise_metric.rb +0 -91
  63. data/lib/svmkit/pipeline/pipeline.rb +0 -197
  64. data/lib/svmkit/polynomial_model/factorization_machine_classifier.rb +0 -262
  65. data/lib/svmkit/polynomial_model/factorization_machine_regressor.rb +0 -194
  66. data/lib/svmkit/preprocessing/l2_normalizer.rb +0 -63
  67. data/lib/svmkit/preprocessing/label_encoder.rb +0 -95
  68. data/lib/svmkit/preprocessing/min_max_scaler.rb +0 -93
  69. data/lib/svmkit/preprocessing/one_hot_encoder.rb +0 -99
  70. data/lib/svmkit/preprocessing/standard_scaler.rb +0 -87
  71. data/lib/svmkit/probabilistic_output.rb +0 -112
  72. data/lib/svmkit/tree/decision_tree_classifier.rb +0 -276
  73. data/lib/svmkit/tree/decision_tree_regressor.rb +0 -251
  74. data/lib/svmkit/tree/node.rb +0 -70
  75. data/lib/svmkit/utils.rb +0 -22
  76. data/lib/svmkit/validation.rb +0 -79
  77. data/lib/svmkit/values.rb +0 -13
  78. data/lib/svmkit/version.rb +0 -7
@@ -1,197 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'svmkit/validation'
4
- require 'svmkit/base/base_estimator'
5
-
6
- module SVMKit
7
- # Module implements utilities of pipeline that cosists of a chain of transfomers and estimators.
8
- module Pipeline
9
- # Pipeline is a class that implements the function to perform the transformers and estimators sequencially.
10
- #
11
- # @example
12
- # rbf = SVMKit::KernelApproximation::RBF.new(gamma: 1.0, n_coponents: 128, random_seed: 1)
13
- # svc = SVMKit::LinearModel::SVC.new(reg_param: 1.0, fit_bias: true, max_iter: 5000, random_seed: 1)
14
- # pipeline = SVMKit::Pipeline::Pipeline.new(steps: { trs: rbf, est: svc })
15
- # pipeline.fit(training_samples, traininig_labels)
16
- # results = pipeline.predict(testing_samples)
17
- #
18
- class Pipeline
19
- include Base::BaseEstimator
20
- include Validation
21
-
22
- # Return the steps.
23
- # @return [Hash]
24
- attr_reader :steps
25
-
26
- # Create a new pipeline.
27
- #
28
- # @param steps [Hash] List of transformers and estimators. The order of transforms follows the insertion order of hash keys.
29
- # The last entry is considered an estimator.
30
- def initialize(steps:)
31
- check_params_type(Hash, steps: steps)
32
- validate_steps(steps)
33
- @params = {}
34
- @steps = steps
35
- end
36
-
37
- # Fit the model with given training data.
38
- #
39
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be transformed and used for fitting the model.
40
- # @param y [Numo::NArray] (shape: [n_samples, n_outputs]) The target values or labels to be used for fitting the model.
41
- # @return [Pipeline] The learned pipeline itself.
42
- def fit(x, y)
43
- check_sample_array(x)
44
- trans_x = apply_transforms(x, y, fit: true)
45
- last_estimator.fit(trans_x, y) unless last_estimator.nil?
46
- self
47
- end
48
-
49
- # Call the fit_predict method of last estimator after applying all transforms.
50
- #
51
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be transformed and used for fitting the model.
52
- # @param y [Numo::NArray] (shape: [n_samples, n_outputs], default: nil) The target values or labels to be used for fitting the model.
53
- # @return [Numo::NArray] The predicted results by last estimator.
54
- def fit_predict(x, y = nil)
55
- check_sample_array(x)
56
- trans_x = apply_transforms(x, y, fit: true)
57
- last_estimator.fit_predict(trans_x)
58
- end
59
-
60
- # Call the fit_transform method of last estimator after applying all transforms.
61
- #
62
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be transformed and used for fitting the model.
63
- # @param y [Numo::NArray] (shape: [n_samples, n_outputs], default: nil) The target values or labels to be used for fitting the model.
64
- # @return [Numo::NArray] The predicted results by last estimator.
65
- def fit_transform(x, y = nil)
66
- check_sample_array(x)
67
- trans_x = apply_transforms(x, y, fit: true)
68
- last_estimator.fit_transform(trans_x, y)
69
- end
70
-
71
- # Call the decision_function method of last estimator after applying all transforms.
72
- #
73
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
74
- # @return [Numo::DFloat] (shape: [n_samples]) Confidence score per sample.
75
- def decision_function(x)
76
- check_sample_array(x)
77
- trans_x = apply_transforms(x)
78
- last_estimator.decision_function(trans_x)
79
- end
80
-
81
- # Call the predict method of last estimator after applying all transforms.
82
- #
83
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to obtain prediction result.
84
- # @return [Numo::NArray] The predicted results by last estimator.
85
- def predict(x)
86
- check_sample_array(x)
87
- trans_x = apply_transforms(x)
88
- last_estimator.predict(trans_x)
89
- end
90
-
91
- # Call the predict_log_proba method of last estimator after applying all transforms.
92
- #
93
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the log-probailities.
94
- # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted log-probability of each class per sample.
95
- def predict_log_proba(x)
96
- check_sample_array(x)
97
- trans_x = apply_transforms(x)
98
- last_estimator.predict_log_proba(trans_x)
99
- end
100
-
101
- # Call the predict_proba method of last estimator after applying all transforms.
102
- #
103
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
104
- # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
105
- def predict_proba(x)
106
- check_sample_array(x)
107
- trans_x = apply_transforms(x)
108
- last_estimator.predict_proba(trans_x)
109
- end
110
-
111
- # Call the transform method of last estimator after applying all transforms.
112
- #
113
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be transformed.
114
- # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed samples.
115
- def transform(x)
116
- check_sample_array(x)
117
- trans_x = apply_transforms(x)
118
- last_estimator.nil? ? trans_x : last_estimator.transform(trans_x)
119
- end
120
-
121
- # Call the inverse_transform method in reverse order.
122
- #
123
- # @param z [Numo::DFloat] (shape: [n_samples, n_components]) The transformed samples to be restored into original space.
124
- # @return [Numo::DFloat] (shape: [n_samples, n_featuress]) The restored samples.
125
- def inverse_transform(z)
126
- check_sample_array(z)
127
- itrans_z = z
128
- @steps.keys.reverse_each do |name|
129
- transformer = @steps[name]
130
- next if transformer.nil?
131
- itrans_z = transformer.inverse_transform(itrans_z)
132
- end
133
- itrans_z
134
- end
135
-
136
- # Call the score method of last estimator after applying all transforms.
137
- #
138
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) Testing data.
139
- # @param y [Numo::NArray] (shape: [n_samples, n_outputs]) True target values or labels for testing data.
140
- # @return [Float] The score of last estimator
141
- def score(x, y)
142
- check_sample_array(x)
143
- trans_x = apply_transforms(x)
144
- last_estimator.score(trans_x, y)
145
- end
146
-
147
- # Dump marshal data.
148
- # @return [Hash] The marshal data about Pipeline.
149
- def marshal_dump
150
- { params: @params,
151
- steps: @steps }
152
- end
153
-
154
- # Load marshal data.
155
- # @return [nil]
156
- def marshal_load(obj)
157
- @params = obj[:params]
158
- @steps = obj[:steps]
159
- nil
160
- end
161
-
162
- private
163
-
164
- def validate_steps(steps)
165
- steps.keys[0...-1].each do |name|
166
- transformer = steps[name]
167
- next if transformer.nil? || %i[fit transform].all? { |m| transformer.class.method_defined?(m) }
168
- raise TypeError,
169
- 'Class of intermediate step in pipeline should be implemented fit and transform methods: ' \
170
- "#{name} => #{transformer.class}"
171
- end
172
-
173
- estimator = steps[steps.keys.last]
174
- unless estimator.nil? || estimator.class.method_defined?(:fit)
175
- raise TypeError,
176
- 'Class of last step in pipeline should be implemented fit method: ' \
177
- "#{steps.keys.last} => #{estimator.class}"
178
- end
179
- end
180
-
181
- def apply_transforms(x, y = nil, fit: false)
182
- trans_x = x
183
- @steps.keys[0...-1].each do |name|
184
- transformer = @steps[name]
185
- next if transformer.nil?
186
- transformer.fit(trans_x, y) if fit
187
- trans_x = transformer.transform(trans_x)
188
- end
189
- trans_x
190
- end
191
-
192
- def last_estimator
193
- @steps[@steps.keys.last]
194
- end
195
- end
196
- end
197
- end
@@ -1,262 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'svmkit/validation'
4
- require 'svmkit/base/base_estimator'
5
- require 'svmkit/base/classifier'
6
- require 'svmkit/optimizer/nadam'
7
-
8
- module SVMKit
9
- # This module consists of the classes that implement polynomial models.
10
- module PolynomialModel
11
- # FactorizationMachineClassifier is a class that implements Factorization Machine
12
- # with stochastic gradient descent (SGD) optimization.
13
- # For multiclass classification problem, it uses one-vs-the-rest strategy.
14
- #
15
- # @example
16
- # estimator =
17
- # SVMKit::PolynomialModel::FactorizationMachineClassifier.new(
18
- # n_factors: 10, loss: 'hinge', reg_param_linear: 0.001, reg_param_factor: 0.001,
19
- # max_iter: 5000, batch_size: 50, random_seed: 1)
20
- # estimator.fit(training_samples, traininig_labels)
21
- # results = estimator.predict(testing_samples)
22
- #
23
- # *Reference*
24
- # - S. Rendle, "Factorization Machines with libFM," ACM TIST, vol. 3 (3), pp. 57:1--57:22, 2012.
25
- # - S. Rendle, "Factorization Machines," Proc. ICDM'10, pp. 995--1000, 2010.
26
- class FactorizationMachineClassifier
27
- include Base::BaseEstimator
28
- include Base::Classifier
29
- include Validation
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 iterations.
58
- # @param batch_size [Integer] The size of the mini batches.
59
- # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
60
- # If nil is given, Nadam is used.
61
- # @param random_seed [Integer] The seed value using to initialize the random generator.
62
- def initialize(n_factors: 2, loss: 'hinge', reg_param_linear: 1.0, reg_param_factor: 1.0,
63
- max_iter: 1000, batch_size: 10, optimizer: nil, random_seed: nil)
64
- check_params_float(reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor)
65
- check_params_integer(n_factors: n_factors, max_iter: max_iter, batch_size: batch_size)
66
- check_params_string(loss: loss)
67
- check_params_type_or_nil(Integer, random_seed: random_seed)
68
- check_params_positive(n_factors: n_factors,
69
- reg_param_linear: reg_param_linear, reg_param_factor: reg_param_factor,
70
- max_iter: max_iter, batch_size: batch_size)
71
- @params = {}
72
- @params[:n_factors] = n_factors
73
- @params[:loss] = loss
74
- @params[:reg_param_linear] = reg_param_linear
75
- @params[:reg_param_factor] = reg_param_factor
76
- @params[:max_iter] = max_iter
77
- @params[:batch_size] = batch_size
78
- @params[:optimizer] = optimizer
79
- @params[:optimizer] ||= Optimizer::Nadam.new
80
- @params[:random_seed] = random_seed
81
- @params[:random_seed] ||= srand
82
- @factor_mat = nil
83
- @weight_vec = nil
84
- @bias_term = nil
85
- @classes = nil
86
- @rng = Random.new(@params[:random_seed])
87
- end
88
-
89
- # Fit the model with given training data.
90
- #
91
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
92
- # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
93
- # @return [FactorizationMachineClassifier] The learned classifier itself.
94
- def fit(x, y)
95
- check_sample_array(x)
96
- check_label_array(y)
97
- check_sample_label_size(x, y)
98
-
99
- @classes = Numo::Int32[*y.to_a.uniq.sort]
100
- n_classes = @classes.size
101
- _n_samples, n_features = x.shape
102
-
103
- if n_classes > 2
104
- @factor_mat = Numo::DFloat.zeros(n_classes, @params[:n_factors], n_features)
105
- @weight_vec = Numo::DFloat.zeros(n_classes, n_features)
106
- @bias_term = Numo::DFloat.zeros(n_classes)
107
- n_classes.times do |n|
108
- bin_y = Numo::Int32.cast(y.eq(@classes[n])) * 2 - 1
109
- @factor_mat[n, true, true], @weight_vec[n, true], @bias_term[n] = binary_fit(x, bin_y)
110
- end
111
- else
112
- negative_label = y.to_a.uniq.min
113
- bin_y = Numo::Int32.cast(y.ne(negative_label)) * 2 - 1
114
- @factor_mat, @weight_vec, @bias_term = binary_fit(x, bin_y)
115
- end
116
-
117
- self
118
- end
119
-
120
- # Calculate confidence scores for samples.
121
- #
122
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
123
- # @return [Numo::DFloat] (shape: [n_samples]) Confidence score per sample.
124
- def decision_function(x)
125
- check_sample_array(x)
126
- linear_term = @bias_term + x.dot(@weight_vec.transpose)
127
- factor_term = if @classes.size <= 2
128
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(0)
129
- else
130
- 0.5 * (@factor_mat.dot(x.transpose)**2 - (@factor_mat**2).dot(x.transpose**2)).sum(1).transpose
131
- end
132
- linear_term + factor_term
133
- end
134
-
135
- # Predict class labels for samples.
136
- #
137
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
138
- # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
139
- def predict(x)
140
- check_sample_array(x)
141
- return Numo::Int32.cast(decision_function(x).ge(0.0)) * 2 - 1 if @classes.size <= 2
142
-
143
- n_samples, = x.shape
144
- decision_values = decision_function(x)
145
- Numo::Int32.asarray(Array.new(n_samples) { |n| @classes[decision_values[n, true].max_index] })
146
- end
147
-
148
- # Predict probability for samples.
149
- #
150
- # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
151
- # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
152
- def predict_proba(x)
153
- check_sample_array(x)
154
- proba = 1.0 / (Numo::NMath.exp(-decision_function(x)) + 1.0)
155
- return (proba.transpose / proba.sum(axis: 1)).transpose if @classes.size > 2
156
-
157
- n_samples, = x.shape
158
- probs = Numo::DFloat.zeros(n_samples, 2)
159
- probs[true, 1] = proba
160
- probs[true, 0] = 1.0 - proba
161
- probs
162
- end
163
-
164
- # Dump marshal data.
165
- # @return [Hash] The marshal data about FactorizationMachineClassifier.
166
- def marshal_dump
167
- { params: @params,
168
- factor_mat: @factor_mat,
169
- weight_vec: @weight_vec,
170
- bias_term: @bias_term,
171
- classes: @classes,
172
- rng: @rng }
173
- end
174
-
175
- # Load marshal data.
176
- # @return [nil]
177
- def marshal_load(obj)
178
- @params = obj[:params]
179
- @factor_mat = obj[:factor_mat]
180
- @weight_vec = obj[:weight_vec]
181
- @bias_term = obj[:bias_term]
182
- @classes = obj[:classes]
183
- @rng = obj[:rng]
184
- nil
185
- end
186
-
187
- private
188
-
189
- def binary_fit(x, y)
190
- # Initialize some variables.
191
- n_samples, n_features = x.shape
192
- rand_ids = [*0...n_samples].shuffle(random: @rng)
193
- weight_vec = Numo::DFloat.zeros(n_features + 1)
194
- factor_mat = Numo::DFloat.zeros(@params[:n_factors], n_features)
195
- weight_optimizer = @params[:optimizer].dup
196
- factor_optimizers = Array.new(@params[:n_factors]) { @params[:optimizer].dup }
197
- # Start optimization.
198
- @params[:max_iter].times do |_t|
199
- # Random sampling.
200
- subset_ids = rand_ids.shift(@params[:batch_size])
201
- rand_ids.concat(subset_ids)
202
- data = x[subset_ids, true]
203
- ex_data = expand_feature(data)
204
- label = y[subset_ids]
205
- # Calculate gradients for loss function.
206
- loss_grad = loss_gradient(data, ex_data, label, factor_mat, weight_vec)
207
- next if loss_grad.ne(0.0).count.zero?
208
- # Update each parameter.
209
- weight_vec = weight_optimizer.call(weight_vec, weight_gradient(loss_grad, ex_data, weight_vec))
210
- @params[:n_factors].times do |n|
211
- factor_mat[n, true] = factor_optimizers[n].call(factor_mat[n, true],
212
- factor_gradient(loss_grad, data, factor_mat[n, true]))
213
- end
214
- end
215
- [factor_mat, *split_weight_vec_bias(weight_vec)]
216
- end
217
-
218
- def bin_decision_function(x, ex_x, factor, weight)
219
- ex_x.dot(weight) + 0.5 * (factor.dot(x.transpose)**2 - (factor**2).dot(x.transpose**2)).sum(0)
220
- end
221
-
222
- def hinge_loss_gradient(x, ex_x, y, factor, weight)
223
- evaluated = y * bin_decision_function(x, ex_x, factor, weight)
224
- gradient = Numo::DFloat.zeros(evaluated.size)
225
- gradient[evaluated < 1.0] = -y[evaluated < 1.0]
226
- gradient
227
- end
228
-
229
- def logistic_loss_gradient(x, ex_x, y, factor, weight)
230
- evaluated = y * bin_decision_function(x, ex_x, factor, weight)
231
- sigmoid_func = 1.0 / (Numo::NMath.exp(-evaluated) + 1.0)
232
- (sigmoid_func - 1.0) * y
233
- end
234
-
235
- def loss_gradient(x, ex_x, y, factor, weight)
236
- if @params[:loss] == 'hinge'
237
- hinge_loss_gradient(x, ex_x, y, factor, weight)
238
- else
239
- logistic_loss_gradient(x, ex_x, y, factor, weight)
240
- end
241
- end
242
-
243
- def weight_gradient(loss_grad, data, weight)
244
- (loss_grad.expand_dims(1) * data).mean(0) + @params[:reg_param_linear] * weight
245
- end
246
-
247
- def factor_gradient(loss_grad, data, factor)
248
- (loss_grad.expand_dims(1) * (data * data.dot(factor).expand_dims(1) - factor * (data**2))).mean(0) + @params[:reg_param_factor] * factor
249
- end
250
-
251
- def expand_feature(x)
252
- Numo::NArray.hstack([x, Numo::DFloat.ones([x.shape[0], 1])])
253
- end
254
-
255
- def split_weight_vec_bias(weight_vec)
256
- weights = weight_vec[0...-1].dup
257
- bias = weight_vec[-1]
258
- [weights, bias]
259
- end
260
- end
261
- end
262
- end