public void learn_whiten_success()
{
#region doc_learn_1
// Below is the same data used on the excellent paper "Tutorial
// On Principal Component Analysis", by Lindsay Smith (2002).
double[][] data =
{
new double[] { 2.5, 2.4 },
new double[] { 0.5, 0.7 },
new double[] { 2.2, 2.9 },
new double[] { 1.9, 2.2 },
new double[] { 3.1, 3.0 },
new double[] { 2.3, 2.7 },
new double[] { 2.0, 1.6 },
new double[] { 1.0, 1.1 },
new double[] { 1.5, 1.6 },
new double[] { 1.1, 0.9 }
};
// Let's create an analysis with centering (covariance method)
// but no standardization (correlation method) and whitening:
var pca = new PrincipalComponentAnalysis()
{
Method = PrincipalComponentMethod.Center,
Whiten = true
};
// Now we can learn the linear projection from the data
MultivariateLinearRegression transform = pca.Learn(data);
// Finally, we can project all the data
double[][] output1 = pca.Transform(data);
// Or just its first components by setting
// NumberOfOutputs to the desired components:
pca.NumberOfOutputs = 1;
// And then calling transform again:
double[][] output2 = pca.Transform(data);
// We can also limit to 80% of explained variance:
pca.ExplainedVariance = 0.8;
// And then call transform again:
double[][] output3 = pca.Transform(data);
#endregion
double[] eigenvalues = { 1.28402771, 0.0490833989 };
double[] proportion = eigenvalues.Divide(eigenvalues.Sum());
double[,] eigenvectors =
{
{ 0.19940687993951403, -1.1061252858739095 },
{ 0.21626410214440508, 1.0199057073792104 }
};
// Everything is alright (up to the 9 decimal places shown in the tutorial)
Assert.IsTrue(eigenvectors.IsEqual(pca.ComponentMatrix, rtol: 1e-9));
Assert.IsTrue(proportion.IsEqual(pca.ComponentProportions, rtol: 1e-9));
Assert.IsTrue(eigenvalues.IsEqual(pca.Eigenvalues, rtol: 1e-5));
pca.ExplainedVariance = 1.0;
double[][] actual = pca.Transform(data);
double[][] expected =
{
new double[] { 0.243560157209023, -0.263472650637184 },
new double[] { -0.522902576315494, 0.214938218565977 },
new double[] { 0.291870144299372, 0.578317788814594 },
new double[] { 0.0806632088164338, 0.19622137941132 },
new double[] { 0.492962746459375, -0.315204397734004 },
new double[] { 0.268558011864442, 0.263724118751361 },
new double[] { -0.0291545644762578, -0.526334573603598 },
new double[] { -0.336693495487974, 0.0698378585807067 },
new double[] { -0.128858004446015, 0.0267280693333571 },
new double[] { -0.360005627922904, -0.244755811482527 }
};
// var str = actual.ToString(CSharpJaggedMatrixFormatProvider.InvariantCulture);
// Everything is correct (up to 8 decimal places)
Assert.IsTrue(expected.IsEqual(actual, atol: 1e-8));
Assert.IsTrue(expected.IsEqual(output1, atol: 1e-8));
Assert.IsTrue(expected.Get(null, 0, 1).IsEqual(output2, atol: 1e-8));
Assert.IsTrue(expected.Get(null, 0, 1).IsEqual(output3, atol: 1e-8));
actual = transform.Transform(data);
Assert.IsTrue(expected.IsEqual(actual, atol: 1e-8));
}