Class: Rumale::Manifold::LocalTangentSpaceAlignment
- Inherits:
-
Base::Estimator
- Object
- Base::Estimator
- Rumale::Manifold::LocalTangentSpaceAlignment
- Includes:
- Base::Transformer
- Defined in:
- lib/rumale/manifold/local_tangent_space_alignment.rb
Overview
LocalTangentSpaceAlignment is a class that implements Local Tangent Space Alignment.
Reference
-
Zhang, A., and Zha, H., “Principal Manifolds and Nonlinear Diemnsion Reduction via Local Tangent Space Alignment,” SIAM Journal on Scientific Computing, vol. 26, iss. 1, pp. 313-338, 2004.
Instance Attribute Summary collapse
-
#embedding ⇒ Numo::DFloat
readonly
Return the data in representation space.
Instance Method Summary collapse
-
#fit(x) ⇒ LocalTangentSpaceAlignment
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) ⇒ LocalTangentSpaceAlignment
constructor
Create a new transformer with Local Tangent Space Alignment.
-
#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) ⇒ LocalTangentSpaceAlignment
Create a new transformer with Local Tangent Space Alignment.
33 34 35 36 37 38 39 40 |
# File 'lib/rumale/manifold/local_tangent_space_alignment.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 'lib/rumale/manifold/local_tangent_space_alignment.rb', line 26 def @embedding end |
Instance Method Details
#fit(x) ⇒ LocalTangentSpaceAlignment
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 75 76 77 78 79 |
# File 'lib/rumale/manifold/local_tangent_space_alignment.rb', line 47 def fit(x, _y = nil) unless enable_linalg?(warning: false) raise 'LocalTangentSpaceAlignment#fit requires Numo::Linalg but that is not loaded' end x = Rumale::Validation.check_convert_sample_array(x) n_samples = x.shape[0] distance_mat = Rumale::PairwiseMetric.squared_error(x) neighbor_ids = neighbor_ids(distance_mat, @params[:n_neighbors], true) affinity_mat = Numo::DFloat.zeros(n_samples, n_samples) x_tangent = Numo::DFloat.zeros(@params[:n_neighbors], @params[:n_components] + 1) x_tangent[true, 0] = 1.fdiv(Math.sqrt(@params[:n_neighbors])) n_samples.times do |n| x_local = x[neighbor_ids[n, true], true] x_tangent[true, 1...] = right_singular_vectors(x_local, @params[:n_components]) weight_mat = x_tangent.dot(x_tangent.transpose) neighbor_ids[n, true].each_with_index do |m, i| affinity_mat[m, neighbor_ids[n, true]] -= weight_mat[i, true] affinity_mat[m, m] += 1 end end kernel_mat = 0.5 * (affinity_mat.transpose + 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.
86 87 88 89 90 91 92 |
# File 'lib/rumale/manifold/local_tangent_space_alignment.rb', line 86 def fit_transform(x, _y = nil) unless enable_linalg?(warning: false) raise 'LocalTangentSpaceAlignment#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. For out-of-sample data embedding, the same method as Locally Linear Embedding is used.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/rumale/manifold/local_tangent_space_alignment.rb', line 99 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 |