Merge branch 'jeffin143-fix-1840'

This commit is contained in:
Ryan Curtin
2020-02-07 22:48:08 -05:00
10 changed files with 36 additions and 71 deletions
+4 -1
View File
@@ -24,9 +24,12 @@
* CMake fix for finding STB include directory (#2145).
* Add normalization support for CF binding (#2136).
* Add Mish activation function (#2158).
* Better error handling of eigendecompositions and Cholesky decompositions
(#2088, #1840).
### mlpack 3.2.2
###### 2019-11-26
* Add `valid` and `same` padding option in `Convolution` and `Atrous
@@ -39,8 +39,11 @@ void GaussianDistribution::Covariance(arma::mat&& covariance)
void GaussianDistribution::FactorCovariance()
{
// On Armadillo < 4.500, the "lower" option isn't available.
covLower = arma::chol(covariance, "lower");
if (!arma::chol(covLower, covariance, "lower"))
{
Log::Fatal << "Cholesky decomposition failed." << std::endl;
}
// Comment from rcurtin:
//
// I think the use of the word "interpret" in the Armadillo documentation
-26
View File
@@ -73,32 +73,6 @@ void mlpack::math::WhitenUsingSVD(const arma::mat& x,
xWhitened = whiteningMatrix * x;
}
/**
* Whitens a matrix using the eigendecomposition of the covariance matrix.
* Whitening means the covariance matrix of the result is the identity matrix.
*/
void mlpack::math::WhitenUsingEig(const arma::mat& x,
arma::mat& xWhitened,
arma::mat& whiteningMatrix)
{
arma::mat diag, eigenvectors;
arma::vec eigenvalues;
// Get eigenvectors of covariance of input matrix.
eig_sym(eigenvalues, eigenvectors, mlpack::math::ColumnCovariance(x));
// Generate diagonal matrix using 1 / sqrt(eigenvalues) for each value.
VectorPower(eigenvalues, -0.5);
diag.zeros(eigenvalues.n_elem, eigenvalues.n_elem);
diag.diag() = eigenvalues;
// Our whitening matrix is diag(1 / sqrt(eigenvectors)) * eigenvalues.
whiteningMatrix = diag * trans(eigenvectors);
// Now apply the whitening matrix.
xWhitened = whiteningMatrix * x;
}
/**
* Overwrites a dimension-N vector to a random vector on the unit sphere in R^N.
*/
-7
View File
@@ -45,13 +45,6 @@ void WhitenUsingSVD(const arma::mat& x,
arma::mat& xWhitened,
arma::mat& whiteningMatrix);
/**
* Whitens a matrix using the eigendecomposition of the covariance matrix.
* Whitening means the covariance matrix of the result is the identity matrix.
*/
void WhitenUsingEig(const arma::mat& x,
arma::mat& xWhitened,
arma::mat& whiteningMatrix);
/**
* Overwrites a dimension-N vector to a random vector on the unit sphere in R^N.
@@ -64,7 +64,12 @@ class EigenvalueRatioConstraint
// Eigendecompose the matrix.
arma::vec eigenvalues;
arma::mat eigenvectors;
arma::eig_sym(eigenvalues, eigenvectors, covariance);
covariance = arma::symmatu(covariance);
if (!arma::eig_sym(eigenvalues, eigenvectors, covariance))
{
Log::Fatal << "applying to constraint could not be accomplished."
<< std::endl;
}
// Change the eigenvalues to what we are forcing them to be. There
// shouldn't be any negative eigenvalues anyway, so it doesn't matter if we
+6 -1
View File
@@ -117,7 +117,12 @@ arma::vec GMM::Random() const
}
}
return trans(chol(dists[gaussian].Covariance())) *
arma::mat cholDecomp;
if (!arma::chol(cholDecomp, dists[gaussian].Covariance()))
{
Log::Fatal << "Cholesky decomposition failed." << std::endl;
}
return trans(cholDecomp) *
arma::randn<arma::vec>(dimensionality) + dists[gaussian].Mean();
}
@@ -41,7 +41,12 @@ class PositiveDefiniteConstraint
// eigenvalues are at least 1e-50).
arma::vec eigval;
arma::mat eigvec;
arma::eig_sym(eigval, eigvec, covariance);
covariance = arma::symmatu(covariance);
if (!arma::eig_sym(eigval, eigvec, covariance))
{
Log::Fatal << "applying to constraint could not be accomplished."
<< std::endl;
}
// If the matrix is not positive definite or if the condition number is
// large, we must project it back onto the cone of positive definite
@@ -73,7 +73,11 @@ class NaiveKernelRule
kernelMatrix += arma::sum(rowMean) / kernelMatrix.n_cols;
// Eigendecompose the centered kernel matrix.
arma::eig_sym(eigval, eigvec, kernelMatrix);
kernelMatrix = arma::symmatu(kernelMatrix);
if (!arma::eig_sym(eigval, eigvec, kernelMatrix))
{
Log::Fatal << "Failed to construct the kernel matrix." << std::endl;
}
// Swap the eigenvalues since they are ordered backwards (we need largest to
// smallest).
@@ -64,7 +64,11 @@ class NystroemKernelRule
G += arma::sum(colMean) / G.n_rows;
// Eigendecompose the centered kernel matrix.
arma::eig_sym(eigval, eigvec, transformedData);
transformedData = arma::symmatu(transformedData);
if (!arma::eig_sym(eigval, eigvec, transformedData))
{
Log::Fatal << "Failed to construct the kernel matrix." << std::endl;
}
// Swap the eigenvalues since they are ordered backwards (we need largest
// to smallest).
-31
View File
@@ -78,37 +78,6 @@ BOOST_AUTO_TEST_CASE(TestCenterB)
BOOST_REQUIRE_CLOSE(tmp_out(row, col), (double) (col - 2.5) * row, 1e-5);
}
BOOST_AUTO_TEST_CASE(TestWhitenUsingEig)
{
// After whitening using eigendecomposition, the covariance of
// our matrix will be I (or something very close to that).
// We are loading a matrix from an external file... bad choice.
mat tmp, tmp_centered, whitened, whitening_matrix;
data::Load("trainSet.csv", tmp);
Center(tmp, tmp_centered);
WhitenUsingEig(tmp_centered, whitened, whitening_matrix);
mat newcov = mlpack::math::ColumnCovariance(whitened);
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 5; col++)
{
if (row == col)
{
// diagonal will be 0 in the case of any zero-valued eigenvalues
// (rank-deficient covariance case)
if (std::abs(newcov(row, col)) > 1e-10)
BOOST_REQUIRE_CLOSE(newcov(row, col), 1.0, 1e-10);
}
else
{
BOOST_REQUIRE_SMALL(newcov(row, col), 1e-10);
}
}
}
}
BOOST_AUTO_TEST_CASE(TestOrthogonalize)
{
// Generate a random matrix; then, orthogonalize it and test if it's