rumale 0.13.5 → 0.13.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9c82fecc8a90ec9d4379249b749e9257b2738c3
4
- data.tar.gz: 1b4ca375174ee9d1c16a35d50e68ee9b5bd471c5
3
+ metadata.gz: e78d2a2eeb35fc8409dac683e2f8a3b90e5c396d
4
+ data.tar.gz: 8ae3c1396efeac327288a5fe534661ea65d0d766
5
5
  SHA512:
6
- metadata.gz: 3d9bc3c21b951f5738cbf8a2e947d94d6fd735ebbcdc41fdb450d8c4f4f28a9788100c595b1b29bbe81e7124f0ca2b5703c4d6107730fab6f9ab6fe67db4fa1d
7
- data.tar.gz: 2f93f78169dd8f694ca65634f3e4619ad83df72a59d0e2eacd8c686b2fdc82011f53b6b49e7c18e1c9a9d86904c77709d9743689e39e8db697f469a77a336fe7
6
+ metadata.gz: f25dee4375b9d9707374341b7cebe19973ea66f8e8b42af92806aa50b2b41323fcd0ba1470b9a87266859e1c30eea8a1a583ffa620519998df6da91bca8e1b23
7
+ data.tar.gz: 2e9a3cd0d87aae35e180e74c8335a93b1126f57fd9d4f5c727e60decf5b81982b96f0bdcd2e99c4104169341a1dc4db9a6d631c1fe5cf8eb709ccc5ae9f377e2
@@ -1,4 +1,6 @@
1
- require: rubocop-performance
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rspec
2
4
 
3
5
  AllCops:
4
6
  TargetRubyVersion: 2.3
@@ -10,7 +12,7 @@ AllCops:
10
12
  - 'Rakefile'
11
13
  - 'Gemfile'
12
14
 
13
- Documentation:
15
+ Style/Documentation:
14
16
  Enabled: false
15
17
 
16
18
  Metrics/LineLength:
@@ -40,7 +42,7 @@ Metrics/BlockLength:
40
42
  Exclude:
41
43
  - 'spec/**/*'
42
44
 
43
- ParameterLists:
45
+ Metrics/ParameterLists:
44
46
  Max: 10
45
47
 
46
48
  Security/MarshalLoad:
@@ -49,6 +51,9 @@ Security/MarshalLoad:
49
51
  Naming/UncommunicativeMethodParamName:
50
52
  Enabled: false
51
53
 
54
+ Naming/ConstantName:
55
+ Enabled: false
56
+
52
57
  Style/FormatStringToken:
53
58
  Enabled: false
54
59
 
@@ -57,3 +62,15 @@ Style/NumericLiterals:
57
62
 
58
63
  Layout/EmptyLineAfterGuardClause:
59
64
  Enabled: false
