Class: Rumale::Manifold::MDS
- Inherits:
- 
      Base::Estimator
      
        - Object
- Base::Estimator
- Rumale::Manifold::MDS
 
- Includes:
- Base::Transformer
- Defined in:
- rumale-manifold/lib/rumale/manifold/mds.rb
Overview
MDS is a class that implements Metric Multidimensional Scaling (MDS) with Scaling by MAjorizing a COmplicated Function (SMACOF) algorithm.
Reference
- 
Groenen, P J. F. and van de Velden, M., “Multidimensional Scaling by Majorization: A Review,” J. of Statistical Software, Vol. 73 (8), 2016. 
Instance Attribute Summary collapse
- 
  
    
      #embedding  ⇒ Numo::DFloat 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Return the data in representation space. 
- 
  
    
      #n_iter  ⇒ Integer 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Return the number of iterations run for optimization. 
- 
  
    
      #rng  ⇒ Random 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Return the random generator. 
- 
  
    
      #stress  ⇒ Float 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Return the stress function value after optimization. 
Attributes inherited from Base::Estimator
Instance Method Summary collapse
- 
  
    
      #fit(x)  ⇒ MDS 
    
    
  
  
  
  
  
  
  
  
  
    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', init: 'random', max_iter: 300, tol: nil, verbose: false, random_seed: nil)  ⇒ MDS 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    Create a new transformer with MDS. 
Constructor Details
#initialize(n_components: 2, metric: 'euclidean', init: 'random', max_iter: 300, tol: nil, verbose: false, random_seed: nil) ⇒ MDS
Create a new transformer with MDS.
| 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 56 def initialize(n_components: 2, metric: 'euclidean', init: 'random', max_iter: 300, tol: nil, verbose: false, random_seed: nil) super() @params = { n_components: n_components, max_iter: max_iter, tol: tol, metric: metric, init: init, verbose: verbose, random_seed: random_seed || srand } @rng = Random.new(@params[:random_seed]) end | 
Instance Attribute Details
#embedding ⇒ Numo::DFloat (readonly)
Return the data in representation space.
| 28 29 30 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 28 def @embedding end | 
#n_iter ⇒ Integer (readonly)
Return the number of iterations run for optimization
| 36 37 38 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 36 def n_iter @n_iter end | 
#rng ⇒ Random (readonly)
Return the random generator.
| 40 41 42 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 40 def rng @rng end | 
#stress ⇒ Float (readonly)
Return the stress function value after optimization.
| 32 33 34 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 32 def stress @stress end | 
Instance Method Details
#fit(x) ⇒ MDS
Fit the model with given training data.
| 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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/mds.rb', line 77 def fit(x, _not_used = nil) 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 # initialize some varibales. n_samples = x.shape[0] hi_distance_mat = @params[:metric] == 'precomputed' ? x : ::Rumale::PairwiseMetric.euclidean_distance(x) @embedding = (x) lo_distance_mat = ::Rumale::PairwiseMetric.euclidean_distance(@embedding) @stress = calc_stress(hi_distance_mat, lo_distance_mat) @n_iter = 0 # perform optimization. @params[:max_iter].times do |t| # guttman tarnsform. ratio = hi_distance_mat / lo_distance_mat ratio[ratio.diag_indices] = 0.0 ratio[lo_distance_mat.eq(0)] = 0.0 tmp_mat = -ratio tmp_mat[tmp_mat.diag_indices] += ratio.sum(axis: 1) @embedding = 1.fdiv(n_samples) * tmp_mat.dot(@embedding) lo_distance_mat = ::Rumale::PairwiseMetric.euclidean_distance(@embedding) # check convergence. new_stress = calc_stress(hi_distance_mat, lo_distance_mat) if terminate?(@stress, new_stress) @stress = new_stress break end # next step. @n_iter = t + 1 @stress = new_stress puts "[MDS] stress function after #{@n_iter} iterations: #{@stress}" if @params[:verbose] && (@n_iter % 100).zero? end self end | 
#fit_transform(x) ⇒ Numo::DFloat
Fit the model with training data, and then transform them with the learned model.
| 120 121 122 123 124 125 | # File 'rumale-manifold/lib/rumale/manifold/mds.rb', line 120 def fit_transform(x, _not_used = nil) x = ::Rumale::Validation.check_convert_sample_array(x) fit(x) @embedding.dup end |