// Decompose computes an m-by-n matrix M for an m-by-m covariance matrix Σ such // that, for an n-element vector X with uncorrelated components, M * X is an // m-element vector whose components are correlated according to Σ. The // function reduces the number of dimensions from m to n such that a certain // portion of the variance is preserved, which is controlled by λ ∈ (0, 1]. func Decompose(Σ []float64, m uint, λ float64) ([]float64, uint, error) { U, Λ, err := decomposition.CovPCA(Σ, m, math.Sqrt(math.Nextafter(1, 2)-1)) if err != nil { return nil, 0, err } n := m // NOTE: Λ is in the descending order and nonnegative. var cum, sum float64 for i := uint(0); i < m; i++ { sum += Λ[i] } for i := uint(0); i < m; i++ { cum += Λ[i] if cum/sum >= λ { n = i + 1 break } } for i := uint(0); i < n; i++ { coef := math.Sqrt(Λ[i]) for j := uint(0); j < m; j++ { U[i*m+j] *= coef } } return U[:m*n], n, nil }
func TestCorrelateLarge(t *testing.T) { _, application, _ := system.Load("fixtures/016_160.tgff") ε := math.Sqrt(math.Nextafter(1.0, 2.0) - 1.0) R := Compute(application, index(160), 5) _, _, err := decomposition.CovPCA(R, 160, ε) assert.Success(err, t) }
func TestCorrelateSmall(t *testing.T) { _, application, _ := system.Load("fixtures/002_020.tgff") R := Compute(application, index(20), 2) _, _, err := decomposition.CovPCA(R, 20, 0) assert.Success(err, t) R = Compute(application, index(1), 2) assert.Equal(R, []float64{1.0}, t) }
// Decompose computes an m-by-n matrix C and an n-by-m matrix D given an m-by-m // covariance matrix Σ such that (a) for an n-element vector Z with uncorrelated // components, C * X is an m-element vector whose components are correlated // according to Σ, and (b) for an m-element vector X with correlated components // according to Σ, D * X is an n-element vector with uncorrelated components. // The function reduces the number of dimensions from m to n such that a certain // portion of the variance is preserved, which is controlled by λ ∈ (0, 1]. // // Internally the function relies on decomposition.CovPCA and returns its // outputs as well (the principal components and vectors of Σ). func Decompose(Σ []float64, m uint, λ, ε float64) (C []float64, D []float64, U []float64, Λ []float64, err error) { U, Λ, err = decomposition.CovPCA(Σ, m, ε) if err != nil { return nil, nil, nil, nil, err } n := m var cum, sum float64 for i := uint(0); i < m; i++ { sum += Λ[i] } for i := uint(0); i < m; i++ { cum += Λ[i] if cum/sum >= λ { n = i + 1 break } } C = make([]float64, m*n) D = make([]float64, n*m) for i := uint(0); i < n; i++ { σ := math.Sqrt(Λ[i]) for j := uint(0); j < m; j++ { ρ := U[i*m+j] C[i*m+j] = ρ * σ D[j*n+i] = ρ / σ } } return }