65
+
66
+ RSpec/MultipleExpectations:
67
+ Enabled: false
68
+
69
+ RSpec/ExampleLength:
70
+ Max: 40
71
+
72
+ RSpec/InstanceVariable:
73
+ Enabled: false
74
+
75
+ RSpec/LeakyConstantDeclaration:
76
+ Enabled: false
@@ -1,3 +1,7 @@
1
+ # 0.13.6
2
+ - Add transformer class for [FastICA](https://yoshoku.github.io/rumale/doc/Rumale/Decomposition/FastICA.html).
3
+ - Fix a typo on README ([#13](https://github.com/yoshoku/rumale/pull/13)).
4
+
1
5
  # 0.13.5
2
6
  - Add transformer class for [Factor Analysis](https://yoshoku.github.io/rumale/doc/Rumale/Decomposition/FactorAnalysis.html).
3
7
  - Add covariance_type parameter to [Rumale::Clustering::GaussianMixture](https://yoshoku.github.io/rumale/doc/Rumale/Clustering/GaussianMixture.html).
data/README.md CHANGED
@@ -13,7 +13,7 @@ Rumale provides machine learning algorithms with interfaces similar to Scikit-Le
13
13
  Rumale supports Linear / Kernel Support Vector Machine,
14
14
  Logistic Regression, Linear Regression, Ridge, Lasso, Kernel Ridge, Factorization Machine,
15
15
  Naive Bayes, Decision Tree, AdaBoost, Gradient Tree Boosting, Random Forest, Extra-Trees, K-nearest neighbor classifier,
16
- K-Means, K-Medoids, Gaussian Mixture Model, DBSCAN, HDSCAN, SNN, Spectral Clustering, Power Iteration Clustering,
16
+ K-Means, K-Medoids, Gaussian Mixture Model, DBSCAN, HDBSCAN, SNN, Spectral Clustering, Power Iteration Clustering,
17
17
  Mutidimensional Scaling, t-SNE, Principal Component Analysis, Kernel PCA and Non-negative Matrix Factorization.
18
18
 
19
19
  This project was formerly known as "SVMKit".
@@ -70,6 +70,7 @@ require 'rumale/clustering/single_linkage'
70
70
  require 'rumale/decomposition/pca'
71
71
  require 'rumale/decomposition/nmf'
72
72
  require 'rumale/decomposition/factor_analysis'
73
+ require 'rumale/decomposition/fast_ica'
73
74
  require 'rumale/manifold/tsne'
74
75
  require 'rumale/manifold/mds'
75
76
  require 'rumale/preprocessing/l2_normalizer'
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rumale/base/base_estimator'
4
+ require 'rumale/base/transformer'
5
+
6
+ module Rumale
7
+ module Decomposition
8
+ # FastICA is a class that implments Fast Independent Component Analaysis.
9
+ #
10
+ # @example
11
+ # require 'numo/linalg/autoloader'
12
+ #
13
+ # transformer = Rumale::Decomposition::FastICA.new(n_components: 2, random_seed: 1)
14
+ # source_data = transformer.fit_transform(observed_data)
15
+ #
16
+ # *Reference*
17
+ # - A. Hyvarinen "Fast and Robust Fixed-Point Algorithms for Independent Component Analysis," IEEE Trans. Neural Networks, Vol. 10 (3), pp. 626--634, 1999.
18
+ # - A. Hyvarinen and E. Oja, "Independent Component Analysis: Algorithms and Applications," Neural Networks, Vol. 13 (4-5), pp. 411--430, 2000.
19
+ class FastICA
20
+ include Base::BaseEstimator
21
+ include Base::Transformer
22
+
23
+ # Returns the unmixing matrix.
24
+ # @return [Numo::DFloat] (shape: [n_components, n_features])
25
+ attr_reader :components
26
+
27
+ # Returns the mixing matrix.
28
+ # @return [Numo::DFloat] (shape: [n_features, n_components])
29
+ attr_reader :mixing
30
+
31
+ # Returns the number of iterations when converged.
32
+ # @return [Integer]
33
+ attr_reader :n_iter
34
+
35
+ # Return the random generator.
36
+ # @return [Random]
37
+ attr_reader :rng
38
+
39
+ # Create a new transformer with FastICA.
40
+ #
41
+ # @param n_components [Integer] The number of independent components.
42
+ # @param whiten [Boolean] The flag indicating whether to perform whitening.
43
+ # @param fun [String] The type of contrast function ('logcosh', 'exp', or 'cube').
44
+ # @param alpha [Float] The parameter of contrast function for 'logcosh' and 'exp'.
45
+ # If fun = 'cube', this parameter is ignored.
46
+ # @param max_iter [Integer] The maximum number of iterations.
47
+ # @param tol [Float] The tolerance of termination criterion.
48
+ # @param random_seed [Integer] The seed value using to initialize the random generator.
49
+ def initialize(n_components: 2, whiten: true, fun: 'logcosh', alpha: 1.0, max_iter: 200, tol: 1e-4, random_seed: nil)
50
+ check_params_integer(n_components: n_components, max_iter: max_iter)
51
+ check_params_boolean(whiten: whiten)
52
+ check_params_string(fun: fun)
53
+ check_params_float(alpha: alpha, tol: tol)
54
+ check_params_type_or_nil(Integer, random_seed: random_seed)
55
+ check_params_positive(n_components: n_components, max_iter: max_iter, tol: tol)
56
+ @params = {}
57
+ @params[:n_components] = n_components
58
+ @params[:whiten] = whiten
59
+ @params[:fun] = fun
60
+ @params[:alpha] = alpha
61
+ @params[:max_iter] = max_iter
62
+ @params[:tol] = tol
63
+ @params[:random_seed] = random_seed
64
+ @params[:random_seed] ||= srand
65
+ @components = nil
66
+ @mixing = nil
67
+ @n_iter = nil
68
+ @mean = nil
69
+ @rng = Random.new(@params[:random_seed])
70
+ end
71
+
72
+ # Fit the model with given training data.
73
+ #
74
+ # @overload fit(x) -> FastICA
75
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
76
+ # @return [FastICA] The learned transformer itself.
77
+ def fit(x, _y = nil)
78
+ check_sample_array(x)
79
+ raise 'FastICA#fit requires Numo::Linalg but that is not loaded.' unless enable_linalg?
80
+
81
+ @mean, whiten_mat = whitening(x, @params[:n_components]) if @params[:whiten]
82
+ wx = @params[:whiten] ? (x - @mean).dot(whiten_mat.transpose) : x
83
+ unmixing, @n_iter = ica(wx, @params[:fun], @params[:max_iter], @params[:tol], @rng.dup)
84
+ @components = @params[:whiten] ? unmixing.dot(whiten_mat) : unmixing
85
+ @mixing = Numo::Linalg.pinv(@components)
86
+ if @params[:n_components] == 1
87
+ @components = @components.flatten.dup
88
+ @mixing = @mixing.flatten.dup
89
+ end
90
+ self
91
+ end
92
+
93
+ # Fit the model with training data, and then transform them with the learned model.
94
+ #
95
+ # @overload fit_transform(x) -> Numo::DFloat
96
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The training data to be used for fitting the model.
97
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data
98
+ def fit_transform(x, _y = nil)
99
+ check_sample_array(x)
100
+ raise 'FastICA#fit_transform requires Numo::Linalg but that is not loaded.' unless enable_linalg?
101
+
102
+ fit(x).transform(x)
103
+ end
104
+
105
+ # Transform the given data with the learned model.
106
+ #
107
+ # @param x [Numo::DFloat] (shape: [n_samples, n_features]) The data to be transformed with the learned model.
108
+ # @return [Numo::DFloat] (shape: [n_samples, n_components]) The transformed data.
109
+ def transform(x)
110
+ check_sample_array(x)
111
+ cx = @params[:whiten] ? (x - @mean) : x
112
+ cx.dot(@components.transpose)
113
+ end
114
+
115
+ # Inverse transform the given transformed data with the learned model.
116
+ #
117
+ # @param z [Numo::DFloat] (shape: [n_samples, n_components]) The source data reconstructed to the mixed data.
118
+ # @return [Numo::DFloat] (shape: [n_samples, n_featuress]) The mixed data.
119
+ def inverse_transform(z)
120
+ check_sample_array(z)
121
+ m = @mixing.shape[1].nil? ? @mixing.expand_dims(0).transpose : @mixing
122
+ x = z.dot(m.transpose)
123
+ x += @mean if @params[:whiten]
124
+ x
125
+ end
126
+
127
+ # Dump marshal data.
128
+ # @return [Hash] The marshal data.
129
+ def marshal_dump
130
+ { params: @params,
131
+ components: @components,
132
+ mixing: @mixing,
133
+ n_iter: @n_iter,
134
+ mean: @mean,
135
+ rng: @rng }
136
+ end
137
+
138
+ # Load marshal data.
139
+ # @return [nil]
140
+ def marshal_load(obj)
141
+ @params = obj[:params]
142
+ @components = obj[:components]
143
+ @mixing = obj[:mixing]
144
+ @n_iter = obj[:n_iter]
145
+ @mean = obj[:mean]
146
+ @rng = obj[:rng]
147
+ nil
148
+ end
149
+
150
+ private
151
+
152
+ def whitening(x, n_components)
153
+ n_samples, n_features = x.shape
154
+ mean_vec = x.mean(0)
155
+ centered_x = x - mean_vec
156
+ covar_mat = centered_x.transpose.dot(centered_x) / n_samples
157
+ eig_vals, eig_vecs = Numo::Linalg.eigh(covar_mat, vals_range: (n_features - n_components)...n_features)
158
+ [mean_vec, (eig_vecs.reverse(1).dup * (1 / Numo::NMath.sqrt(eig_vals.reverse.dup))).transpose.dup]
159
+ end
160
+
161
+ def ica(x, fun, max_iter, tol, sub_rng)
162
+ n_samples, n_components = x.shape
163
+ w = decorrelation(Rumale::Utils.rand_normal([n_components, n_components], sub_rng))
164
+ n_iters = 0
165
+ max_iter.times do |t|
166
+ n_iters = t + 1
167
+ gx, ggx = gradient(x.dot(w.transpose), fun)
168
+ new_w = decorrelation(gx.transpose.dot(x) / n_samples - w * ggx / n_samples)
169
+ err = (new_w - w).abs.max
170
+ w = new_w
171
+ break if err <= tol
172
+ end
173
+ [w, n_iters]
174
+ end
175
+
176
+ def decorrelation(w)
177
+ eig_vals, eig_vecs = Numo::Linalg.eigh(w.dot(w.transpose))
178
+ decorr_mat = (eig_vecs * (1 / Numo::NMath.sqrt(eig_vals))).dot(eig_vecs.transpose)
179
+ decorr_mat.dot(w)
180
+ end
181
+
182
+ def gradient(x, func)
183
+ case func
184
+ when 'exp'
185
+ grad_exp(x, @params[:alpha])
186
+ when 'cube'
187
+ grad_cube(x)
188
+ else
189
+ grad_logcosh(x, @params[:alpha])
190
+ end
191
+ end
192
+
193
+ def grad_logcosh(x, alpha)
194
+ gx = Numo::NMath.tanh(alpha * x)
195
+ ggx = (alpha * (1 - gx**2)).sum(0)
196
+ [gx, ggx]
197
+ end
198
+
199
+ def grad_exp(x, alpha)
200
+ squared_x = x**2
201
+ exp_x = Numo::NMath.exp(-0.5 * alpha * squared_x)
202
+ gx = exp_x * x
203
+ ggx = (exp_x * (1 - alpha * squared_x)).sum(0)
204
+ [gx, ggx]
205
+ end
206
+
207
+ def grad_cube(x)
208
+ [x**3, (3 * x**2).sum(0)]
209
+ end
210
+ end
211
+ end
212
+ end
@@ -106,7 +106,9 @@ module Rumale
106
106
  y = (b.dot(one_vec) * y + (a - b).dot(y)) / a.dot(one_vec)
107
107
  lo_prob_mat = t_distributed_probability_matrix(y)
108
108
  @n_iter = t + 1
109
- puts "[t-SNE] KL divergence after #{@n_iter} iterations: #{cost(hi_prob_mat, lo_prob_mat)}" if @params[:verbose] && (@n_iter % 100).zero?
109
+ if @params[:verbose] && (@n_iter % 100).zero?
110
+ puts "[t-SNE] KL divergence after #{@n_iter} iterations: #{cost(hi_prob_mat, lo_prob_mat)}"
111
+ end
110
112
  end
111
113
  # store results.
112
114
  @embedding = y
@@ -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.13.5'
6
+ VERSION = '0.13.6'
7
7
  end
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.13.5
4
+ version: 0.13.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-03 00:00:00.000000000 Z
11
+ date: 2019-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -172,6 +172,7 @@ files:
172
172
  - lib/rumale/clustering/spectral_clustering.rb
173
173
  - lib/rumale/dataset.rb
174
174
  - lib/rumale/decomposition/factor_analysis.rb
175
+ - lib/rumale/decomposition/fast_ica.rb
175
176
  - lib/rumale/decomposition/nmf.rb
176
177
  - lib/rumale/decomposition/pca.rb
177
178
  - lib/rumale/ensemble/ada_boost_classifier.rb