Exemple #1
0
        public static PCAData GetPCAData(Matrix LoadMatrix,  object Tag = null)
        {
            ColumnVector AverageVector = LoadMatrix.GetAverageRow();
            Matrix AverageMatrix = Matrix.GetSameElementMatrix(AverageVector, LoadMatrix.ColSize);
            Matrix DiffMatrix = LoadMatrix - AverageMatrix;
            SymmetricMatrix LMatrix = new SymmetricMatrix(DiffMatrix.GetTranspose() * DiffMatrix);
            EigenSystem EigenSystemData = LMatrix.GetEigenVectorAndValue(0.00001);
            Matrix LEigenVector = EigenSystemData.GetEigenVectors();
            Matrix FinalEigenVector = (LoadMatrix * LEigenVector).GetNormalizedMatrixCol();
            EigenSystem FinalEigenSystem = new EigenSystem();
            for (int i = 0; i < EigenSystemData.Count; i++)
            {
                if (EigenSystemData[i].EigenValue > 0.0001)
                    FinalEigenSystem.Add(new EigenVectorAndValue(FinalEigenVector.GetColVector(i), EigenSystemData[i].EigenValue));
            }
            Matrix CoefficientMatrix = FinalEigenSystem.GetEigenVectors().GetTranspose() * DiffMatrix;

            return new PCAData( FinalEigenSystem, CoefficientMatrix, AverageVector, Tag);
        }
        /// <summary>
        /// 固有値と固有ベクトルを取得します。
        /// </summary>
        /// <param name="EPS">許容相対誤差</param>
        /// <returns>固有値と固有ベクトル</returns>
        public override EigenSystem GetEigenVectorAndValue(double EPS)
        {
            //現在の行列を設定(後に固有ベクトルが入る)
            double[][] EigenValueMatrix = this.MatrixElements;
            //単位行列を設定(後に固有値が入る)
            double[][] EigenVectorMatrix = SquareMatrix.IdentityMatrix(this.Dimension).MatrixElements;

            double Max = double.MaxValue;

            do
            {
                #region 固有値、固有ベクトルの繰り返し計算
                //α、β、γ
                double Alpha, Beta, Gamma;

                double Sin, Cos, Work;

                //一時的にpp,pq,qqを格納
                double Temp_A, Temp_B, Temp_C;

                int MaxRow ;
                int MaxCol ;

                //現在の行列の中で最大のものを取得。
                //MaxRowとMaxColの中に最大値、Maxに最大値が入る
                Max = this.GetMaxValue(EigenValueMatrix, out MaxRow, out MaxCol);

                //ピボットを決めて回転
                Temp_A = EigenValueMatrix[MaxRow][MaxRow];
                Temp_B = EigenValueMatrix[MaxRow][MaxCol];
                Temp_C = EigenValueMatrix[MaxCol][MaxCol];

                Alpha = -Temp_B;
                Beta = (Temp_A - Temp_C) / 2;
                Gamma = Math.Abs(Beta) / Math.Sqrt(Alpha * Alpha + Beta * Beta);

                Sin = Math.Sqrt((1.0 - Gamma) / 2);
                if (Alpha * Beta < 0) Sin = -Sin;
                Cos = Math.Sqrt(1.0 - Sin * Sin);

                for (int j = 0; j < EigenValueMatrix.Length; j++)
                {
                    Work = EigenValueMatrix[MaxRow][j] * Cos - EigenValueMatrix[MaxCol][j] * Sin;
                    EigenValueMatrix[MaxCol][j] = EigenValueMatrix[MaxRow][j] * Sin + EigenValueMatrix[MaxCol][j] * Cos;
                    EigenValueMatrix[MaxRow][j] = Work;
                }

                for (int j = 0; j < EigenValueMatrix.Length; j++)
                {
                    EigenValueMatrix[j][MaxRow] = EigenValueMatrix[MaxRow][j];
                    EigenValueMatrix[j][MaxCol] = EigenValueMatrix[MaxCol][j];
                }

                Work = 2.0 * Temp_B * Sin * Cos;
                EigenValueMatrix[MaxRow][MaxRow] = Temp_A * Cos * Cos + Temp_C * Sin * Sin - Work;
                EigenValueMatrix[MaxCol][MaxCol] = Temp_A * Sin * Sin + Temp_C * Cos * Cos + Work;
                EigenValueMatrix[MaxRow][MaxCol] = EigenValueMatrix[MaxCol][MaxRow] = 0;

                // 固有ベクトルの導出
                for (int i = 0; i < EigenValueMatrix.Length; i++)
                {
                    Work = EigenVectorMatrix[i][MaxRow] * Cos - EigenVectorMatrix[i][MaxCol] * Sin;
                    EigenVectorMatrix[i][MaxCol] = EigenVectorMatrix[i][MaxRow] * Sin + EigenVectorMatrix[i][MaxCol] * Cos;
                    EigenVectorMatrix[i][MaxRow] = Work;
                }
                #endregion
            } while (EPS < Max);
            //許容相対誤差以下になるまで繰り返して、抜けたら計算終了

            //固有ベクトル、固有値をセットする処理
            EigenSystem EigenData = new EigenSystem();
            Matrix ResultVectorMatrix = new Matrix(EigenVectorMatrix);
            for (int i = 0; i < this.Dimension; i++)
            {
                //固有ベクトルをセット
                Vector EigenVector = ResultVectorMatrix.GetRowVector(i);
                //固有値をセット
                double EigenValue = EigenValueMatrix[i][i];

                if (EigenValue > EPS)
                {
                    //保持するクラスにセット後、固有ベクトルの大きさを正規化
                    EigenData.Add(new EigenVectorAndValue(EigenVector, EigenValue));
                    EigenData[i].Normlize();
                }
                else
                {
                    //固有値が小さすぎたら固有値0、固有ベクトル0にしておく。
                    EigenData.Add(new EigenVectorAndValue(new Vector(EigenVector.Length), 0d));
                }
            }

            return EigenData;
        }