Class: Rumale::Decomposition::FactorAnalysis
- Inherits:
- 
      Base::Estimator
      
        - Object
- Base::Estimator
- Rumale::Decomposition::FactorAnalysis
 
- Includes:
- Base::Transformer
- Defined in:
- rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb
Overview
FactorAnalysis is a class that implements fator analysis with EM algorithm.
Reference
- 
Barber, D., “Bayesian Reasoning and Machine Learning,” Cambridge University Press, 2012. 
Instance Attribute Summary collapse
- 
  
    
      #components  ⇒ Numo::DFloat 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the components with maximum variance. 
- 
  
    
      #loglike  ⇒ Numo::DFloat 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the log likelihood at each iteration. 
- 
  
    
      #mean  ⇒ Numo::DFloat 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the mean vector. 
- 
  
    
      #n_iter  ⇒ Integer 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Return the number of iterations run for optimization. 
- 
  
    
      #noise_variance  ⇒ Numo::DFloat 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the estimated noise variance for each feature. 
Attributes inherited from Base::Estimator
Instance Method Summary collapse
- 
  
    
      #fit(x)  ⇒ FactorAnalysis 
    
    
  
  
  
  
  
  
  
  
  
    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, max_iter: 100, tol: 1e-8)  ⇒ FactorAnalysis 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    Create a new transformer with factor analysis. 
- 
  
    
      #transform(x)  ⇒ Numo::DFloat 
    
    
  
  
  
  
  
  
  
  
  
    Transform the given data with the learned model. 
Constructor Details
#initialize(n_components: 2, max_iter: 100, tol: 1e-8) ⇒ FactorAnalysis
Create a new transformer with factor analysis.
| 49 50 51 52 53 54 55 56 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 49 def initialize(n_components: 2, max_iter: 100, tol: 1e-8) super() @params = { n_components: n_components, max_iter: max_iter, tol: tol } end | 
Instance Attribute Details
#components ⇒ Numo::DFloat (readonly)
Returns the components with maximum variance.
| 33 34 35 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 33 def components @components end | 
#loglike ⇒ Numo::DFloat (readonly)
Returns the log likelihood at each iteration.
| 37 38 39 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 37 def loglike @loglike end | 
#mean ⇒ Numo::DFloat (readonly)
Returns the mean vector.
| 25 26 27 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 25 def mean @mean end | 
#n_iter ⇒ Integer (readonly)
Return the number of iterations run for optimization
| 41 42 43 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 41 def n_iter @n_iter end | 
#noise_variance ⇒ Numo::DFloat (readonly)
Returns the estimated noise variance for each feature.
| 29 30 31 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 29 def noise_variance @noise_variance end | 
Instance Method Details
#fit(x) ⇒ FactorAnalysis
Fit the model with given training data.
| 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 63 def fit(x, _y = nil) x = ::Rumale::Validation.check_convert_sample_array(x) raise 'FactorAnalysis#fit requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) # initialize some variables. n_samples, n_features = x.shape @mean = x.mean(0) centered_x = x - @mean cov_mat = centered_x.transpose.dot(centered_x) / n_samples sample_vars = x.var(0) sqrt_n_samples = Math.sqrt(n_samples) @noise_variance = Numo::DFloat.ones(n_features) # run optimization. old_loglike = 0.0 @n_iter = 0 @loglike = [] unless @params[:tol].nil? @params[:max_iter].times do |t| @n_iter = t + 1 sqrt_noise_variance = Numo::NMath.sqrt(@noise_variance) scaled_x = centered_x / (sqrt_noise_variance * sqrt_n_samples + 1e-12) s, u = truncate_svd(scaled_x, @params[:n_components]) scaler = Numo::NMath.sqrt(Numo::DFloat.maximum(s**2 - 1.0, 0.0)) @components = (sqrt_noise_variance.diag.dot(u) * scaler).transpose.dup @noise_variance = Numo::DFloat.maximum(sample_vars - @components.transpose.dot(@components).diagonal, 1e-12) next if @params[:tol].nil? new_loglike = log_likelihood(cov_mat, @components, @noise_variance) @loglike.push(new_loglike) break if (old_loglike - new_loglike).abs <= @params[:tol] old_loglike = new_loglike end @loglike = Numo::DFloat.cast(@loglike) unless @params[:tol].nil? @components = @components[0, true].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.
| 107 108 109 110 111 112 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 107 def fit_transform(x, _y = nil) x = ::Rumale::Validation.check_convert_sample_array(x) raise 'FactorAnalysis#fit_transform requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) fit(x).transform(x) end | 
#transform(x) ⇒ Numo::DFloat
Transform the given data with the learned model.
| 118 119 120 121 122 123 124 125 126 127 | # File 'rumale-decomposition/lib/rumale/decomposition/factor_analysis.rb', line 118 def transform(x) x = ::Rumale::Validation.check_convert_sample_array(x) raise 'FactorAnalysis#transform requires Numo::Linalg but that is not loaded' unless enable_linalg?(warning: false) factors = @params[:n_components] == 1 ? @components.(0) : @components centered_x = x - @mean beta = Numo::Linalg.inv(Numo::DFloat.eye(factors.shape[0]) + (factors / @noise_variance).dot(factors.transpose)) z = centered_x.dot((beta.dot(factors) / @noise_variance).transpose) @params[:n_components] == 1 ? z[true, 0].dup : z end |