示例#1
0
        public void Test()
        {
            // Make a random list.
            RandomHelper.Random = new Random(77);
            List <VectorF> points = new List <VectorF>();

            for (int i = 0; i < 10; i++)
            {
                var vector = new VectorF(4);
                RandomHelper.Random.NextVectorF(vector, -1, 10);
                points.Add(vector);
            }

            PrincipalComponentAnalysisF pca = new PrincipalComponentAnalysisF(points);

            Assert.Greater(pca.Variances[0], pca.Variances[1]);
            Assert.Greater(pca.Variances[1], pca.Variances[2]);
            Assert.Greater(pca.Variances[2], pca.Variances[3]);
            Assert.Greater(pca.Variances[3], 0);

            Assert.IsTrue(pca.V.GetColumn(0).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(1).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(2).IsNumericallyNormalized);
            Assert.IsTrue(pca.V.GetColumn(3).IsNumericallyNormalized);

            // Compute covariance matrix and check if it is diagonal in the transformed space.
            MatrixF cov            = StatisticsHelper.ComputeCovarianceMatrix(points);
            MatrixF transformedCov = pca.V.Transposed * cov * pca.V;

            for (int row = 0; row < transformedCov.NumberOfRows; row++)
            {
                for (int column = 0; column < transformedCov.NumberOfColumns; column++)
                {
                    if (row != column)
                    {
                        Assert.IsTrue(Numeric.IsZero(transformedCov[row, column]));
                    }
                }
            }

            // The principal components must be Eigenvectors which means that multiplying with the covariance
            // matrix does only change the length!
            VectorF v0       = pca.V.GetColumn(0);
            VectorF v0Result = cov * v0;

            Assert.IsTrue(VectorF.AreNumericallyEqual(v0.Normalized, v0Result.Normalized));
            VectorF v1       = pca.V.GetColumn(1);
            VectorF v1Result = cov * v1;

            Assert.IsTrue(VectorF.AreNumericallyEqual(v1.Normalized, v1Result.Normalized));
            VectorF v2       = pca.V.GetColumn(2);
            VectorF v2Result = cov * v2;

            Assert.IsTrue(VectorF.AreNumericallyEqual(v2.Normalized, v2Result.Normalized));
            VectorF v3       = pca.V.GetColumn(3);
            VectorF v3Result = cov * v3;

            Assert.IsTrue(VectorF.AreNumericallyEqual(v3.Normalized, v3Result.Normalized));
        }
        public void Test()
        {
            // Make a random list.
              RandomHelper.Random = new Random(77);
              List<VectorF> points = new List<VectorF>();
              for (int i = 0; i < 10; i++)
              {
            var vector = new VectorF(4);
            RandomHelper.Random.NextVectorF(vector, -1, 10);
            points.Add(vector);
              }

              PrincipalComponentAnalysisF pca = new PrincipalComponentAnalysisF(points);

              Assert.Greater(pca.Variances[0], pca.Variances[1]);
              Assert.Greater(pca.Variances[1], pca.Variances[2]);
              Assert.Greater(pca.Variances[2], pca.Variances[3]);
              Assert.Greater(pca.Variances[3], 0);

              Assert.IsTrue(pca.V.GetColumn(0).IsNumericallyNormalized);
              Assert.IsTrue(pca.V.GetColumn(1).IsNumericallyNormalized);
              Assert.IsTrue(pca.V.GetColumn(2).IsNumericallyNormalized);
              Assert.IsTrue(pca.V.GetColumn(3).IsNumericallyNormalized);

              // Compute covariance matrix and check if it is diagonal in the transformed space.
              MatrixF cov = StatisticsHelper.ComputeCovarianceMatrix(points);
              MatrixF transformedCov = pca.V.Transposed * cov * pca.V;

              for (int row = 0; row < transformedCov.NumberOfRows; row++)
            for (int column = 0; column < transformedCov.NumberOfColumns; column++)
              if (row != column)
            Assert.IsTrue(Numeric.IsZero(transformedCov[row, column]));

              // The principal components must be Eigenvectors which means that multiplying with the covariance
              // matrix does only change the length!
              VectorF v0 = pca.V.GetColumn(0);
              VectorF v0Result = cov * v0;
              Assert.IsTrue(VectorF.AreNumericallyEqual(v0.Normalized, v0Result.Normalized));
              VectorF v1 = pca.V.GetColumn(1);
              VectorF v1Result = cov * v1;
              Assert.IsTrue(VectorF.AreNumericallyEqual(v1.Normalized, v1Result.Normalized));
              VectorF v2 = pca.V.GetColumn(2);
              VectorF v2Result = cov * v2;
              Assert.IsTrue(VectorF.AreNumericallyEqual(v2.Normalized, v2Result.Normalized));
              VectorF v3 = pca.V.GetColumn(3);
              VectorF v3Result = cov * v3;
              Assert.IsTrue(VectorF.AreNumericallyEqual(v3.Normalized, v3Result.Normalized));
        }
