rumale-kernel_approximation 0.24.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 30bd034634876366a9bcb1c4aad391a8447b2b6e4c9c11ef2626c20a55d5fbf6
4
+ data.tar.gz: bd072bc7a8927e5702ff4ec3bce9e2b289672d31bdab8503fcd77045a6d5d3eb
5
+ SHA512:
6
+ metadata.gz: ab986c1eac6cc07412dbbcf025f5951ba42f6cf1f93cc4b9c7dcf7c815b0834a7ba24aa713999a0b97b0f4e065e4f2e705238baaca83a91cca0bf5c8cea5771f
7
+ data.tar.gz: 2c6abdd6c60d68353da3745a32338daa782ac84a1f1cd47e08816ea393a35d7d5199dfcdca0af4dede04bb5b95291cdc2424a01e69ba1734f3291c18d44d027a
data/LICENSE.txt ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2022 Atsushi Tatsuma
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the copyright holder nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Rumale::KernelApproximation
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rumale-kernel_approximation.svg)](https://badge.fury.io/rb/rumale-kernel_approximation)
4
+ [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/rumale/blob/main/rumale-kernel_approximation/LICENSE.txt)
5
+ [![Documentation](https://img.shields.io/badge/api-reference-blue.svg)](https://yoshoku.github.io/rumale/doc/Rumale/KernelApproximation.html)
6
+
7
+ Rumale is a machine learning library in Ruby.
8
+ Rumale::KernelApproximation provides kernel approximation algorithms,
9
+ such as RBF feature mapping and Nystroem method,
10
+ with Rumale interface.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'rumale-kernel_approximation'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle install
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install rumale-kernel_approximation
27
+
28
+ ## Documentation
29
+
30
+ - [Rumale API Documentation - KernelApproximation](https://yoshoku.github.io/rumale/doc/Rumale/KernelApproximation.html)
31
+
32
+ ## License
33
+
34
+ The gem is available as open source under the terms of the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/base/estimator'
4
+ require 'rumale/base/transformer'
5
+ require 'rumale/pairwise_metric'
6
+ require 'rumale/validation'
7
+
8
+ module Rumale
9
+ module KernelApproximation
10
+ # Nystroem is a class that implements feature mapping with Nystroem method.
11
+ #
12
+ # @example
13
+ # require 'numo/linalg/autoloader'
14
+ # require 'rumale/kernel_approximation/nystroem'
15
+ #
16
+ # transformer = Rumale::KernelApproximation::Nystroem.new(kernel: 'rbf', gamma: 1, n_components: 128, random_seed: 1)
17
+ # new_training_samples = transformer.fit_transform(training_samples)
18
+ # new_testing_samples = transformer.transform(testing_samples)
19
+ #
20
+ # *Reference*
21
+ # - Yang, T., Li, Y., Mahdavi, M., Jin, R., and Zhou, Z-H., "Nystrom Method vs Random Fourier Features: A Theoretical and Empirical Comparison," Advances in NIPS'12, Vol. 1, pp. 476--484, 2012.
22
+ class Nystroem < ::Rumale::Base::Estimator
23
+ include ::Rumale::Base::Transformer
24
+
25
+ # Returns the randomly sampled training data for feature mapping.
26
+ # @return [Numo::DFloat] (shape: n_components, n_features])
27
+ attr_reader :components
28
+
29
+ # Returns the indices sampled training data.
30
+ # @return [Numo::Int32] (shape: [n_components])
31
+ attr_reader :component_indices
32
+
33
+ # Returns the normalizing factors.
34
+ # @return [Numo::DFloat] (shape: [n_components, n_components])
35
+ attr_reader :normalizer
36
+
37
+ # Return the random generator for transformation.
38
+ # @return [Random]
39
+ attr_reader :rng
40
+
41
+ # Create a new transformer for mapping to kernel feature space with Nystrom method.
42
+ #
43
+ # @param kernel [String] The type of kernel function ('rbf', 'linear', 'poly', and 'sigmoid)
44
+ # @param gamma [Float] The gamma parameter in rbf/poly/sigmoid kernel function.
45
+ # @param degree [Integer] The degree parameter in polynomial kernel function.
46
+ # @param coef [Float] The coefficient in poly/sigmoid kernel function.
47
+ # @param n_components [Integer] The number of dimensions of the kernel feature space.
48
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
49
+ def initialize(kernel: 'rbf', gamma: 1, degree: 3, coef: 1, n_components: 100, random_seed: nil)
50
+ super()
51
+ @params = {
52
+ kernel: kernel,
53
+ gamma: gamma,
54
+ degree: degree,
55
+ coef: coef,
56
+ n_components: n_components,
57
+ random_seed: (random_seed || srand)
58
+ }
59
+ @rng = Random.new(@params[:random_seed])
60
+ end
61
+
62
+ # Fit the model with given training data.
63
+ #
64
+ # @overload fit(x) -> Nystroem
65
+ # @param x [Numo::NArray] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
66
+ # @return [Nystroem] The learned transformer itself.
67
+ def fit(x, _y = nil)
68
+ x = ::Rumale::Validation.check_convert_sample_array(x)
69
+ raise 'Nystroem#fit requires Numo::Linalg but that is not loaded.' unless enable_linalg?(warning: false)
70
+
71
+ # initialize some variables.
72
+ sub_rng = @rng.dup
73
+ n_samples = x.shape[0]
74
+ n_components = [1, [@params[:n_components], n_samples].min].max
75
+
76
+ # random sampling.
77
+ @component_indices = Numo::Int32.cast(Array(0...n_samples).shuffle(random: sub_rng)[0...n_components])
78
+ @components = x[@component_indices, true].dup
79
+
80
+ # calculate normalizing factor.
81
+ kernel_mat = kernel_mat(@components)
82
+ eig_vals, eig_vecs = Numo::Linalg.eigh(kernel_mat)
83
+ la = eig_vals.class.maximum(eig_vals.reverse, 1e-12)
84
+ u = eig_vecs.reverse(1)
85
+ @normalizer = u.dot((1.0 / Numo::NMath.sqrt(la)).diag)
86
+
87
+ self
88
+ end
89
+
90
+ # Fit the model with training data, and then transform them with the learned model.
91
+ #
92
+ # @overload fit_transform(x) -> Numo::DFloat
93
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
94
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data
95
+ def fit_transform(x, _y = nil)
96
+ x = ::Rumale::Validation.check_convert_sample_array(x)
97
+
98
+ fit(x).transform(x)
99
+ end
100
+
101
+ # Transform the given data with the learned model.
102
+ #
103
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The data to be transformed with the learned model.
104
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data.
105
+ def transform(x)
106
+ x = ::Rumale::Validation.check_convert_sample_array(x)
107
+
108
+ z = kernel_mat(x, @components)
109
+ z.dot(@normalizer)
110
+ end
111
+
112
+ private
113
+
114
+ def kernel_mat(x, y = nil)
115
+ case @params[:kernel]
116
+ when 'rbf'
117
+ ::Rumale::PairwiseMetric.rbf_kernel(x, y, @params[:gamma])
118
+ when 'poly'
119
+ ::Rumale::PairwiseMetric.polynomial_kernel(x, y, @params[:degree], @params[:gamma], @params[:coef])
120
+ when 'sigmoid'
121
+ ::Rumale::PairwiseMetric.sigmoid_kernel(x, y, @params[:gamma], @params[:coef])
122
+ when 'linear'
123
+ ::Rumale::PairwiseMetric.linear_kernel(x, y)
124
+ else
125
+ raise ArgumentError, "Expect kernel parameter to be given 'rbf', 'linear', 'poly', or 'sigmoid'."
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/base/estimator'
4
+ require 'rumale/base/transformer'
5
+ require 'rumale/utils'
6
+ require 'rumale/validation'
7
+
8
+ module Rumale
9
+ module KernelApproximation
10
+ # Class for RBF kernel feature mapping.
11
+ #
12
+ # @example
13
+ # require 'rumale/kernel_approximation/rbf'
14
+ #
15
+ # transformer = Rumale::KernelApproximation::RBF.new(gamma: 1.0, n_components: 128, random_seed: 1)
16
+ # new_training_samples = transformer.fit_transform(training_samples)
17
+ # new_testing_samples = transformer.transform(testing_samples)
18
+ #
19
+ # *Refernce*:
20
+ # - Rahimi, A., and Recht, B., "Random Features for Large-Scale Kernel Machines," Proc. NIPS'07, pp.1177--1184, 2007.
21
+ class RBF < ::Rumale::Base::Estimator
22
+ include ::Rumale::Base::Transformer
23
+
24
+ # Return the random matrix for transformation.
25
+ # @return [Numo::DFloat] (shape: [n_features, n_components])
26
+ attr_reader :random_mat
27
+
28
+ # Return the random vector for transformation.
29
+ # @return [Numo::DFloat] (shape: [n_components])
30
+ attr_reader :random_vec
31
+
32
+ # Return the random generator for transformation.
33
+ # @return [Random]
34
+ attr_reader :rng
35
+
36
+ # Create a new transformer for mapping to RBF kernel feature space.
37
+ #
38
+ # @param gamma [Float] The parameter of RBF kernel: exp(-gamma * x^2).
39
+ # @param n_components [Integer] The number of dimensions of the RBF kernel feature space.
40
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
41
+ def initialize(gamma: 1.0, n_components: 128, random_seed: nil)
42
+ super()
43
+ @params = {
44
+ gamma: gamma,
45
+ n_components: n_components,
46
+ random_seed: (random_seed || srand)
47
+ }
48
+ @rng = Random.new(@params[:random_seed])
49
+ end
50
+
51
+ # Fit the model with given training data.
52
+ #
53
+ # @overload fit(x) -> RBF
54
+ # @param x [Numo::NArray] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
55
+ # This method uses only the number of features of the data.
56
+ # @return [RBF] The learned transformer itself.
57
+ def fit(x, _y = nil)
58
+ x = ::Rumale::Validation.check_convert_sample_array(x)
59
+
60
+ n_features = x.shape[1]
61
+ sub_rng = @rng.dup
62
+ @params[:n_components] = 2 * n_features if @params[:n_components] <= 0
63
+ @random_mat = ::Rumale::Utils.rand_normal([n_features, @params[:n_components]], sub_rng) * (2.0 * @params[:gamma])**0.5
64
+ n_half_components = @params[:n_components] / 2
65
+ @random_vec = Numo::DFloat.zeros(@params[:n_components] - n_half_components).concatenate(
66
+ Numo::DFloat.ones(n_half_components) * (0.5 * Math::PI)
67
+ )
68
+ self
69
+ end
70
+
71
+ # Fit the model with training data, and then transform them with the learned model.
72
+ #
73
+ # @overload fit_transform(x) -> Numo::DFloat
74
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
75
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data
76
+ def fit_transform(x, _y = nil)
77
+ x = ::Rumale::Validation.check_convert_sample_array(x)
78
+
79
+ fit(x).transform(x)
80
+ end
81
+
82
+ # Transform the given data with the learned model.
83
+ #
84
+ # @overload transform(x) -> Numo::DFloat
85
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The data to be transformed with the learned model.
86
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data.
87
+ def transform(x)
88
+ x = ::Rumale::Validation.check_convert_sample_array(x)
89
+
90
+ n_samples, = x.shape
91
+ projection = x.dot(@random_mat) + @random_vec.tile(n_samples, 1)
92
+ Numo::NMath.sin(projection) * ((2.0 / @params[:n_components])**0.5)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rumale is a machine learning library in Ruby.
4
+ module Rumale
5
+ # Module for kernel approximation algorithms.
6
+ module KernelApproximation
7
+ # @!visibility private
8
+ VERSION = '0.24.0'
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'numo/narray'
4
+
5
+ require_relative 'kernel_approximation/nystroem'
6
+ require_relative 'kernel_approximation/rbf'
7
+ require_relative 'kernel_approximation/version'
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rumale-kernel_approximation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.24.0
5
+ platform: ruby
6
+ authors:
7
+ - yoshoku
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-12-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: numo-narray
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rumale-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.24.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.24.0
41
+ description: |
42
+ Rumale::KernelApproximation provides kernel approximation algorithms,
43
+ such as RBF feature mapping and Nystroem method,
44
+ with Rumale interface.
45
+ email:
46
+ - yoshoku@outlook.com
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - LICENSE.txt
52
+ - README.md
53
+ - lib/rumale/kernel_approximation.rb
54
+ - lib/rumale/kernel_approximation/nystroem.rb
55
+ - lib/rumale/kernel_approximation/rbf.rb
56
+ - lib/rumale/kernel_approximation/version.rb
57
+ homepage: https://github.com/yoshoku/rumale
58
+ licenses:
59
+ - BSD-3-Clause
60
+ metadata:
61
+ homepage_uri: https://github.com/yoshoku/rumale
62
+ source_code_uri: https://github.com/yoshoku/rumale/tree/main/rumale-kernel_approximation
63
+ changelog_uri: https://github.com/yoshoku/rumale/blob/main/CHANGELOG.md
64
+ documentation_uri: https://yoshoku.github.io/rumale/doc/
65
+ rubygems_mfa_required: 'true'
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.3.26
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Rumale::KernelApproximation provides kernel approximation algorithms with
85
+ Rumale interface.
86
+ test_files: []