Class: Rumale::Decomposition::PCA

Inherits:
Object
  • Object
show all
Includes:
Base::BaseEstimator, Base::Transformer
Defined in:
lib/rumale/decomposition/pca.rb

Overview

PCA is a class that implements Principal Component Analysis.

Reference

    1. Sharma and K K. Paliwal, “Fast principal component analysis using fixed-point algorithm,” Pattern Recognition Letters, 28, pp. 1151–1155, 2007.

Examples:

decomposer = Rumale::Decomposition::PCA.new(n_components: 2)
representaion = decomposer.fit_transform(samples)

Instance Attribute Summary collapse

Attributes included from Base::BaseEstimator

#params

Instance Method Summary collapse

Constructor Details

#initialize(n_components: 2, max_iter: 100, tol: 1.0e-4, random_seed: nil) ⇒ PCA

Create a new transformer with PCA.

Parameters:

  • n_components (Integer) (defaults to: 2)

    The number of principal components.

  • max_iter (Integer) (defaults to: 100)

    The maximum number of iterations.

  • tol (Float) (defaults to: 1.0e-4)

    The tolerance of termination criterion.

  • random_seed (Integer) (defaults to: nil)

    The seed value using to initialize the random generator.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rumale/decomposition/pca.rb', line 39

def initialize(n_components: 2, max_iter: 100, tol: 1.0e-4, random_seed: nil)
  check_params_integer(n_components: n_components, max_iter: max_iter)
  check_params_float(tol: tol)
  check_params_type_or_nil(Integer, random_seed: random_seed)
  check_params_positive(n_components: n_components, max_iter: max_iter, tol: tol)
  @params = {}
  @params[:n_components] = n_components
  @params[:max_iter] = max_iter
  @params[:tol] = tol
  @params[:random_seed] = random_seed
  @params[:random_seed] ||= srand
  @components = nil
  @mean = nil
  @rng = Random.new(@params[:random_seed])
end

Instance Attribute Details

#componentsNumo::DFloat (readonly)

Returns the principal components.

Returns:

  • (Numo::DFloat)

    (shape: [n_components, n_features])



23
24
25
# File 'lib/rumale/decomposition/pca.rb', line 23

def components
  @components
end

#meanNumo::DFloat (readonly)

Returns the mean vector.

Returns:

  • (Numo::DFloat)

    (shape: [n_features]



27
28
29
# File 'lib/rumale/decomposition/pca.rb', line 27

def mean
  @mean
end

#rngRandom (readonly)

Return the random generator.

Returns:

  • (Random)


31
32
33
# File 'lib/rumale/decomposition/pca.rb', line 31

def rng
  @rng
end

Instance Method Details

#fit(x) ⇒ PCA

Fit the model with given training data.

Parameters:

  • x (Numo::DFloat)

    (shape: [n_samples, n_features]) The training data to be used for fitting the model.

Returns:

  • (PCA)

    The learned transformer itself.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/rumale/decomposition/pca.rb', line 61

def fit(x, _y = nil)
  check_sample_array(x)
  # initialize some variables.
  @components = nil
  n_samples, n_features = x.shape
  sub_rng = @rng.dup
  # centering.
  @mean = x.mean(0)
  centered_x = x - @mean
  # optimization.
  covariance_mat = centered_x.transpose.dot(centered_x) / (n_samples - 1)
  @params[:n_components].times do
    comp_vec = Rumale::Utils.rand_uniform(n_features, sub_rng)
    @params[:max_iter].times do
      updated = orthogonalize(covariance_mat.dot(comp_vec))
      break if (updated.dot(comp_vec) - 1).abs < @params[:tol]
      comp_vec = updated
    end
    @components = @components.nil? ? comp_vec : Numo::NArray.vstack([@components, comp_vec])
  end
  self
end

#fit_transform(x) ⇒ Numo::DFloat

Fit the model with training data, and then transform them with the learned model.

Parameters:

  • x (Numo::DFloat)

    (shape: [n_samples, n_features]) The training data to be used for fitting the model.

Returns:

  • (Numo::DFloat)

    (shape: [n_samples, n_components]) The transformed data



90
91
92
93
# File 'lib/rumale/decomposition/pca.rb', line 90

def fit_transform(x, _y = nil)
  check_sample_array(x)
  fit(x).transform(x)
end

#inverse_transform(z) ⇒ Numo::DFloat

Inverse transform the given transformed data with the learned model.

Parameters:

  • z (Numo::DFloat)

    (shape: [n_samples, n_components]) The data to be restored into original space with the learned model.

Returns:

  • (Numo::DFloat)

    (shape: [n_samples, n_featuress]) The restored data.



108
109
110
111
112
# File 'lib/rumale/decomposition/pca.rb', line 108

def inverse_transform(z)
  check_sample_array(z)
  c = @components.shape[1].nil? ? @components.expand_dims(0) : @components
  z.dot(c) + @mean
end

#marshal_dumpHash

Dump marshal data.

Returns:

  • (Hash)

    The marshal data.



116
117
118
119
120
121
# File 'lib/rumale/decomposition/pca.rb', line 116

def marshal_dump
  { params: @params,
    components: @components,
    mean: @mean,
    rng: @rng }
end

#marshal_load(obj) ⇒ nil

Load marshal data.

Returns:

  • (nil)


125
126
127
128
129
130
131
# File 'lib/rumale/decomposition/pca.rb', line 125

def marshal_load(obj)
  @params = obj[:params]
  @components = obj[:components]
  @mean = obj[:mean]
  @rng = obj[:rng]
  nil
end

#transform(x) ⇒ Numo::DFloat

Transform the given data with the learned model.

Parameters:

  • x (Numo::DFloat)

    (shape: [n_samples, n_features]) The data to be transformed with the learned model.

Returns:

  • (Numo::DFloat)

    (shape: [n_samples, n_components]) The transformed data.



99
100
101
102
# File 'lib/rumale/decomposition/pca.rb', line 99

def transform(x)
  check_sample_array(x)
  (x - @mean).dot(@components.transpose)
end