Class: Rumale::Manifold::LocallyLinearEmbedding
- Inherits:
-
Base::Estimator
- Object
- Base::Estimator
- Rumale::Manifold::LocallyLinearEmbedding
- Includes:
- Base::Transformer
- Defined in:
- rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb
Overview
LocallyLinearEmbedding is a class that implements Locally Linear Embedding.
Reference
-
Roweis, S., and Saul, L., “Nonlinear Dimensionality Reduction by Locally Linear Embedding,” J. of Science, vol. 290, pp. 2323-2326, 2000.
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) ⇒ LocallyLinearEmbedding
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, n_neighbors: 10, reg_param: 1e-3) ⇒ LocallyLinearEmbedding
constructor
Create a new transformer with Locally Linear Embedding.
-
#transform(x) ⇒ Numo::DFloat
Transform the given data with the learned model.
Constructor Details
#initialize(n_components: 2, n_neighbors: 10, reg_param: 1e-3) ⇒ LocallyLinearEmbedding
Create a new transformer with Locally Linear Embedding.
33 34 35 36 37 38 39 40 |
# File 'rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb', line 33 def initialize(n_components: 2, n_neighbors: 10, reg_param: 1e-3) super() @params = { n_components: n_components, n_neighbors: [1, n_neighbors].max, reg_param: reg_param } end |
Instance Attribute Details
#embedding ⇒ Numo::DFloat (readonly)
Return the data in representation space.
26 27 28 |
# File 'rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb', line 26 def @embedding end |
Instance Method Details
#fit(x) ⇒ LocallyLinearEmbedding
Fit the model with given training data.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb', line 47 def fit(x, _y = nil) raise 'LocallyLinearEmbedding#fit requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) x = Rumale::Validation.check_convert_sample_array(x) n_samples = x.shape[0] tol = @params[:reg_param].fdiv(@params[:n_neighbors]) distance_mat = Rumale::PairwiseMetric.squared_error(x) neighbor_ids = neighbor_ids(distance_mat, @params[:n_neighbors], true) affinity_mat = Numo::DFloat.eye(n_samples) n_samples.times do |n| x_local = x[neighbor_ids[n, true], true] - x[n, true] gram_mat = x_local.dot(x_local.transpose) gram_mat += tol * gram_mat.trace * Numo::DFloat.eye(@params[:n_neighbors]) weights = Numo::Linalg.solve(gram_mat, Numo::DFloat.ones(@params[:n_neighbors])) weights /= weights.sum + 1e-8 affinity_mat[n, neighbor_ids[n, true]] -= weights end kernel_mat = affinity_mat.transpose.dot(affinity_mat) _, eig_vecs = Numo::Linalg.eigh(kernel_mat, vals_range: 1...(1 + @params[:n_components])) @embedding = @params[:n_components] == 1 ? eig_vecs[true, 0].dup : eig_vecs.dup @x_train = x.dup self end |
#fit_transform(x) ⇒ Numo::DFloat
Fit the model with training data, and then transform them with the learned model.
81 82 83 84 85 86 87 |
# File 'rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb', line 81 def fit_transform(x, _y = nil) unless enable_linalg?(warning: false) raise 'LocallyLinearEmbedding#fit_transform requires Numo::Linalg but that is not loaded' end fit(x).transform(x) end |
#transform(x) ⇒ Numo::DFloat
Transform the given data with the learned model.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'rumale-manifold/lib/rumale/manifold/locally_linear_embedding.rb', line 93 def transform(x) x = Rumale::Validation.check_convert_sample_array(x) n_samples = x.shape[0] tol = @params[:reg_param].fdiv(@params[:n_neighbors]) distance_mat = Rumale::PairwiseMetric.squared_error(x, @x_train) neighbor_ids = neighbor_ids(distance_mat, @params[:n_neighbors], false) weight_mat = Numo::DFloat.zeros(n_samples, @x_train.shape[0]) n_samples.times do |n| x_local = @x_train[neighbor_ids[n, true], true] - x[n, true] gram_mat = x_local.dot(x_local.transpose) gram_mat += tol * weight_mat.trace * Numo::DFloat.eye(@params[:n_neighbors]) weights = Numo::Linalg.solve(gram_mat, Numo::DFloat.ones(@params[:n_neighbors])) weights /= weights.sum + 1e-8 weight_mat[n, neighbor_ids[n, true]] = weights end weight_mat.dot(@embedding) end |