示例#3
0
        private void DoPca()
        {
            // Create random 2-dimensional vectors.
            var points = new List <VectorF>();

            for (int i = 0; i < 20; i++)
            {
                var x            = RandomHelper.Random.NextFloat(-200, 200);
                var y            = RandomHelper.Random.NextFloat(-100, 100);
                var randomVector = new VectorF(new float[] { x, y });
                points.Add(randomVector);
            }

            // Draw a small cross for each point.
            var debugRenderer = GraphicsScreen.DebugRenderer2D;

            debugRenderer.Clear();
            var center = new Vector3(640, 360, 0);

            foreach (var point in points)
            {
                var x = point[0];
                var y = point[1];
                debugRenderer.DrawLine(
                    center + new Vector3(x - 10, y - 10, 0),
                    center + new Vector3(x + 10, y + 10, 0),
                    Color.Black,
                    true);
                debugRenderer.DrawLine(
                    center + new Vector3(x + 10, y - 10, 0),
                    center + new Vector3(x - 10, y + 10, 0),
                    Color.Black,
                    true);
            }

            // Compute the average of the points.
            var average = new Vector2F();

            foreach (var point in points)
            {
                average += (Vector2F)point;
            }

            average /= points.Count;

            // Compute the PCA of the point set.
            var pca = new PrincipalComponentAnalysisF(points);

            // Get the principal components.
            // pca.V is a matrix where each column represents a principal component.
            // The first column represents the first principal component, which can be loosely
            // interpreted as the "direction of the widest spread".
            Vector2F pc0 = (Vector2F)pca.V.GetColumn(0);
            // The second column represents the second principal component, which is a vector
            // orthogonal to the first.
            Vector2F pc1 = (Vector2F)pca.V.GetColumn(1);

            // pca.Variances contains the variances of the data points along the principal components.
            // The square root of the variance is the standard deviation.
            float standardDeviation0 = (float)Math.Sqrt(pca.Variances[0]);
            float standardDeviation1 = (float)Math.Sqrt(pca.Variances[1]);

            // Draw a line in the direction of the first principal component through the average point.
            // The line length is proportional to the standard deviation with an arbitrary scaling.
            debugRenderer.DrawLine(
                center + new Vector3(average.X, average.Y, 0) - 3 * standardDeviation0 * new Vector3(pc0.X, pc0.Y, 0),
                center + new Vector3(average.X, average.Y, 0) + 3 * standardDeviation0 * new Vector3(pc0.X, pc0.Y, 0),
                Color.Black,
                true);

            // Draw a line in the direction of the second principal component through the average point.
            debugRenderer.DrawLine(
                center + new Vector3(average.X, average.Y, 0) - 3 * standardDeviation1 * new Vector3(pc1.X, pc1.Y, 0),
                center + new Vector3(average.X, average.Y, 0) + 3 * standardDeviation1 * new Vector3(pc1.X, pc1.Y, 0),
                Color.Black,
                true);
        }