Class: Rumale::Manifold::ClassicalMDS
- Inherits:
-
Base::Estimator
- Object
- Base::Estimator
- Rumale::Manifold::ClassicalMDS
- Includes:
- Base::Transformer
- Defined in:
- rumale-manifold/lib/rumale/manifold/classical_mds.rb
Overview
ClassicalMDS is a class that implements classical multi-dimensional scaling.
Instance Attribute Summary collapse
-
#embedding ⇒ Numo::DFloat
readonly
Return the data in representation space.
Attributes inherited from Base::Estimator
Instance Method Summary collapse
-
#fit(x) ⇒ ClassicalMDS
Fit the model with given training data.
-
#fit_transform(x) ⇒ Numo::DFloat
Fit the model with training data, and then transform them with the learned model.
-
#initialize(n_components: 2, metric: 'euclidean') ⇒ ClassicalMDS
constructor
Create a new transformer with Classical MDS.
Constructor Details
#initialize(n_components: 2, metric: 'euclidean') ⇒ ClassicalMDS
Create a new transformer with Classical MDS.
32 33 34 35 36 37 38 |
# File 'rumale-manifold/lib/rumale/manifold/classical_mds.rb', line 32 def initialize(n_components: 2, metric: 'euclidean') super() @params = { n_components: n_components, metric: metric } end |
Instance Attribute Details
#embedding ⇒ Numo::DFloat (readonly)
Return the data in representation space.
24 25 26 |
# File 'rumale-manifold/lib/rumale/manifold/classical_mds.rb', line 24 def @embedding end |
Instance Method Details
#fit(x) ⇒ ClassicalMDS
Fit the model with given training data.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'rumale-manifold/lib/rumale/manifold/classical_mds.rb', line 46 def fit(x, _not_used = nil) raise 'ClassicalMDS#fit requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) x = ::Rumale::Validation.check_convert_sample_array(x) if @params[:metric] == 'precomputed' && x.shape[0] != x.shape[1] raise ArgumentError, 'Expect the input distance matrix to be square.' end n_samples = x.shape[0] distance_mat = @params[:metric] == 'precomputed' ? x : ::Rumale::PairwiseMetric.euclidean_distance(x) centering_mat = Numo::DFloat.eye(n_samples) - Numo::DFloat.new(n_samples, n_samples).fill(1.fdiv(n_samples)) kernel_mat = -0.5 * centering_mat.dot(distance_mat * distance_mat).dot(centering_mat) eig_vals, eig_vecs = Numo::Linalg.eigh(kernel_mat, vals_range: (n_samples - @params[:n_components])...n_samples) eig_vals = eig_vals.reverse eig_vecs = eig_vecs.reverse(1) @embedding = eig_vecs.dot(Numo::NMath.sqrt(eig_vals.abs).diag) @embedding = @embedding.flatten.dup if @params[:n_components] == 1 self end |
#fit_transform(x) ⇒ Numo::DFloat
Fit the model with training data, and then transform them with the learned model.
75 76 77 78 79 80 81 |
# File 'rumale-manifold/lib/rumale/manifold/classical_mds.rb', line 75 def fit_transform(x, _not_used = nil) raise 'ClassicalMDS#fit_transform requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) x = ::Rumale::Validation.check_convert_sample_array(x) fit(x) @embedding.dup end |