rumale 0.8.0

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 (85) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +47 -0
  6. data/.rubocop_todo.yml +58 -0
  7. data/.travis.yml +13 -0
  8. data/CHANGELOG.md +2 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +4 -0
  11. data/LICENSE.txt +23 -0
  12. data/README.md +175 -0
  13. data/Rakefile +6 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/lib/rumale.rb +70 -0
  17. data/lib/rumale/base/base_estimator.rb +13 -0
  18. data/lib/rumale/base/classifier.rb +36 -0
  19. data/lib/rumale/base/cluster_analyzer.rb +31 -0
  20. data/lib/rumale/base/evaluator.rb +17 -0
  21. data/lib/rumale/base/regressor.rb +36 -0
  22. data/lib/rumale/base/splitter.rb +21 -0
  23. data/lib/rumale/base/transformer.rb +22 -0
  24. data/lib/rumale/clustering/dbscan.rb +125 -0
  25. data/lib/rumale/clustering/k_means.rb +138 -0
  26. data/lib/rumale/dataset.rb +110 -0
  27. data/lib/rumale/decomposition/nmf.rb +141 -0
  28. data/lib/rumale/decomposition/pca.rb +148 -0
  29. data/lib/rumale/ensemble/ada_boost_classifier.rb +196 -0
  30. data/lib/rumale/ensemble/ada_boost_regressor.rb +178 -0
  31. data/lib/rumale/ensemble/random_forest_classifier.rb +180 -0
  32. data/lib/rumale/ensemble/random_forest_regressor.rb +141 -0
  33. data/lib/rumale/evaluation_measure/accuracy.rb +29 -0
  34. data/lib/rumale/evaluation_measure/f_score.rb +50 -0
  35. data/lib/rumale/evaluation_measure/log_loss.rb +45 -0
  36. data/lib/rumale/evaluation_measure/mean_absolute_error.rb +29 -0
  37. data/lib/rumale/evaluation_measure/mean_squared_error.rb +29 -0
  38. data/lib/rumale/evaluation_measure/normalized_mutual_information.rb +62 -0
  39. data/lib/rumale/evaluation_measure/precision.rb +50 -0
  40. data/lib/rumale/evaluation_measure/precision_recall.rb +91 -0
  41. data/lib/rumale/evaluation_measure/purity.rb +40 -0
  42. data/lib/rumale/evaluation_measure/r2_score.rb +43 -0
  43. data/lib/rumale/evaluation_measure/recall.rb +50 -0
  44. data/lib/rumale/kernel_approximation/rbf.rb +121 -0
  45. data/lib/rumale/kernel_machine/kernel_svc.rb +193 -0
  46. data/lib/rumale/linear_model/base_linear_model.rb +89 -0
  47. data/lib/rumale/linear_model/lasso.rb +136 -0
  48. data/lib/rumale/linear_model/linear_regression.rb +110 -0
  49. data/lib/rumale/linear_model/logistic_regression.rb +159 -0
  50. data/lib/rumale/linear_model/ridge.rb +110 -0
  51. data/lib/rumale/linear_model/svc.rb +183 -0
  52. data/lib/rumale/linear_model/svr.rb +122 -0
  53. data/lib/rumale/model_selection/cross_validation.rb +123 -0
  54. data/lib/rumale/model_selection/grid_search_cv.rb +247 -0
  55. data/lib/rumale/model_selection/k_fold.rb +76 -0
  56. data/lib/rumale/model_selection/stratified_k_fold.rb +94 -0
  57. data/lib/rumale/multiclass/one_vs_rest_classifier.rb +100 -0
  58. data/lib/rumale/naive_bayes/naive_bayes.rb +315 -0
  59. data/lib/rumale/nearest_neighbors/k_neighbors_classifier.rb +111 -0
  60. data/lib/rumale/nearest_neighbors/k_neighbors_regressor.rb +93 -0
  61. data/lib/rumale/optimizer/nadam.rb +90 -0
  62. data/lib/rumale/optimizer/rmsprop.rb +69 -0
  63. data/lib/rumale/optimizer/sgd.rb +65 -0
  64. data/lib/rumale/optimizer/yellow_fin.rb +144 -0
  65. data/lib/rumale/pairwise_metric.rb +91 -0
  66. data/lib/rumale/pipeline/pipeline.rb +197 -0
  67. data/lib/rumale/polynomial_model/base_factorization_machine.rb +99 -0
  68. data/lib/rumale/polynomial_model/factorization_machine_classifier.rb +197 -0
  69. data/lib/rumale/polynomial_model/factorization_machine_regressor.rb +131 -0
  70. data/lib/rumale/preprocessing/l2_normalizer.rb +62 -0
  71. data/lib/rumale/preprocessing/label_encoder.rb +94 -0
  72. data/lib/rumale/preprocessing/min_max_scaler.rb +92 -0
  73. data/lib/rumale/preprocessing/one_hot_encoder.rb +98 -0
  74. data/lib/rumale/preprocessing/standard_scaler.rb +86 -0
  75. data/lib/rumale/probabilistic_output.rb +112 -0
  76. data/lib/rumale/tree/base_decision_tree.rb +153 -0
  77. data/lib/rumale/tree/decision_tree_classifier.rb +163 -0
  78. data/lib/rumale/tree/decision_tree_regressor.rb +135 -0
  79. data/lib/rumale/tree/node.rb +70 -0
  80. data/lib/rumale/utils.rb +37 -0
  81. data/lib/rumale/validation.rb +79 -0
  82. data/lib/rumale/values.rb +13 -0
  83. data/lib/rumale/version.rb +6 -0
  84. data/rumale.gemspec +41 -0
  85. metadata +204 -0
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/linear_model/base_linear_model'
4
+ require 'rumale/base/regressor'
5
+
6
+ module Rumale
7
+ module LinearModel
8
+ # Lasso is a class that implements Lasso Regression
9
+ # with stochastic gradient descent (SGD) optimization.
10
+ #
11
+ # @example
12
+ # estimator =
13
+ # Rumale::LinearModel::Lasso.new(reg_param: 0.1, max_iter: 1000, batch_size: 20, random_seed: 1)
14
+ # estimator.fit(training_samples, traininig_values)
15
+ # results = estimator.predict(testing_samples)
16
+ #
17
+ # *Reference*
18
+ # - S. Shalev-Shwartz and Y. Singer, "Pegasos: Primal Estimated sub-GrAdient SOlver for SVM," Proc. ICML'07, pp. 807--814, 2007.
19
+ # - L. Bottou, "Large-Scale Machine Learning with Stochastic Gradient Descent," Proc. COMPSTAT'10, pp. 177--186, 2010.
20
+ class Lasso < BaseLinearModel
21
+ include Base::Regressor
22
+
23
+ # Return the weight vector.
24
+ # @return [Numo::DFloat] (shape: [n_outputs, n_features])
25
+ attr_reader :weight_vec
26
+
27
+ # Return the bias term (a.k.a. intercept).
28
+ # @return [Numo::DFloat] (shape: [n_outputs])
29
+ attr_reader :bias_term
30
+
31
+ # Return the random generator for random sampling.
32
+ # @return [Random]
33
+ attr_reader :rng
34
+
35
+ # Create a new Lasso regressor.
36
+ #
37
+ # @param reg_param [Float] The regularization parameter.
38
+ # @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
39
+ # @param bias_scale [Float] The scale of the bias term.
40
+ # @param max_iter [Integer] The maximum number of iterations.
41
+ # @param batch_size [Integer] The size of the mini batches.
42
+ # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
43
+ # If nil is given, Nadam is used.
44
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
45
+ def initialize(reg_param: 1.0, fit_bias: false, bias_scale: 1.0, max_iter: 1000, batch_size: 10, optimizer: nil, random_seed: nil)
46
+ check_params_float(reg_param: reg_param, bias_scale: bias_scale)
47
+ check_params_integer(max_iter: max_iter, batch_size: batch_size)
48
+ check_params_boolean(fit_bias: fit_bias)
49
+ check_params_type_or_nil(Integer, random_seed: random_seed)
50
+ check_params_positive(reg_param: reg_param, max_iter: max_iter, batch_size: batch_size)
51
+ super
52
+ end
53
+
54
+ # Fit the model with given training data.
55
+ #
56
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
57
+ # @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
58
+ # @return [Lasso] The learned regressor itself.
59
+ def fit(x, y)
60
+ check_sample_array(x)
61
+ check_tvalue_array(y)
62
+ check_sample_tvalue_size(x, y)
63
+
64
+ n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
65
+ n_features = x.shape[1]
66
+
67
+ if n_outputs > 1
68
+ @weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
69
+ @bias_term = Numo::DFloat.zeros(n_outputs)
70
+ n_outputs.times { |n| @weight_vec[n, true], @bias_term[n] = partial_fit(x, y[true, n]) }
71
+ else
72
+ @weight_vec, @bias_term = partial_fit(x, y)
73
+ end
74
+
75
+ self
76
+ end
77
+
78
+ # Predict values for samples.
79
+ #
80
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
81
+ # @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
82
+ def predict(x)
83
+ check_sample_array(x)
84
+ x.dot(@weight_vec.transpose) + @bias_term
85
+ end
86
+
87
+ # Dump marshal data.
88
+ # @return [Hash] The marshal data about Lasso.
89
+ def marshal_dump
90
+ { params: @params,
91
+ weight_vec: @weight_vec,
92
+ bias_term: @bias_term,
93
+ rng: @rng }
94
+ end
95
+
96
+ # Load marshal data.
97
+ # @return [nil]
98
+ def marshal_load(obj)
99
+ @params = obj[:params]
100
+ @weight_vec = obj[:weight_vec]
101
+ @bias_term = obj[:bias_term]
102
+ @rng = obj[:rng]
103
+ nil
104
+ end
105
+
106
+ private
107
+
108
+ def partial_fit(x, y)
109
+ n_features = @params[:fit_bias] ? x.shape[1] + 1 : x.shape[1]
110
+ @left_weight = Numo::DFloat.zeros(n_features)
111
+ @right_weight = Numo::DFloat.zeros(n_features)
112
+ @left_optimizer = @params[:optimizer].dup
113
+ @right_optimizer = @params[:optimizer].dup
114
+ super
115
+ end
116
+
117
+ def calc_loss_gradient(x, y, weight)
118
+ 2.0 * (x.dot(weight) - y)
119
+ end
120
+
121
+ def calc_new_weight(_optimizer, x, _weight, loss_gradient)
122
+ @left_weight = round_weight(@left_optimizer.call(@left_weight, calc_weight_gradient(loss_gradient, x)))
123
+ @right_weight = round_weight(@right_optimizer.call(@right_weight, calc_weight_gradient(-loss_gradient, x)))
124
+ @left_weight - @right_weight
125
+ end
126
+
127
+ def calc_weight_gradient(loss_gradient, data)
128
+ ((@params[:reg_param] + loss_gradient).expand_dims(1) * data).mean(0)
129
+ end
130
+
131
+ def round_weight(weight)
132
+ 0.5 * (weight + weight.abs)
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/linear_model/base_linear_model'
4
+ require 'rumale/base/regressor'
5
+
6
+ module Rumale
7
+ module LinearModel
8
+ # LinearRegression is a class that implements ordinary least square linear regression
9
+ # with mini-batch stochastic gradient descent optimization.
10
+ #
11
+ # @example
12
+ # estimator =
13
+ # Rumale::LinearModel::LinearRegression.new(max_iter: 1000, batch_size: 20, random_seed: 1)
14
+ # estimator.fit(training_samples, traininig_values)
15
+ # results = estimator.predict(testing_samples)
16
+ #
17
+ class LinearRegression < BaseLinearModel
18
+ include Base::Regressor
19
+
20
+ # Return the weight vector.
21
+ # @return [Numo::DFloat] (shape: [n_outputs, n_features])
22
+ attr_reader :weight_vec
23
+
24
+ # Return the bias term (a.k.a. intercept).
25
+ # @return [Numo::DFloat] (shape: [n_outputs])
26
+ attr_reader :bias_term
27
+
28
+ # Return the random generator for random sampling.
29
+ # @return [Random]
30
+ attr_reader :rng
31
+
32
+ # Create a new ordinary least square linear regressor.
33
+ #
34
+ # @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
35
+ # @param bias_scale [Float] The scale of the bias term.
36
+ # @param max_iter [Integer] The maximum number of iterations.
37
+ # @param batch_size [Integer] The size of the mini batches.
38
+ # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
39
+ # If nil is given, Nadam is used.
40
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
41
+ def initialize(fit_bias: false, bias_scale: 1.0, max_iter: 1000, batch_size: 10, optimizer: nil, random_seed: nil)
42
+ check_params_float(bias_scale: bias_scale)
43
+ check_params_integer(max_iter: max_iter, batch_size: batch_size)
44
+ check_params_boolean(fit_bias: fit_bias)
45
+ check_params_type_or_nil(Integer, random_seed: random_seed)
46
+ check_params_positive(max_iter: max_iter, batch_size: batch_size)
47
+ keywd_args = method(:initialize).parameters.map { |_t, arg| [arg, binding.local_variable_get(arg)] }.to_h.merge(reg_param: 0.0)
48
+ super(keywd_args)
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
+ # @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
55
+ # @return [LinearRegression] The learned regressor itself.
56
+ def fit(x, y)
57
+ check_sample_array(x)
58
+ check_tvalue_array(y)
59
+ check_sample_tvalue_size(x, y)
60
+
61
+ n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
62
+ n_features = x.shape[1]
63
+
64
+ if n_outputs > 1
65
+ @weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
66
+ @bias_term = Numo::DFloat.zeros(n_outputs)
67
+ n_outputs.times { |n| @weight_vec[n, true], @bias_term[n] = partial_fit(x, y[true, n]) }
68
+ else
69
+ @weight_vec, @bias_term = partial_fit(x, y)
70
+ end
71
+
72
+ self
73
+ end
74
+
75
+ # Predict values for samples.
76
+ #
77
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
78
+ # @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
79
+ def predict(x)
80
+ check_sample_array(x)
81
+ x.dot(@weight_vec.transpose) + @bias_term
82
+ end
83
+
84
+ # Dump marshal data.
85
+ # @return [Hash] The marshal data about LinearRegression.
86
+ def marshal_dump
87
+ { params: @params,
88
+ weight_vec: @weight_vec,
89
+ bias_term: @bias_term,
90
+ rng: @rng }
91
+ end
92
+
93
+ # Load marshal data.
94
+ # @return [nil]
95
+ def marshal_load(obj)
96
+ @params = obj[:params]
97
+ @weight_vec = obj[:weight_vec]
98
+ @bias_term = obj[:bias_term]
99
+ @rng = obj[:rng]
100
+ nil
101
+ end
102
+
103
+ private
104
+
105
+ def calc_loss_gradient(x, y, weight)
106
+ 2.0 * (x.dot(weight) - y)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/linear_model/base_linear_model'
4
+ require 'rumale/base/classifier'
5
+
6
+ module Rumale
7
+ module LinearModel
8
+ # LogisticRegression is a class that implements Logistic Regression
9
+ # with mini-batch stochastic gradient descent optimization.
10
+ # For multiclass classification problem, it uses one-vs-the-rest strategy.
11
+ #
12
+ # @example
13
+ # estimator =
14
+ # Rumale::LinearModel::LogisticRegression.new(reg_param: 1.0, max_iter: 1000, batch_size: 20, random_seed: 1)
15
+ # estimator.fit(training_samples, traininig_labels)
16
+ # results = estimator.predict(testing_samples)
17
+ #
18
+ # *Reference*
19
+ # - S. Shalev-Shwartz, Y. Singer, N. Srebro, and A. Cotter, "Pegasos: Primal Estimated sub-GrAdient SOlver for SVM," Mathematical Programming, vol. 127 (1), pp. 3--30, 2011.
20
+ class LogisticRegression < BaseLinearModel
21
+ include Base::Classifier
22
+
23
+ # Return the weight vector for Logistic Regression.
24
+ # @return [Numo::DFloat] (shape: [n_classes, n_features])
25
+ attr_reader :weight_vec
26
+
27
+ # Return the bias term (a.k.a. intercept) for Logistic Regression.
28
+ # @return [Numo::DFloat] (shape: [n_classes])
29
+ attr_reader :bias_term
30
+
31
+ # Return the class labels.
32
+ # @return [Numo::Int32] (shape: [n_classes])
33
+ attr_reader :classes
34
+
35
+ # Return the random generator for performing random sampling.
36
+ # @return [Random]
37
+ attr_reader :rng
38
+
39
+ # Create a new classifier with Logisitc Regression by the SGD optimization.
40
+ #
41
+ # @param reg_param [Float] The regularization parameter.
42
+ # @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
43
+ # @param bias_scale [Float] The scale of the bias term.
44
+ # If fit_bias is true, the feature vector v becoms [v; bias_scale].
45
+ # @param max_iter [Integer] The maximum number of iterations.
46
+ # @param batch_size [Integer] The size of the mini batches.
47
+ # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
48
+ # If nil is given, Nadam is used.
49
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
50
+ def initialize(reg_param: 1.0, fit_bias: false, bias_scale: 1.0,
51
+ max_iter: 1000, batch_size: 20, optimizer: nil, random_seed: nil)
52
+ check_params_float(reg_param: reg_param, bias_scale: bias_scale)
53
+ check_params_integer(max_iter: max_iter, batch_size: batch_size)
54
+ check_params_boolean(fit_bias: fit_bias)
55
+ check_params_type_or_nil(Integer, random_seed: random_seed)
56
+ check_params_positive(reg_param: reg_param, bias_scale: bias_scale, max_iter: max_iter, batch_size: batch_size)
57
+ super
58
+ @classes = nil
59
+ end
60
+
61
+ # Fit the model with given training data.
62
+ #
63
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
64
+ # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
65
+ # @return [LogisticRegression] The learned classifier itself.
66
+ def fit(x, y)
67
+ check_sample_array(x)
68
+ check_label_array(y)
69
+ check_sample_label_size(x, y)
70
+
71
+ @classes = Numo::Int32[*y.to_a.uniq.sort]
72
+ n_classes = @classes.size
73
+ n_features = x.shape[1]
74
+
75
+ if n_classes > 2
76
+ @weight_vec = Numo::DFloat.zeros(n_classes, n_features)
77
+ @bias_term = Numo::DFloat.zeros(n_classes)
78
+ n_classes.times do |n|
79
+ bin_y = Numo::Int32.cast(y.eq(@classes[n])) * 2 - 1
80
+ @weight_vec[n, true], @bias_term[n] = partial_fit(x, bin_y)
81
+ end
82
+ else
83
+ negative_label = y.to_a.uniq.min
84
+ bin_y = Numo::Int32.cast(y.ne(negative_label)) * 2 - 1
85
+ @weight_vec, @bias_term = partial_fit(x, bin_y)
86
+ end
87
+
88
+ self
89
+ end
90
+
91
+ # Calculate confidence scores for samples.
92
+ #
93
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
94
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Confidence score per sample.
95
+ def decision_function(x)
96
+ check_sample_array(x)
97
+ x.dot(@weight_vec.transpose) + @bias_term
98
+ end
99
+
100
+ # Predict class labels for samples.
101
+ #
102
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
103
+ # @return [Numo::Int32] (shape: [n_samples]) Predicted class label per sample.
104
+ def predict(x)
105
+ check_sample_array(x)
106
+
107
+ return Numo::Int32.cast(predict_proba(x)[true, 1].ge(0.5)) * 2 - 1 if @classes.size <= 2
108
+
109
+ n_samples, = x.shape
110
+ decision_values = predict_proba(x)
111
+ Numo::Int32.asarray(Array.new(n_samples) { |n| @classes[decision_values[n, true].max_index] })
112
+ end
113
+
114
+ # Predict probability for samples.
115
+ #
116
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
117
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) Predicted probability of each class per sample.
118
+ def predict_proba(x)
119
+ check_sample_array(x)
120
+
121
+ proba = 1.0 / (Numo::NMath.exp(-decision_function(x)) + 1.0)
122
+ return (proba.transpose / proba.sum(axis: 1)).transpose if @classes.size > 2
123
+
124
+ n_samples, = x.shape
125
+ probs = Numo::DFloat.zeros(n_samples, 2)
126
+ probs[true, 1] = proba
127
+ probs[true, 0] = 1.0 - proba
128
+ probs
129
+ end
130
+
131
+ # Dump marshal data.
132
+ # @return [Hash] The marshal data about LogisticRegression.
133
+ def marshal_dump
134
+ { params: @params,
135
+ weight_vec: @weight_vec,
136
+ bias_term: @bias_term,
137
+ classes: @classes,
138
+ rng: @rng }
139
+ end
140
+
141
+ # Load marshal data.
142
+ # @return [nil]
143
+ def marshal_load(obj)
144
+ @params = obj[:params]
145
+ @weight_vec = obj[:weight_vec]
146
+ @bias_term = obj[:bias_term]
147
+ @classes = obj[:classes]
148
+ @rng = obj[:rng]
149
+ nil
150
+ end
151
+
152
+ private
153
+
154
+ def calc_loss_gradient(x, y, weight)
155
+ y / (Numo::NMath.exp(-y * x.dot(weight)) + 1.0) - y
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/linear_model/base_linear_model'
4
+ require 'rumale/base/regressor'
5
+
6
+ module Rumale
7
+ module LinearModel
8
+ # Ridge is a class that implements Ridge Regression
9
+ # with mini-batch stochastic gradient descent optimization.
10
+ #
11
+ # @example
12
+ # estimator =
13
+ # Rumale::LinearModel::Ridge.new(reg_param: 0.1, max_iter: 1000, batch_size: 20, random_seed: 1)
14
+ # estimator.fit(training_samples, traininig_values)
15
+ # results = estimator.predict(testing_samples)
16
+ #
17
+ class Ridge < BaseLinearModel
18
+ include Base::Regressor
19
+
20
+ # Return the weight vector.
21
+ # @return [Numo::DFloat] (shape: [n_outputs, n_features])
22
+ attr_reader :weight_vec
23
+
24
+ # Return the bias term (a.k.a. intercept).
25
+ # @return [Numo::DFloat] (shape: [n_outputs])
26
+ attr_reader :bias_term
27
+
28
+ # Return the random generator for random sampling.
29
+ # @return [Random]
30
+ attr_reader :rng
31
+
32
+ # Create a new Ridge regressor.
33
+ #
34
+ # @param reg_param [Float] The regularization parameter.
35
+ # @param fit_bias [Boolean] The flag indicating whether to fit the bias term.
36
+ # @param bias_scale [Float] The scale of the bias term.
37
+ # @param max_iter [Integer] The maximum number of iterations.
38
+ # @param batch_size [Integer] The size of the mini batches.
39
+ # @param optimizer [Optimizer] The optimizer to calculate adaptive learning rate.
40
+ # If nil is given, Nadam is used.
41
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
42
+ def initialize(reg_param: 1.0, fit_bias: false, bias_scale: 1.0, max_iter: 1000, batch_size: 10, optimizer: nil, random_seed: nil)
43
+ check_params_float(reg_param: reg_param, bias_scale: bias_scale)
44
+ check_params_integer(max_iter: max_iter, batch_size: batch_size)
45
+ check_params_boolean(fit_bias: fit_bias)
46
+ check_params_type_or_nil(Integer, random_seed: random_seed)
47
+ check_params_positive(reg_param: reg_param, max_iter: max_iter, batch_size: batch_size)
48
+ super
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
+ # @param y [Numo::Int32] (shape: [n_samples, n_outputs]) The target values to be used for fitting the model.
55
+ # @return [Ridge] The learned regressor itself.
56
+ def fit(x, y)
57
+ check_sample_array(x)
58
+ check_tvalue_array(y)
59
+ check_sample_tvalue_size(x, y)
60
+
61
+ n_outputs = y.shape[1].nil? ? 1 : y.shape[1]
62
+ n_features = x.shape[1]
63
+
64
+ if n_outputs > 1
65
+ @weight_vec = Numo::DFloat.zeros(n_outputs, n_features)
66
+ @bias_term = Numo::DFloat.zeros(n_outputs)
67
+ n_outputs.times { |n| @weight_vec[n, true], @bias_term[n] = partial_fit(x, y[true, n]) }
68
+ else
69
+ @weight_vec, @bias_term = partial_fit(x, y)
70
+ end
71
+
72
+ self
73
+ end
74
+
75
+ # Predict values for samples.
76
+ #
77
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
78
+ # @return [Numo::DFloat] (shape: [n_samples, n_outputs]) Predicted values per sample.
79
+ def predict(x)
80
+ check_sample_array(x)
81
+ x.dot(@weight_vec.transpose) + @bias_term
82
+ end
83
+
84
+ # Dump marshal data.
85
+ # @return [Hash] The marshal data about Ridge.
86
+ def marshal_dump
87
+ { params: @params,
88
+ weight_vec: @weight_vec,
89
+ bias_term: @bias_term,
90
+ rng: @rng }
91
+ end
92
+
93
+ # Load marshal data.
94
+ # @return [nil]
95
+ def marshal_load(obj)
96
+ @params = obj[:params]
97
+ @weight_vec = obj[:weight_vec]
98
+ @bias_term = obj[:bias_term]
99
+ @rng = obj[:rng]
100
+ nil
101
+ end
102
+
103
+ private
104
+
105
+ def calc_loss_gradient(x, y, weight)
106
+ 2.0 * (x.dot(weight) - y)
107
+ end
108
+ end
109
+ end
110
+ end