Exemplo n.º 1
0
// CovPCA performs principal component analysis on an m-by-m covariance matrix
// Σ. The principal components U and their variances Λ are returned in the
// descending order of the variances.
//
// By definition, the variances should be nonnegative. Due to finite-precision
// arithmetics, however, some close-to-zero variances might turn out to be
// negative. If the absolute value of a negative variance is smaller than the
// tolerance ε, the function nullifies that variance and proceeds without any
// errors; otherwise, an error is returned.
func CovPCA(Σ []float64, m uint, ε float64) (U []float64, Λ []float64, err error) {
	U = make([]float64, m*m)
	Λ = make([]float64, m)

	if err = decomposition.SymmetricEigen(Σ, U, Λ, m); err != nil {
		return nil, nil, err
	}

	for i := uint(0); i < m; i++ {
		if Λ[i] < 0.0 {
			if -Λ[i] < ε {
				Λ[i] = 0.0
			} else {
				return nil, nil, errors.New("the matrix should be positive semidefinite")
			}
		}
	}

	// Λ is in the ascending order. Reverse!
	for i, j := uint(0), m-1; i < j; i, j = i+1, j-1 {
		Λ[i], Λ[j] = Λ[j], Λ[i]
		for k := uint(0); k < m; k++ {
			U[i*m+k], U[j*m+k] = U[j*m+k], U[i*m+k]
		}
	}

	return
}
Exemplo n.º 2
0
func TestInverse(t *testing.T) {
	m := uint(3)

	A := []float64{
		1.0, 2.0, 3.0,
		2.0, 4.0, 5.0,
		3.0, 5.0, 6.0,
	}
	U := make([]float64, m*m)
	Λ := make([]float64, m)

	err := decomposition.SymmetricEigen(A, U, Λ, m)
	assert.Equal(err, nil, t)

	err = matrix.Invert(A, m)
	assert.Equal(err, nil, t)

	I, err := invert(U, Λ, m)
	assert.Equal(err, nil, t)
	assert.EqualWithin(A, I, 1e-14, t)
}