rumale 0.22.1 → 0.22.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 475798da3815141b5337bc7803eca26978bbc98c36a2be4d681bc63f778f5840
4
- data.tar.gz: 71841127edccbeea2b30c4bd8a744735933c1fcf8c7d6afa507cd2d361c8b5c8
3
+ metadata.gz: 703a6895f4218ca45c5d5ae5e86559b077cf1be213d4939eb1e9ab94eac4621d
4
+ data.tar.gz: 5862466e565d1e6030c35494b5028ae980a47d373e90050c62266055fcecd374
5
5
  SHA512:
6
- metadata.gz: 8c90eaffa3847e3cc4f31c58e3d74f66a86e2cf0bd1c6e5aa386f9519de3984ac1c605187119e0ec01585c82cf8c06e4f4aa2f19c7b40883b784e834e2e801d8
7
- data.tar.gz: 336b1afcc35e52e1c13ced74f527d54c994ff66509cf9b8b2f81dce62692078964a453df790a5bcaf8ea2bd156277d719a33958de2f57aa64d97beeafdc48d01
6
+ metadata.gz: 988d55c681a102e0c65b9133c6aeafc049e33755955f959d6e6046f5601dd192af881424355a2b373ed2e7a5a16b74236698aef5372e09584b10fe28d1b7bc21
7
+ data.tar.gz: adc58efa3b46d9fc1a87ddb2a4df32472507d61f21a3a0eb07026068cc5e41af166fb0a0f8ae23f1b23aec649b22835a50edbed79d35255e8cc231b82b31eb8c
@@ -1,6 +1,6 @@
1
1
  name: build
2
2
 
3
- on: [push]
3
+ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  build:
@@ -1,5 +1,6 @@
1
1
  require:
2
2
  - rubocop-performance
3
+ - rubocop-rake
3
4
  - rubocop-rspec
4
5
 
5
6
  AllCops:
