Exemplo n.º 1
0
        /// <summary>
        /// Perform CCA analysis on columns of two number tables.
        /// </summary>
        /// <param name="tableX">A number table.</param>
        /// <param name="tableY">A number table.</param>
        /// <returns>A PlsResult structure.</returns>
        /// <remarks>This method finds directions for tableX and tableY; so that these two tables will
        /// have maximal correlation in those directions.</remarks>
        public PlsResult DoCCA(INumberTable tableX, INumberTable tableY)
        {
            double[][] X   = (double[][])tableX.Matrix;
            double[][] Y   = (double[][])tableY.Matrix;
            double[][] Cxy = Covariance(X, Y);
            double[][] Cyx = Covariance(Y, X);

            IMathAdaptor math = MultivariateAnalysisPlugin.App.GetMathAdaptor();

            double[][] rCxx = math.InvertMatrix(Covariance(X, X));
            double[][] rCyy = math.InvertMatrix(Covariance(Y, Y));

            MakeSymmetric(rCxx);
            MakeSymmetric(rCyy);

            double[][] A  = MatrixProduct(rCxx, Cxy);
            double[][] B  = MatrixProduct(rCyy, Cyx);
            double[][] Cx = MatrixProduct(A, B);
            double[][] Cy = MatrixProduct(B, A);

            double[][] Wx, Wy;
            double[]   Rx, Ry;

            math.EigenDecomposition(Cx, out Wx, out Rx);
            math.EigenDecomposition(Cy, out Wy, out Ry);

            //
            // Rx and Ry should be the equal upto permutation and dimension.
            // Wy can be calculated from Wx by Ry = sqrt(1/Rx) * B * Rx
            //

            /*
             * double x0 = Math.Sqrt(Rx[0]);
             * double x1 = Math.Sqrt(Rx[1]);
             * double x2 = Math.Sqrt(Rx[2]);
             *
             * double y0 = Math.Sqrt(Ry[0]);
             * double y1 = Math.Sqrt(Ry[1]);
             * double y2 = Math.Sqrt(Ry[2]);
             *
             * 0.7165   0.4906   0.2668
             */

            SortEigenVectors(Wx, Rx);
            SortEigenVectors(Wy, Ry);

            //ValidateMatrix(Wx);
            //ValidateMatrix(Wy);

            PlsResult ret = new PlsResult();

            ret.ProjectionX   = EigenProjection(tableX, Wx);
            ret.ProjectionY   = EigenProjection(tableY, Wy);
            ret.EigenVectorsX = Wx;
            ret.EigenVectorsY = Wy;
            ret.EigenValuesX  = Rx;
            ret.EigenValuesY  = Ry;

            return(ret);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Perform PLS analysis on columns of two number tables.
        /// </summary>
        /// <param name="tableX">A number table.</param>
        /// <param name="tableY">A number table.</param>
        /// <returns>A PlsResult structure.</returns>
        /// <remarks>This method finds directions for tableX and tableY; so that these two tables will
        /// have maximal covariance in those directions.</remarks>
        public PlsResult DoPLS(INumberTable tableX, INumberTable tableY)
        {
            double[][] Cxy    = Covariance((double[][])tableX.Matrix, (double[][])tableY.Matrix);
            double[][] Cyx    = Covariance((double[][])tableY.Matrix, (double[][])tableX.Matrix);
            double[][] CxyCyx = MatrixProduct(Cxy, Cyx);
            double[][] CyxCxy = MatrixProduct(Cyx, Cxy);

            IMathAdaptor math = MultivariateAnalysisPlugin.App.GetMathAdaptor();

            double[][] Wx, Wy;
            double[]   Rx, Ry;

            // These two matrix might be slightly asymmetric due to calculation errors.
            MakeSymmetric(CxyCyx);
            MakeSymmetric(CyxCxy);

            math.EigenDecomposition(CxyCyx, out Wx, out Rx);
            math.EigenDecomposition(CyxCxy, out Wy, out Ry);

            SortEigenVectors(Wx, Rx);
            SortEigenVectors(Wy, Ry);

            PlsResult ret = new PlsResult();

            ret.ProjectionX   = EigenProjection(tableX, Wx);
            ret.ProjectionY   = EigenProjection(tableY, Wy);
            ret.EigenVectorsX = Wx;
            ret.EigenVectorsY = Wy;
            ret.EigenValuesX  = Rx;
            ret.EigenValuesY  = Ry;
            return(ret);
        }
Exemplo n.º 3
0
        public void Initialize(IDataset dataset, XmlElement filterNode)
        {
            INumberTable numTable = dataset.GetNumberTable();
            int          N        = numTable.Rows;

            double[][] L      = Matrix(N, N);
            int        offset = numTable.Columns - N;

            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    if (i != j)
                    {
                        L[i][j] = -numTable.Matrix[i][offset + j];
                    }
                    else
                    {
                        L[i][j] = 0;
                    }
                }
            }
            for (int i = 0; i < N; i++)
            {
                double rowSum = 0;
                for (int j = 0; j < N; j++)
                {
                    rowSum += L[i][j];
                }
                L[i][i] = -rowSum;
            }

            IMathAdaptor math = GraphMetrics.App.GetMathAdaptor();

            double[][] H = math.InvertMatrix(L);

            d = Matrix(N, N);
            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    d[i][j] = H[i][i] + H[j][j] - H[i][j] - H[j][i];
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Performs the Linear Discreminate Analysis (LDA) on a given number table.
        /// </summary>
        /// <param name="table">A numerical data table.</param>
        /// <returns>A LdaResult structure</returns>
        /// <remarks>This method find a set of directions, so that the projection of the row vector of the input data
        /// table to those directions will maximally separate rows with different types.</remarks>
        public LdaResult DoLDA(INumberTable table)
        {
            int rows    = table.Rows;
            int columns = table.Columns;

            double[][] m = (double[][])table.Matrix;

            int classNumber = 0;  // the number of classes
            Dictionary <int, int> type2ClassIndex = new Dictionary <int, int>();

            int[] row2ClassIndex = new int[rows];
            for (int row = 0; row < rows; row++)
            {
                int type = table.RowSpecList[row].Type;
                if (!type2ClassIndex.ContainsKey(type))
                {
                    type2ClassIndex[type] = classNumber++;
                }
                row2ClassIndex[row] = type2ClassIndex[type];
            }

            // Calculate the class mean vectors.
            double[][] classMean = NewMatrix(classNumber, columns);
            for (int cIdx = 0; cIdx < classNumber; cIdx++)
            {
                Array.Clear(classMean[cIdx], 0, columns);
            }
            double[] totalMean = new double[columns];
            Array.Clear(totalMean, 0, columns);
            int[] classSize = new int[classNumber];
            Array.Clear(classSize, 0, classSize.Length);

            for (int row = 0; row < rows; row++)
            {
                int cIdx = row2ClassIndex[row];
                classSize[cIdx]++;
                for (int col = 0; col < columns; col++)
                {
                    double v = m[row][col];
                    totalMean[col]       += v;
                    classMean[cIdx][col] += v;
                }
            }

            for (int col = 0; col < columns; col++)
            {
                for (int cIdx = 0; cIdx < classNumber; cIdx++)
                {
                    classMean[cIdx][col] /= classSize[cIdx];
                }
                totalMean[col] /= rows;
            }

            // Zero mean the matrix m and the classMean vectors.
            double[][] z = NewMatrix(rows, columns);
            for (int row = 0; row < rows; row++)
            {
                int cIdx = row2ClassIndex[row];
                for (int col = 0; col < columns; col++)
                {
                    z[row][col] = m[row][col] - classMean[cIdx][col];
                }
            }
            for (int cIdx = 0; cIdx < classNumber; cIdx++)
            {
                for (int col = 0; col < columns; col++)
                {
                    classMean[cIdx][col] -= totalMean[col];
                }
            }

            // Calculate the within- and between- covariance matrix.
            double[][] Sw = NewMatrix(columns, columns);
            double[][] Sb = NewMatrix(columns, columns);
            double[][] S  = NewMatrix(columns, columns);

            for (int i = 0; i < columns; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    double v = 0.0;
                    for (int row = 0; row < rows; row++)
                    {
                        v += z[row][i] * z[row][j];
                    }
                    Sw[i][j] = v;

                    v = 0.0;
                    for (int cIdx = 0; cIdx < classNumber; cIdx++)
                    {
                        v += classMean[cIdx][i] * classMean[cIdx][j];
                    }
                    Sb[i][j] = v;
                }
            }

            // Calculate the inverse of Sw, and then Sb/Sw into S.
            IMathAdaptor math = MultivariateAnalysisPlugin.App.GetMathAdaptor();

            Sw = math.InvertMatrix(Sw);
            if (Sw == null)
            {
                S = Sb;
            }
            else
            {
                for (int i = 0; i < columns; i++)
                {
                    for (int j = 0; j < columns; j++)
                    {
                        double v = 0.0;
                        for (int k = 0; k < columns; k++)
                        {
                            v += Sw[i][k] * Sb[k][j];
                        }
                        S[i][j] = v;
                    }
                }
            }

            //
            // REVISIT: Make the matrix S symmetric. This matrix should be symmetrical
            // by itself, but is normally not completely symmetric due to caculation errors (particularily,
            // the matrix Sw Inverted is mostly not symmetrically.) Notice: the method math.EigenDecomposition()
            // follows completely different algorithm when the matrix is not symmetric
            //
            MakeSymmetric(S);

            double[][] eigenVectors;
            double[]   eigenValues;
            if (!math.EigenDecomposition(S, out eigenVectors, out eigenValues))
            {
                MultivariateAnalysisPlugin.App.ScriptApp.LastError = "Failed to calculate the eigenvectors.";
                return(null);
            }

            /*
             * MultivariateAnalysisPlugin.App.ScriptApp.New.NumberTable(S).ShowAsTable();
             * INumberTable eT = MultivariateAnalysisPlugin.App.ScriptApp.New.NumberTable(eigenVectors);
             * eT.AddRows(1);
             * for (int i = 0; i < eigenValues.Length; i++) eT.Matrix[eT.Rows - 1][i] = eigenValues[i];
             * eT.RowSpecList[eT.Rows - 1].Id = "EV";
             * eT.ShowAsTable();
             */

            SortEigenVectors(eigenVectors, eigenValues);

            // project the original data m to the eigenvectors.
            LdaResult ret = new LdaResult();

            ret.EigenVectors = MultivariateAnalysisPlugin.App.ScriptApp.New.NumberTable(eigenVectors);
            int columnNumber = Math.Min(ret.EigenVectors.Columns, table.Columns);

            for (int col = 0; col < columnNumber; col++)
            {
                ret.EigenVectors.ColumnSpecList[col].CopyFrom(table.ColumnSpecList[col]);
            }
            ret.EigenValues = eigenValues;
            ret.Projection  = EigenProjection(table, eigenVectors);
            return(ret);
        }