@@ -1,5 +1,11 @@
1
+ # 0.22.2
2
+ - Add classifier and regressor classes for stacking method.
3
+ - [StackingClassifier](https://yoshoku.github.io/rumale/doc/Rumale/Ensemble/StackingClassifier.html)
4
+ - [StackingRegressor](https://yoshoku.github.io/rumale/doc/Rumale/Ensemble/StackingRegressor.html)
5
+ - Refactor some codes with Rubocop.
6
+
1
7
  # 0.22.1
2
- - Add transfomer class for MLKR, that implements Metric Learning for Kernel Regression.
8
+ - Add transfomer class for [MLKR](https://yoshoku.github.io/rumale/doc/Rumale/MetricLearning/MLKR.html), that implements Metric Learning for Kernel Regression.
3
9
  - Refactor NeighbourhoodComponentAnalysis.
4
10
  - Update API documentation.
5
11
 
data/Gemfile CHANGED
@@ -9,7 +9,8 @@ gem 'parallel', '>= 1.17.0'
9
9
  gem 'rake', '~> 12.0'
10
10
  gem 'rake-compiler', '~> 1.0'
11
11
  gem 'rspec', '~> 3.0'
12
- gem 'rubocop', '~> 0.91'
12
+ gem 'rubocop', '~> 1.0'
13
13
  gem 'rubocop-performance', '~> 1.8'
14
- gem 'rubocop-rspec', '~> 1.43'
14
+ gem 'rubocop-rake', '~> 0.5'
15
+ gem 'rubocop-rspec', '~> 2.0'
15
16
  gem 'simplecov', '~> 0.19'
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Build Status](https://github.com/yoshoku/rumale/workflows/build/badge.svg)](https://github.com/yoshoku/rumale/actions?query=workflow%3Abuild)
6
6
  [![Gem Version](https://badge.fury.io/rb/rumale.svg)](https://badge.fury.io/rb/rumale)
7
- [![BSD 2-Clause License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://github.com/yoshoku/rumale/blob/master/LICENSE.txt)
7
+ [![BSD 2-Clause License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://github.com/yoshoku/rumale/blob/main/LICENSE.txt)
8
8
  [![Documentation](https://img.shields.io/badge/api-reference-blue.svg)](https://yoshoku.github.io/rumale/doc/)
9
9
 
10
10
  Rumale (**Ru**by **ma**chine **le**arning) is a machine learning library in Ruby.
@@ -244,4 +244,4 @@ The gem is available as open source under the terms of the [BSD 2-clause License
244
244
  ## Code of Conduct
245
245
 
246
246
  Everyone interacting in the Rumale project’s codebases, issue trackers,
247
- chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/Rumale/blob/master/CODE_OF_CONDUCT.md).
247
+ chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/Rumale/blob/main/CODE_OF_CONDUCT.md).
@@ -59,6 +59,8 @@ require 'rumale/ensemble/random_forest_classifier'
59
59
  require 'rumale/ensemble/random_forest_regressor'
60
60
  require 'rumale/ensemble/extra_trees_classifier'
61
61
  require 'rumale/ensemble/extra_trees_regressor'
62
+ require 'rumale/ensemble/stacking_classifier'
63
+ require 'rumale/ensemble/stacking_regressor'
62
64
  require 'rumale/clustering/k_means'
63
65
  require 'rumale/clustering/mini_batch_k_means'
64
66
  require 'rumale/clustering/k_medoids'
@@ -59,7 +59,7 @@ module Rumale
59
59
  @params[:solver] = if solver == 'auto'
60
60
  load_linalg? ? 'evd' : 'fpt'
61
61
  else
62
- solver != 'evd' ? 'fpt' : 'evd'
62
+ solver != 'evd' ? 'fpt' : 'evd' # rubocop:disable Style/NegatedIfElseCondition
63
63
  end
64
64
  @params[:n_components] = n_components
65
65
  @params[:max_iter] = max_iter
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/base/base_estimator'
4
+ require 'rumale/base/classifier'
5
+
6
+ module Rumale
7
+ module Ensemble
8
+ # StackingClassifier is a class that implements classifier with stacking method.
9
+ #
10
+ # @example
11
+ # estimators = {
12
+ # lgr: Rumale::LinearModel::LogisticRegression.new(reg_param: 1e-2, random_seed: 1),
13
+ # mlp: Rumele::NeuralNetwork::MLPClassifier.new(hidden_units: [256], random_seed: 1),
14
+ # rnd: Rumale::Ensemble::RandomForestClassifier.new(random_seed: 1)
15
+ # }
16
+ # meta_estimator = Rumale::LinearModel::LogisticRegression.new(random_seed: 1)
17
+ # classifier = Rumale::Ensemble::StackedClassifier.new(
18
+ # estimators: estimators, meta_estimator: meta_estimator, random_seed: 1
19
+ # )
20
+ # classifier.fit(training_samples, traininig_labels)
21
+ # results = classifier.predict(testing_samples)
22
+ #
23
+ # *Reference*
24
+ # - Zhou, Z-H., "Ensemble Mehotds - Foundations and Algorithms," CRC Press Taylor and Francis Group, Chapman and Hall/CRC, 2012.
25
+ class StackingClassifier
26
+ include Base::BaseEstimator
27
+ include Base::Classifier
28
+
29
+ # Return the base classifiers.
30
+ # @return [Hash<Symbol,Classifier>]
31
+ attr_reader :estimators
32
+
33
+ # Return the meta classifier.
34
+ # @return [Classifier]
35
+ attr_reader :meta_estimator
36
+
37
+ # Return the class labels.
38
+ # @return [Numo::Int32] (size: n_classes)
39
+ attr_reader :classes
40
+
41
+ # Return the method used by each base classifier.
42
+ # @return [Hash<Symbol,Symbol>]
43
+ attr_reader :stack_method
44
+
45
+ # Create a new classifier with stacking method.
46
+ #
47
+ # @param estimators [Hash<Symbol,Classifier>] The base classifiers for extracting meta features.
48
+ # @param meta_estimator [Classifier/Nil] The meta classifier that predicts class label.
49
+ # If nil is given, LogisticRegression is used.
50
+ # @param n_splits [Integer] The number of folds for cross validation with stratified k-fold on meta feature extraction in training phase.
51
+ # @param shuffle [Boolean] The flag indicating whether to shuffle the dataset on cross validation.
52
+ # @param stack_method [String] The method name of base classifier for using meta feature extraction.
53
+ # If 'auto' is given, it searches the callable method in the order 'predict_proba', 'decision_function', and 'predict'
54
+ # on each classifier.
55
+ # @param passthrough [Boolean] The flag indicating whether to concatenate the original features and meta features when training the meta classifier.
56
+ # @param random_seed [Integer/Nil] The seed value using to initialize the random generator on cross validation.
57
+ def initialize(estimators:, meta_estimator: nil, n_splits: 5, shuffle: true, stack_method: 'auto', passthrough: false, random_seed: nil)
58
+ check_params_type(Hash, estimators: estimators)
59
+ check_params_numeric(n_splits: n_splits)
60
+ check_params_string(stack_method: stack_method)
61
+ check_params_boolean(shuffle: shuffle, passthrough: passthrough)
62
+ check_params_numeric_or_nil(random_seed: random_seed)
63
+ @estimators = estimators
64
+ @meta_estimator = meta_estimator || Rumale::LinearModel::LogisticRegression.new
65
+ @classes = nil
66
+ @stack_method = nil
67
+ @output_size = nil
68
+ @params = {}
69
+ @params[:n_splits] = n_splits
70
+ @params[:shuffle] = shuffle
71
+ @params[:stack_method] = stack_method
72
+ @params[:passthrough] = passthrough
73
+ @params[:random_seed] = random_seed || srand
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]) The labels to be used for fitting the model.
80
+ # @return [StackedClassifier] The learned classifier itself.
81
+ def fit(x, y)
82
+ x = check_convert_sample_array(x)
83
+ y = check_convert_label_array(y)
84
+ check_sample_label_size(x, y)
85
+
86
+ n_samples, n_features = x.shape
87
+
88
+ @encoder = Rumale::Preprocessing::LabelEncoder.new
89
+ y_encoded = @encoder.fit_transform(y)
90
+ @classes = Numo::NArray[*@encoder.classes]
91
+
92
+ # training base classifiers with all training data.
93
+ @estimators.each_key { |name| @estimators[name].fit(x, y_encoded) }
94
+
95
+ # detecting feature extraction method and its size of output for each base classifier.
96
+ @stack_method = detect_stack_method
97
+ @output_size = detect_output_size(n_features)
98
+
99
+ # extracting meta features with base classifiers.
100
+ n_components = @output_size.values.inject(:+)
101
+ z = Numo::DFloat.zeros(n_samples, n_components)
102
+
103
+ kf = Rumale::ModelSelection::StratifiedKFold.new(
104
+ n_splits: @params[:n_splits], shuffle: @params[:shuffle], random_seed: @params[:random_seed]
105
+ )
106
+
107
+ kf.split(x, y_encoded).each do |train_ids, valid_ids|
108
+ x_train = x[train_ids, true]
109
+ y_train = y_encoded[train_ids]
110
+ x_valid = x[valid_ids, true]
111
+ f_start = 0
112
+ @estimators.each_key do |name|
113
+ est_fold = Marshal.load(Marshal.dump(@estimators[name]))
114
+ f_last = f_start + @output_size[name]
115
+ f_position = @output_size[name] == 1 ? f_start : f_start...f_last
116
+ z[valid_ids, f_position] = est_fold.fit(x_train, y_train).public_send(@stack_method[name], x_valid)
117
+ f_start = f_last
118
+ end
119
+ end
120
+
121
+ # concatenating original features.
122
+ z = Numo::NArray.hstack([z, x]) if @params[:passthrough]
123
+
124
+ # training meta classifier.
125
+ @meta_estimator.fit(z, y_encoded)
126
+
127
+ self
128
+ end
129
+
130
+ # Calculate confidence scores for samples.
131
+ #
132
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to compute the scores.
133
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) The confidence score per sample.
134
+ def decision_function(x)
135
+ x = check_convert_sample_array(x)
136
+ z = transform(x)
137
+ @meta_estimator.decision_function(z)
138
+ end
139
+
140
+ # Predict class labels for samples.
141
+ #
142
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the labels.
143
+ # @return [Numo::Int32] (shape: [n_samples]) The predicted class label per sample.
144
+ def predict(x)
145
+ x = check_convert_sample_array(x)
146
+ z = transform(x)
147
+ Numo::Int32.cast(@encoder.inverse_transform(@meta_estimator.predict(z)))
148
+ end
149
+
150
+ # Predict probability for samples.
151
+ #
152
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the probailities.
153
+ # @return [Numo::DFloat] (shape: [n_samples, n_classes]) The predicted probability of each class per sample.
154
+ def predict_proba(x)
155
+ x = check_convert_sample_array(x)
156
+ z = transform(x)
157
+ @meta_estimator.predict_proba(z)
158
+ end
159
+
160
+ # Transform the given data with the learned model.
161
+ #
162
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be transformed with the learned model.
163
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The meta features for samples.
164
+ def transform(x)
165
+ x = check_convert_sample_array(x)
166
+ n_samples = x.shape[0]
167
+ n_components = @output_size.values.inject(:+)
168
+ z = Numo::DFloat.zeros(n_samples, n_components)
169
+ f_start = 0
170
+ @estimators.each_key do |name|
171
+ f_last = f_start + @output_size[name]
172
+ f_position = @output_size[name] == 1 ? f_start : f_start...f_last
173
+ z[true, f_position] = @estimators[name].public_send(@stack_method[name], x)
174
+ f_start = f_last
175
+ end
176
+ z = Numo::NArray.hstack([z, x]) if @params[:passthrough]
177
+ z
178
+ end
179
+
180
+ # Fit the model with training data, and then transform them with the learned model.
181
+ #
182
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
183
+ # @param y [Numo::Int32] (shape: [n_samples]) The labels to be used for fitting the model.
184
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The meta features for training data.
185
+ def fit_transform(x, y)
186
+ x = check_convert_sample_array(x)
187
+ y = check_convert_label_array(y)
188
+ fit(x, y).transform(x)
189
+ end
190
+
191
+ private
192
+
193
+ STACK_METHODS = %i[predict_proba decision_function predict].freeze
194
+
195
+ private_constant :STACK_METHODS
196
+
197
+ def detect_stack_method
198
+ if @params[:stack_method] == 'auto'
199
+ @estimators.each_key.with_object({}) { |name, obj| obj[name] = STACK_METHODS.detect { |m| @estimators[name].respond_to?(m) } }
200
+ else
201
+ @estimators.each_key.with_object({}) { |name, obj| obj[name] = @params[:stack_method].to_sym }
202
+ end
203
+ end
204
+
205
+ def detect_output_size(n_features)
206
+ x_dummy = Numo::DFloat.new(2, n_features).rand
207
+ @estimators.each_key.with_object({}) do |name, obj|
208
+ output_dummy = @estimators[name].public_send(@stack_method[name], x_dummy)
209
+ obj[name] = output_dummy.ndim == 1 ? 1 : output_dummy.shape[1]
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/base/base_estimator'
4
+ require 'rumale/base/regressor'
5
+
6
+ module Rumale
7
+ module Ensemble
8
+ # StackingRegressor is a class that implements regressor with stacking method.
9
+ #
10
+ # @example
11
+ # estimators = {
12
+ # las: Rumale::LinearModel::Lasso.new(reg_param: 1e-2, random_seed: 1),
13
+ # mlp: Rumele::NeuralNetwork::MLPRegressor.new(hidden_units: [256], random_seed: 1),
14
+ # rnd: Rumale::Ensemble::RandomForestRegressor.new(random_seed: 1)
15
+ # }
16
+ # meta_estimator = Rumale::LinearModel::Ridge.new(random_seed: 1)
17
+ # regressor = Rumale::Ensemble::StackedRegressor.new(
18
+ # estimators: estimators, meta_estimator: meta_estimator, random_seed: 1
19
+ # )
20
+ # regressor.fit(training_samples, traininig_values)
21
+ # results = regressor.predict(testing_samples)
22
+ #
23
+ # *Reference*
24
+ # - Zhou, Z-H., "Ensemble Mehotds - Foundations and Algorithms," CRC Press Taylor and Francis Group, Chapman and Hall/CRC, 2012.
25
+ class StackingRegressor
26
+ include Base::BaseEstimator
27
+ include Base::Regressor
28
+
29
+ # Return the base regressors.
30
+ # @return [Hash<Symbol,Regressor>]
31
+ attr_reader :estimators
32
+
33
+ # Return the meta regressor.
34
+ # @return [Regressor]
35
+ attr_reader :meta_estimator
36
+
37
+ # Create a new regressor with stacking method.
38
+ #
39
+ # @param estimators [Hash<Symbol,Regressor>] The base regressors for extracting meta features.
40
+ # @param meta_estimator [Regressor/Nil] The meta regressor that predicts values.
41
+ # If nil is given, Ridge is used.
42
+ # @param n_splits [Integer] The number of folds for cross validation with k-fold on meta feature extraction in training phase.
43
+ # @param shuffle [Boolean] The flag indicating whether to shuffle the dataset on cross validation.
44
+ # @param passthrough [Boolean] The flag indicating whether to concatenate the original features and meta features when training the meta regressor.
45
+ # @param random_seed [Integer/Nil] The seed value using to initialize the random generator on cross validation.
46
+ def initialize(estimators:, meta_estimator: nil, n_splits: 5, shuffle: true, passthrough: false, random_seed: nil)
47
+ check_params_type(Hash, estimators: estimators)
48
+ check_params_numeric(n_splits: n_splits)
49
+ check_params_boolean(shuffle: shuffle, passthrough: passthrough)
50
+ check_params_numeric_or_nil(random_seed: random_seed)
51
+ @estimators = estimators
52
+ @meta_estimator = meta_estimator || Rumale::LinearModel::Ridge.new
53
+ @output_size = nil
54
+ @params = {}
55
+ @params[:n_splits] = n_splits
56
+ @params[:shuffle] = shuffle
57
+ @params[:passthrough] = passthrough
58
+ @params[:random_seed] = random_seed || srand
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::DFloat] (shape: [n_samples, n_outputs]) The target variables to be used for fitting the model.
65
+ # @return [StackedRegressor] The learned regressor itself.
66
+ def fit(x, y)
67
+ x = check_convert_sample_array(x)
68
+ y = check_convert_tvalue_array(y)
69
+ check_sample_tvalue_size(x, y)
70
+
71
+ n_samples, n_features = x.shape
72
+ n_outputs = y.ndim == 1 ? 1 : y.shape[1]
73
+
74
+ # training base regressors with all training data.
75
+ @estimators.each_key { |name| @estimators[name].fit(x, y) }
76
+
77
+ # detecting size of output for each base regressor.
78
+ @output_size = detect_output_size(n_features)
79
+
80
+ # extracting meta features with base regressors.
81
+ n_components = @output_size.values.inject(:+)
82
+ z = Numo::DFloat.zeros(n_samples, n_components)
83
+
84
+ kf = Rumale::ModelSelection::KFold.new(
85
+ n_splits: @params[:n_splits], shuffle: @params[:shuffle], random_seed: @params[:random_seed]
86
+ )
87
+
88
+ kf.split(x, y).each do |train_ids, valid_ids|
89
+ x_train = x[train_ids, true]
90
+ y_train = n_outputs == 1 ? y[train_ids] : y[train_ids, true]
91
+ x_valid = x[valid_ids, true]
92
+ f_start = 0
93
+ @estimators.each_key do |name|
94
+ est_fold = Marshal.load(Marshal.dump(@estimators[name]))
95
+ f_last = f_start + @output_size[name]
96
+ f_position = @output_size[name] == 1 ? f_start : f_start...f_last
97
+ z[valid_ids, f_position] = est_fold.fit(x_train, y_train).predict(x_valid)
98
+ f_start = f_last
99
+ end
100
+ end
101
+
102
+ # concatenating original features.
103
+ z = Numo::NArray.hstack([z, x]) if @params[:passthrough]
104
+
105
+ # training meta regressor.
106
+ @meta_estimator.fit(z, y)
107
+
108
+ self
109
+ end
110
+
111
+ # Predict values for samples.
112
+ #
113
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to predict the values.
114
+ # @return [Numo::DFloat] (shape: [n_samples, n_outputs]) The predicted values per sample.
115
+ def predict(x)
116
+ x = check_convert_sample_array(x)
117
+ z = transform(x)
118
+ @meta_estimator.predict(z)
119
+ end
120
+
121
+ # Transform the given data with the learned model.
122
+ #
123
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The samples to be transformed with the learned model.
124
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The meta features for samples.
125
+ def transform(x)
126
+ x = check_convert_sample_array(x)
127
+ n_samples = x.shape[0]
128
+ n_components = @output_size.values.inject(:+)
129
+ z = Numo::DFloat.zeros(n_samples, n_components)
130
+ f_start = 0
131
+ @estimators.each_key do |name|
132
+ f_last = f_start + @output_size[name]
133
+ f_position = @output_size[name] == 1 ? f_start : f_start...f_last
134
+ z[true, f_position] = @estimators[name].predict(x)
135
+ f_start = f_last
136
+ end
137
+ z = Numo::NArray.hstack([z, x]) if @params[:passthrough]
138
+ z
139
+ end
140
+
141
+ # Fit the model with training data, and then transform them with the learned model.
142
+ #
143
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
144
+ # @param y [Numo::DFloat] (shape: [n_samples, n_outputs]) The target variables to be used for fitting the model.
145
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The meta features for training data.
146
+ def fit_transform(x, y)
147
+ x = check_convert_sample_array(x)
148
+ y = check_convert_tvalue_array(y)
149
+ fit(x, y).transform(x)
150
+ end
151
+
152
+ private
153
+
154
+ def detect_output_size(n_features)
155
+ x_dummy = Numo::DFloat.new(2, n_features).rand
156
+ @estimators.each_key.with_object({}) do |name, obj|
157
+ output_dummy = @estimators[name].predict(x_dummy)
158
+ obj[name] = output_dummy.ndim == 1 ? 1 : output_dummy.shape[1]
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -67,7 +67,7 @@ module Rumale
67
67
  def transform(x)
68
68
  raise 'FeatureHasher#transform requires Mmh3 but that is not loaded.' unless enable_mmh3?
69
69
 
70
- x = [x] unless x.is_a?(Array) # rubocop:disable Style/ArrayCoercion
70
+ x = [x] unless x.is_a?(Array)
71
71
  n_samples = x.size
72
72
 
73
73
  z = Numo::DFloat.zeros(n_samples, n_features)
@@ -99,7 +99,7 @@ module Rumale
99
99
  # @param x [Array<Hash>] (shape: [n_samples]) The array of hash consisting of feature names and values.
100
100
  # @return [Numo::DFloat] (shape: [n_samples, n_features]) The encoded sample array.
101
101
  def transform(x)
102
- x = [x] unless x.is_a?(Array) # rubocop:disable Style/ArrayCoercion
102
+ x = [x] unless x.is_a?(Array)
103
103
  n_samples = x.size
104
104
  n_features = @vocabulary.size
105
105
  z = Numo::DFloat.zeros(n_samples, n_features)
@@ -82,7 +82,7 @@ module Rumale
82
82
  @params[:solver] = if solver == 'auto'
83
83
  load_linalg? ? 'svd' : 'sgd'
84
84
  else
85
- solver != 'svd' ? 'sgd' : 'svd'
85
+ solver != 'svd' ? 'sgd' : 'svd' # rubocop:disable Style/NegatedIfElseCondition
86
86
  end
87
87
  @params[:decay] ||= @params[:learning_rate]
88
88
  @params[:random_seed] ||= srand
@@ -181,7 +181,7 @@ module Rumale
181
181
  @classes.size > 2
182
182
  end
183
183
 
184
- def fit_lbfgs(base_x, base_y)
184
+ def fit_lbfgs(base_x, base_y) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
185
185
  if multiclass_problem?
186
186
  fnc = proc do |w, x, y, a|
187
187
  n_features = x.shape[1]
@@ -85,7 +85,7 @@ module Rumale
85
85
  @params[:solver] = if solver == 'auto'
86
86
  load_linalg? ? 'svd' : 'sgd'
87
87
  else
88
- solver != 'svd' ? 'sgd' : 'svd'
88
+ solver != 'svd' ? 'sgd' : 'svd' # rubocop:disable Style/NegatedIfElseCondition
89
89
  end
90
90
  @params[:decay] ||= @params[:reg_param] * @params[:learning_rate]
91
91
  @params[:random_seed] ||= srand
@@ -123,7 +123,7 @@ module Rumale
123
123
  # @param gamma [Float] The parameter of polynomial kernel, if nil it is 1 / n_features.
124
124
  # @param coef [Integer] The parameter of polynomial kernel.
125
125
  # @return [Numo::DFloat] (shape: [n_samples_x, n_samples_x] or [n_samples_x, n_samples_y] if y is given)
126
- def polynomial_kernel(x, y = nil, degree = 3, gamma = nil, coef = 1)
126
+ def polynomial_kernel(x, y = nil, degree = 3, gamma = nil, coef = 1) # rubocop:disable Metrics/ParameterLists
127
127
  y = x if y.nil?
128
128
  gamma ||= 1.0 / x.shape[1]
129
129
  x = Rumale::Validation.check_convert_sample_array(x)
@@ -109,7 +109,7 @@ module Rumale
109
109
 
110
110
  # @!visibility private
111
111
  def check_params_positive(params = {})
112
- params.reject { |_, v| v.nil? }.each { |k, v| raise ArgumentError, "Expect #{k} to be positive value" if v.negative? }
112
+ params.compact.each { |k, v| raise ArgumentError, "Expect #{k} to be positive value" if v.negative? }
113
113
  nil
114
114
  end
115
115
  end
@@ -3,5 +3,5 @@
3
3
  # Rumale is a machine learning library in Ruby.
4
4
  module Rumale
5
5
  # The version of Rumale you are using.
6
- VERSION = '0.22.1'
6
+ VERSION = '0.22.2'
7
7
  end
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
38
38
 
39
39
  spec.metadata = {
40
40
  'homepage_uri' => 'https://github.com/yoshoku/rumale',
41
- 'changelog_uri' => 'https://github.com/yoshoku/rumale/blob/master/CHANGELOG.md',
41
+ 'changelog_uri' => 'https://github.com/yoshoku/rumale/blob/main/CHANGELOG.md',
42
42
  'source_code_uri' => 'https://github.com/yoshoku/rumale',
43
43
  'documentation_uri' => 'https://yoshoku.github.io/rumale/doc/',
44
44
  'bug_tracker_uri' => 'https://github.com/yoshoku/rumale/issues'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rumale
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.1
4
+ version: 0.22.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-05 00:00:00.000000000 Z
11
+ date: 2021-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -104,6 +104,8 @@ files:
104
104
  - lib/rumale/ensemble/gradient_boosting_regressor.rb
105
105
  - lib/rumale/ensemble/random_forest_classifier.rb
106
106
  - lib/rumale/ensemble/random_forest_regressor.rb
107
+ - lib/rumale/ensemble/stacking_classifier.rb
108
+ - lib/rumale/ensemble/stacking_regressor.rb
107
109
  - lib/rumale/evaluation_measure/accuracy.rb
108
110
  - lib/rumale/evaluation_measure/adjusted_rand_score.rb
109
111
  - lib/rumale/evaluation_measure/calinski_harabasz_score.rb
@@ -205,11 +207,11 @@ licenses:
205
207
  - BSD-2-Clause
206
208
  metadata:
207
209
  homepage_uri: https://github.com/yoshoku/rumale
208
- changelog_uri: https://github.com/yoshoku/rumale/blob/master/CHANGELOG.md
210
+ changelog_uri: https://github.com/yoshoku/rumale/blob/main/CHANGELOG.md
209
211
  source_code_uri: https://github.com/yoshoku/rumale
210
212
  documentation_uri: https://yoshoku.github.io/rumale/doc/
211
213
  bug_tracker_uri: https://github.com/yoshoku/rumale/issues
212
- post_install_message:
214
+ post_install_message:
213
215
  rdoc_options: []
214
216
  require_paths:
215
217
  - lib
@@ -225,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
227
  version: '0'
226
228
  requirements: []
227
229
  rubygems_version: 3.1.4
228
- signing_key:
230
+ signing_key:
229
231
  specification_version: 4
230
232
  summary: Rumale is a machine learning library in Ruby. Rumale provides machine learning
231
233
  algorithms with interfaces similar to Scikit-Learn in Python.