コード例 #1
1
		/// <summary>
		/// Execution of the fast nonnegative least squares algorithm. The algorithm finds a vector x with all elements xi&gt;=0 which minimizes |X*x-y|.
		/// </summary>
		/// <param name="XtX">X transposed multiplied by X, thus a square matrix.</param>
		/// <param name="Xty">X transposed multiplied by Y, thus a matrix with one column and same number of rows as X.</param>
		/// <param name="tolerance">Used to decide if a solution element is less than or equal to zero. If this is null, a default tolerance of tolerance = MAX(SIZE(XtX)) * NORM(XtX,1) * EPS is used.</param>
		/// <param name="x">Output: solution vector (matrix with one column and number of rows according to dimension of X.</param>
		/// <param name="w">Output: Lagrange vector. Elements which take place in the fit are set to 0. Elements fixed to zero contain a negative number.</param>
		/// <remarks>
		/// <para>
		/// Literature: Rasmus Bro and Sijmen De Jong, 'A fast non-negativity-constrained least squares algorithm', Journal of Chemometrics, Vol. 11, 393-401 (1997)
		/// </para>
		/// <para>
		/// Algorithm modified by Dirk Lellinger 2015 to allow a mixture of restricted and unrestricted parameters.
		/// </para>
		/// </remarks>
		public static void Execution(IROMatrix XtX, IROMatrix Xty, double? tolerance, out IMatrix x, out IMatrix w)
		{
			Execution(XtX, Xty, (i) => true, tolerance, out x, out w);
		}
コード例 #2
1
    ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
    ///<param name="B">RHS side of the system.</param>
    ///<returns>the solution matrix, X.</returns>  
    ///<exception cref="ArgumentNullException">B is null.</exception>
    ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception>
    ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception>
    public DoubleMatrix Solve (IROMatrix B) 
    {
      if ( B == null ) 
      {
        throw new System.ArgumentNullException("B cannot be null.");
      }
      Compute();
      if ( !ispd ) 
      {
        throw new NotPositiveDefiniteException();
      } 
      else 
      {
        if ( B.Rows != order ) 
        {
          throw new System.ArgumentException("Matrix row dimensions must agree." );
        }
#if MANAGED
        // Copy right hand side.
        int cols = B.Columns;
        DoubleMatrix X = new DoubleMatrix(B);
        for (int c = 0; c < cols; c++ ) 
        {
          // Solve L*Y = B;
          for (int i = 0; i < order; i++) 
          {
            double sum = B[i,c];
            for (int k = i-1; k >= 0; k--) 
            {
              sum -= l.data[i][k] * X.data[k][c];
            }
            X.data[i][c] = sum / l.data[i][i];
          }

          // Solve L'*X = Y;
          for (int i =order-1; i >= 0; i--) 
          {
            double sum = X.data[i][c];
            for (int k = i+1; k < order; k++) 
            {
              sum -= l.data[k][i] * X.data[k][c];
            }
            X.data[i][c] = sum / l.data[i][i];
          }
        }

        return X;
#else
                double[] rhs = DoubleMatrix.ToLinearArray(B);
                Lapack.Potrs.Compute(Lapack.UpLo.Lower,order,B.Columns,l.data,order,rhs,B.Rows);
                DoubleMatrix ret = new DoubleMatrix(order,B.Columns);
                ret.data = rhs;
                return ret;
#endif
      }
    }
コード例 #3
0
        public void EhCrossValidationWorker(int[] group, IMatrix XX, IMatrix YY, IMatrix XU, IMatrix YU)
        {
            IVector meanX, scaleX, meanY, scaleY;

            MultivariateRegression.PreprocessForAnalysis(_preprocessOptions, _spectralRegions, XX, YY,
                                                         out meanX, out scaleX, out meanY, out scaleY);

            _analysis.AnalyzeFromPreprocessed(XX, YY, _numFactors);
            _numFactors = Math.Min(_numFactors, _analysis.NumberOfFactors);

            MultivariateRegression.PreprocessSpectraForPrediction(_preprocessOptions, XU, meanX, scaleX);
            IROMatrix xResidual = _analysis.SpectralResidualsFromPreprocessed(XU, _numFactors);



            if (this._XCrossResiduals == null)
            {
                this._XCrossResiduals = new MatrixMath.BEMatrix(_numberOfPoints, xResidual.Columns);
            }

            for (int i = 0; i < group.Length; i++)
            {
                MatrixMath.SetRow(xResidual, i, this._XCrossResiduals, group[i]);
            }
        }
コード例 #4
0
        public static void GetSpectralResiduals(
            IROMatrix matrixX,
            IROMatrix xLoads,
            IROMatrix yLoads,
            IROMatrix xScores,
            IROVector crossProduct,
            int numberOfFactors,
            IMatrix spectralResiduals)
        {
            int numX = xLoads.Columns;
            int numY = yLoads.Columns;
            int numM = yLoads.Rows;

            MatrixMath.BEMatrix reconstructedSpectra = new MatrixMath.BEMatrix(matrixX.Rows, matrixX.Columns);
            MatrixMath.ZeroMatrix(reconstructedSpectra);

            for (int nf = 0; nf < numberOfFactors; nf++)
            {
                double scale = crossProduct[nf];
                for (int m = 0; m < numM; m++)
                {
                    for (int k = 0; k < numX; k++)
                    {
                        reconstructedSpectra[m, k] += scale * xScores[m, nf] * xLoads[nf, k];
                    }
                }
            }
            for (int m = 0; m < numM; m++)
            {
                spectralResiduals[m, 0] = MatrixMath.SumOfSquaredDifferences(
                    MatrixMath.ToROSubMatrix(matrixX, m, 0, 1, matrixX.Columns),
                    MatrixMath.ToROSubMatrix(reconstructedSpectra, m, 0, 1, matrixX.Columns));
            }
        }
コード例 #5
0
ファイル: QRDecomposition.cs プロジェクト: olesar/Altaxo
        public IMatrix <double> GetSolution(IROMatrix <double> B)
        {
            var result = new JaggedArrayMatrix(m, B.ColumnCount);

            Solve(B, result);
            return(result);
        }
コード例 #6
0
ファイル: PLS1Regression.cs プロジェクト: carlhuth/GenXSource
 protected override void InternalGetXLeverageFromPreprocessed(IROMatrix matrixX, int numFactors, IMatrix xLeverage)
 {
     for (int i = 0; i < _calib.NumberOfY; i++)
     {
         PLS2Regression.CalculateXLeverageFromPreprocessed(matrixX, _calib.XWeights[i], numFactors, xLeverage, i);
     }
 }
コード例 #7
0
ファイル: PLS1Regression.cs プロジェクト: carlhuth/GenXSource
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
        {
            int     numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);
            IMatrix helperY         = new MatrixMath.BEMatrix(matrixY.Rows, 1);

            _PRESS = null;

            for (int i = 0; i < matrixY.Columns; i++)
            {
                MatrixMath.Submatrix(matrixY, helperY, 0, i);

                PLS2Regression r = PLS2Regression.CreateFromPreprocessed(matrixX, helperY, maxFactors);

                IPLS2CalibrationModel cal = r.CalibrationModel;
                _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors, cal.NumberOfFactors);
                _calib.XLoads[i]       = cal.XLoads;
                _calib.YLoads[i]       = cal.YLoads;
                _calib.XWeights[i]     = cal.XWeights;
                _calib.CrossProduct[i] = cal.CrossProduct;

                if (_PRESS == null)
                {
                    _PRESS = VectorMath.CreateExtensibleVector(r.PRESS.Length);
                }
                VectorMath.Add(_PRESS, r.PRESS, _PRESS);
            }
        }
コード例 #8
0
		/// <summary>
		/// Constructor of a bivariate linear spline. The vectors and the data matrix are not cloned, so make sure that they don't change during usage of this instance.
		/// </summary>
		/// <param name="x">Vector of x values corresponding to the rows of the data matrix. Must be strongly increasing or decreasing.</param>
		/// <param name="y">Vector of y values corresponding to the columns of the data matrix. Must be strongly increasing or decreasing.</param>
		/// <param name="datamatrix"></param>
		public BivariateLinearSpline(IROVector x, IROVector y, IROMatrix datamatrix)
		{
			_x = x;
			_y = y;
			_vmatrix = datamatrix;

			// check the arguments
			if (_x.Length < 2)
				throw new ArgumentException("x.Length is less or equal 1 (you can use univariate interpolation instead)");
			if (_y.Length < 2)
				throw new ArgumentException("y.Length is less or equal 1 (you can use univariate interpolation instead)");
			if (_x.Length != _vmatrix.Rows)
				throw new ArgumentException("Length of vector x is not equal to datamatrix.Rows");
			if (_y.Length != _vmatrix.Columns)
				throw new ArgumentException("Length of vector y is not equal to datamatrix.Columns");

			if (!VectorMath.IsStrictlyIncreasingOrDecreasing(_x, out _isXDecreasing))
				throw new ArgumentException("Vector x is not strictly increasing or decreasing");

			if (!VectorMath.IsStrictlyIncreasingOrDecreasing(_y, out _isYDecreasing))
				throw new ArgumentException("Vector y is not strictly increasing or decreasing");

			_lastIX = 0;
			_lastIY = 0;
		}
コード例 #9
0
        public static void GetPredictionScoreMatrix(
            IROMatrix xLoads,
            IROMatrix yLoads,
            IROMatrix xScores,
            IROVector crossProduct,
            int numberOfFactors,
            IMatrix predictionScores)
        {
            int numX = xLoads.Columns;
            int numY = yLoads.Columns;
            int numM = yLoads.Rows;

            MatrixMath.BEMatrix UtY = new MatrixMath.BEMatrix(xScores.Columns, yLoads.Columns);
            MatrixMath.MultiplyFirstTransposed(xScores, yLoads, UtY);

            MatrixMath.ZeroMatrix(predictionScores);

            for (int nf = 0; nf < numberOfFactors; nf++)
            {
                double scale = 1 / crossProduct[nf];
                for (int cn = 0; cn < numY; cn++)
                {
                    for (int k = 0; k < numX; k++)
                    {
                        predictionScores[k, cn] += scale * xLoads[nf, k] * UtY[nf, cn];
                    }
                }
            }
        }
コード例 #10
0
        // ------------------------ Map indexed with auxillary parameters -----------------------------------------

        /// <summary>
        /// Elementwise application of a function to each element of a matrix. The result is stored in another matrix or in the same matrix.
        /// </summary>
        /// <param name="src1">Matrix to use the values from.</param>
        /// <param name="parameter1">An auxillary parameter.</param>
        /// <param name="function">Function to be applied to each element of the matrix. 1st argument is the row number, 2nd argument the column number, 3rd argument the element of the src matrix, 4th argument the auxillary parameter1.</param>
        /// <param name="result">Matrix to store the result. This may be the same instance as the source matrix.</param>
        public static void MapIndexed <T1>(IROMatrix <double> src1, T1 parameter1, Func <int, int, Double, T1, Double> function, IMatrix <double> result)
        {
            if (null == src1)
            {
                throw new ArgumentNullException(nameof(src1));
            }
            if (null == result)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (src1.RowCount != result.RowCount || src1.ColumnCount != result.ColumnCount)
            {
                throw new RankException("Mismatch of dimensions of src1 and result");
            }

            var cols = src1.ColumnCount;
            var rows = src1.RowCount;

            for (int i = 0; i < rows; ++i)
            {
                for (int j = 0; j < cols; ++j)
                {
                    result[i, j] = function(i, j, src1[i, j], parameter1);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Gets a pixelwise image of the matrix data, i.e. each element of the matrix is converted to a pixel of the resulting bitmap.
        /// </summary>
        /// <param name="matrix">The matrix data.</param>
        /// <param name="image">Bitmap to fill with the pixelwise image. If null, a new image is created.</param>
        /// <exception cref="ArgumentException">An exception will be thrown if the provided image is smaller than the required dimensions.</exception>
        public void GetPixelwiseImage(IROMatrix <double> matrix, ref System.Drawing.Bitmap image)
        {
            // look if the image has the right dimensions

            int numberOfRows    = matrix.RowCount;
            int numberOfColumns = matrix.ColumnCount;

            if (null != image && (image.Width < matrix.ColumnCount || image.Height < matrix.RowCount))
            {
                throw new ArgumentException("The provided image is smaller than required");
            }

            if (null == image)
            {
                // please notice: the horizontal direction of the image is related to the row index!!! (this will turn the image in relation to the table)
                // and the vertical direction of the image is related to the column index
                image = new System.Drawing.Bitmap(numberOfRows, numberOfColumns, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }

            // now we can fill the image with our data
            for (int i = 0; i < numberOfColumns; i++)
            {
                for (int j = 0; j < numberOfRows; j++)
                {
                    image.SetPixel(j, numberOfColumns - i - 1, GetColor(matrix[j, i]));
                } // for all pixel of a column
            }     // for all columns
        }
コード例 #12
0
ファイル: Matrix.cs プロジェクト: olesar/Altaxo
        public void AppendBottom(IROMatrix <double> a)
        {
            if (m_NumVectors == 0 && m_VectorLen == 0)
            {
                m_bVerticalVectors = false;
                m_NumVectors       = a.RowCount;
                m_VectorLen        = a.ColumnCount;
                m_Array            = new double[m_NumVectors][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    m_Array[i] = new double[m_VectorLen];
                }
                MatrixMath.Copy(a, this);
            }
            else if (m_bVerticalVectors == false)
            {
                double[][] newArray = new double[m_NumVectors + a.RowCount][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    newArray[i] = m_Array[i];
                }
                for (int i = m_NumVectors; i < m_NumVectors + a.RowCount; i++)
                {
                    newArray[i] = new double[m_VectorLen];
                }
                m_Array       = newArray;
                m_NumVectors += a.RowCount;

                MatrixMath.Copy(a, this, RowCount - a.RowCount, 0);
            }
            else
            {
                throw new System.NotImplementedException("This worst case is not implemented yet.");
            }
        }
コード例 #13
0
        public int[][] Group(IROMatrix <double> Y)
        {
            var groups = new System.Collections.ArrayList[2];

            for (int i = 0; i < 2; i++)
            {
                groups[i] = new System.Collections.ArrayList();
            }

            int[][] similarGroups = new ExcludeGroupsGroupingStrategy().Group(Y);

            int destinationGroupNumber = 0;

            for (int g = 0; g < similarGroups.Length; g++)
            {
                for (int i = 0; i < similarGroups[g].Length; i++)
                {
                    groups[destinationGroupNumber % 2].Add(similarGroups[g][i]);
                    destinationGroupNumber++;
                }
            }

            int[][] result = new int[2][];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = (int[])groups[i].ToArray(typeof(int));
            }
            return(result);
        }
コード例 #14
0
        public static void GetSpectralResiduals(
            IROMatrix <double> matrixX,
            IROMatrix <double> xLoads,
            IROMatrix <double> yLoads,
            IROMatrix <double> xScores,
            IReadOnlyList <double> crossProduct,
            int numberOfFactors,
            IMatrix <double> spectralResiduals)
        {
            int numX = xLoads.ColumnCount;
            int numY = yLoads.ColumnCount;
            int numM = yLoads.RowCount;

            var reconstructedSpectra = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(matrixX.RowCount, matrixX.ColumnCount);

            MatrixMath.ZeroMatrix(reconstructedSpectra);

            for (int nf = 0; nf < numberOfFactors; nf++)
            {
                double scale = crossProduct[nf];
                for (int m = 0; m < numM; m++)
                {
                    for (int k = 0; k < numX; k++)
                    {
                        reconstructedSpectra[m, k] += scale * xScores[m, nf] * xLoads[nf, k];
                    }
                }
            }
            for (int m = 0; m < numM; m++)
            {
                spectralResiduals[m, 0] = MatrixMath.SumOfSquaredDifferences(
                    MatrixMath.ToROSubMatrix(matrixX, m, 0, 1, matrixX.ColumnCount),
                    MatrixMath.ToROSubMatrix(reconstructedSpectra, m, 0, 1, matrixX.ColumnCount));
            }
        }
コード例 #15
0
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        public static PCRRegression CreateFromPreprocessed(IROMatrix <double> matrixX, IROMatrix <double> matrixY, int maxFactors)
        {
            var result = new PCRRegression();

            result.AnalyzeFromPreprocessed(matrixX, matrixY, maxFactors);
            return(result);
        }
コード例 #16
0
        public static void CalculatePRESS(
            IROMatrix <double> yLoads,
            IROMatrix <double> xScores,
            int numberOfFactors,
            out IROVector <double> press)
        {
            int numMeasurements = yLoads.RowCount;

            IExtensibleVector <double> PRESS = VectorMath.CreateExtensibleVector <double>(numberOfFactors + 1);
            var UtY        = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(yLoads.RowCount, yLoads.ColumnCount);
            var predictedY = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(yLoads.RowCount, yLoads.ColumnCount);

            press = PRESS;

            MatrixMath.MultiplyFirstTransposed(xScores, yLoads, UtY);

            // now calculate PRESS by predicting the y
            // using yp = U (w*(1/w)) U' y
            // of course w*1/w is the identity matrix, but we use only the first factors, so using a cutted identity matrix
            // we precalculate the last term U'y = UtY
            // and multiplying with one row of U in every factor step, summing up the predictedY
            PRESS[0] = MatrixMath.SumOfSquares(yLoads);
            for (int nf = 0; nf < numberOfFactors; nf++)
            {
                for (int cn = 0; cn < yLoads.ColumnCount; cn++)
                {
                    for (int k = 0; k < yLoads.RowCount; k++)
                    {
                        predictedY[k, cn] += xScores[k, nf] * UtY[nf, cn];
                    }
                }
                PRESS[nf + 1] = MatrixMath.SumOfSquaredDifferences(yLoads, predictedY);
            }
        }
コード例 #17
0
        public static void GetPredictionScoreMatrix(
            IROMatrix <double> xLoads,
            IROMatrix <double> yLoads,
            IROMatrix <double> xScores,
            IReadOnlyList <double> crossProduct,
            int numberOfFactors,
            IMatrix <double> predictionScores)
        {
            int numX = xLoads.ColumnCount;
            int numY = yLoads.ColumnCount;
            int numM = yLoads.RowCount;

            var UtY = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(xScores.ColumnCount, yLoads.ColumnCount);

            MatrixMath.MultiplyFirstTransposed(xScores, yLoads, UtY);

            MatrixMath.ZeroMatrix(predictionScores);

            for (int nf = 0; nf < numberOfFactors; nf++)
            {
                double scale = 1 / crossProduct[nf];
                for (int cn = 0; cn < numY; cn++)
                {
                    for (int k = 0; k < numX; k++)
                    {
                        predictionScores[k, cn] += scale * xLoads[nf, k] * UtY[nf, cn];
                    }
                }
            }
        }
コード例 #18
0
        /// <summary>Solves system of linear equations Ax = b using Gaussian elimination with partial pivoting.</summary>
        /// <param name="A">Elements of matrix 'A'.</param>
        /// <param name="b">Right part 'b'</param>
        /// <param name="vectorCreation">Function to create the resulting vector. Argument is the length of the vector.</param>
        public VectorT Solve <VectorT>(IROMatrix <double> A, IReadOnlyList <double> b, Func <int, VectorT> vectorCreation) where VectorT : IVector <double>
        {
            var x = vectorCreation(b.Count);

            Solve(A, b, x);
            return(x);
        }
コード例 #19
0
        /// <summary>
        /// Elementwise application of a function to each element of two matrices. The result is stored in another matrix or in the same matrix.
        /// </summary>
        /// <param name="src1">First matrix to use the values from.</param>
        /// <param name="src2">Second matrix to use the values from.</param>
        /// <param name="function">Function to be applied to each element of src1 and src2.</param>
        /// <param name="result">Matrix to store the result. This may be the same instance as one of the matrices src1 or src2.</param>
        public static void Map(IROMatrix <double> src1, IROMatrix <double> src2, Func <Double, Double, Double> function, IMatrix <double> result)
        {
            if (null == src1)
            {
                throw new ArgumentNullException(nameof(src1));
            }
            if (null == src2)
            {
                throw new ArgumentNullException(nameof(src2));
            }
            if (null == result)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (src1.RowCount != src2.RowCount || src1.ColumnCount != src2.ColumnCount)
            {
                throw new RankException("Mismatch of dimensions of src1 and src2");
            }
            if (src1.RowCount != result.RowCount || src1.ColumnCount != result.ColumnCount)
            {
                throw new RankException("Mismatch of dimensions of src1 and result");
            }

            var cols = src1.ColumnCount;
            var rows = src1.RowCount;

            for (int i = 0; i < rows; ++i)
            {
                for (int j = 0; j < cols; ++j)
                {
                    result[i, j] = function(src1[i, j], src2[i, j]);
                }
            }
        }
コード例 #20
0
        public void AppendRight(IROMatrix a)
        {
            if (m_NumVectors == 0 && m_VectorLen == 0)
            {
                m_bVerticalVectors = true;
                m_NumVectors       = a.Columns;
                m_VectorLen        = a.Rows;
                m_Array            = new double[m_NumVectors][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    m_Array[i] = new double[m_VectorLen];
                }
                MatrixMath.Copy(a, this);
            }
            else if (this.m_bVerticalVectors == true)
            {
                double [][] newArray = new double[m_NumVectors + a.Columns][];
                for (int i = 0; i < m_NumVectors; i++)
                {
                    newArray[i] = m_Array[i];
                }
                for (int i = m_NumVectors; i < m_NumVectors + a.Columns; i++)
                {
                    newArray[i] = new double[m_VectorLen];
                }
                m_Array       = newArray;
                m_NumVectors += a.Columns;

                MatrixMath.Copy(a, this, 0, this.Columns - a.Columns);
            }
            else
            {
                throw new System.NotImplementedException("This worst case is not implemented yet.");
            }
        }
コード例 #21
0
ファイル: PLS1Regression.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Creates an analyis from preprocessed spectra and preprocessed concentrations.
		/// </summary>
		/// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
		/// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
		/// <param name="maxFactors">Maximum number of factors for analysis.</param>
		/// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
		protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
		{
			int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);
			IMatrix helperY = new MatrixMath.BEMatrix(matrixY.Rows, 1);

			_PRESS = null;

			for (int i = 0; i < matrixY.Columns; i++)
			{
				MatrixMath.Submatrix(matrixY, helperY, 0, i);

				PLS2Regression r = PLS2Regression.CreateFromPreprocessed(matrixX, helperY, maxFactors);

				IPLS2CalibrationModel cal = r.CalibrationModel;
				_calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors, cal.NumberOfFactors);
				_calib.XLoads[i] = cal.XLoads;
				_calib.YLoads[i] = cal.YLoads;
				_calib.XWeights[i] = cal.XWeights;
				_calib.CrossProduct[i] = cal.CrossProduct;

				if (_PRESS == null)
					_PRESS = VectorMath.CreateExtensibleVector(r.PRESS.Length);
				VectorMath.Add(_PRESS, r.PRESS, _PRESS);
			}
		}
コード例 #22
0
ファイル: PLS2Regression.cs プロジェクト: carlhuth/GenXSource
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        public static PLS2Regression CreateFromPreprocessed(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
        {
            PLS2Regression result = new PLS2Regression();

            result.AnalyzeFromPreprocessed(matrixX, matrixY, maxFactors);
            return(result);
        }
コード例 #23
0
        public static void Predict(
            IROMatrix <double> XU,             // unknown spectrum or spectra,  horizontal oriented
            IROMatrix <double> xLoads,         // x-loads matrix
            IROMatrix <double> yLoads,         // y-loads matrix
            IROMatrix <double> W,              // weighting matrix
            IROMatrix <double> V,              // Cross product vector
            int numFactors,                    // number of factors to use for prediction
            IMatrix <double> predictedY,       // Matrix of predicted y-values, must be same number of rows as spectra
            IMatrix <double> spectralResiduals // Matrix of spectral residuals, n rows x 1 column, can be zero
            )
        {
            // now predicting a "unkown" spectra
            var si = new MatrixMath.ScalarAsMatrix <double>(0);
            var Cu = new MatrixMath.MatrixWithOneRow <double>(yLoads.ColumnCount);

            var wi    = new MatrixMath.MatrixWithOneRow <double>(XU.ColumnCount);
            var cuadd = new MatrixMath.MatrixWithOneRow <double>(yLoads.ColumnCount);

            // xu holds a single spectrum extracted out of XU
            var xu = new MatrixMath.MatrixWithOneRow <double>(XU.ColumnCount);

            // xl holds temporarily a row of the xLoads matrix+
            var xl = new MatrixMath.MatrixWithOneRow <double>(xLoads.ColumnCount);

            int maxFactors = Math.Min(yLoads.RowCount, numFactors);

            for (int nSpectrum = 0; nSpectrum < XU.RowCount; nSpectrum++)
            {
                MatrixMath.Submatrix(XU, xu, nSpectrum, 0); // extract one spectrum to predict
                MatrixMath.ZeroMatrix(Cu);                  // Set Cu=0
                for (int i = 0; i < maxFactors; i++)
                {
                    //1. Calculate the unknown spectral score for a weighting vector
                    MatrixMath.Submatrix(W, wi, i, 0);
                    MatrixMath.MultiplySecondTransposed(wi, xu, si);
                    // take the y loading vector
                    MatrixMath.Submatrix(yLoads, cuadd, i, 0);
                    // and multiply it with the cross product and the score
                    MatrixMath.MultiplyScalar(cuadd, si * V[0, i], cuadd);
                    // Add it to the predicted y-values
                    MatrixMath.Add(Cu, cuadd, Cu);
                    // remove the spectral contribution of the factor from the spectrum
                    // TODO this is quite ineffective: in every loop we extract the xl vector, we have to find a shortcut for this!
                    MatrixMath.Submatrix(xLoads, xl, i, 0);
                    MatrixMath.SubtractProductFromSelf(xl, (double)si, xu);
                }
                // xu now contains the spectral residual,
                // Cu now contains the predicted y values
                if (null != predictedY)
                {
                    MatrixMath.SetRow(Cu, 0, predictedY, nSpectrum);
                }

                if (null != spectralResiduals)
                {
                    spectralResiduals[nSpectrum, 0] = MatrixMath.SumOfSquares(xu);
                }
            } // for each spectrum in XU
        }     // end partial-least-squares-predict
コード例 #24
0
		public static void SetContentFromMatrix(DataTable destinationTable, IROMatrix matrix, string columnBaseName, IROVector rowHeaderColumn, string rowHeaderColumnName, IROVector colHeaderColumn, string colHeaderColumnName)
		{
			var c = new MatrixToDataTableConverter(matrix, destinationTable);
			c.ColumnBaseName = columnBaseName;
			c.AddMatrixColumnHeaderData(rowHeaderColumn, rowHeaderColumnName);
			c.AddMatrixColumnHeaderData(colHeaderColumn, colHeaderColumnName);
			c.Execute();
		}
コード例 #25
0
 /// <summary>
 /// Creates an instance of <see cref="SubMatrixROWrapper{T}"/>
 /// </summary>
 /// <param name="matrix">Matrix to wrap.</param>
 /// <param name="rowOffset">First row of the matrix that will become row 0 of the submatrix.</param>
 /// <param name="columnOffset">First column of the matrix that will become column 0 of the submatrix.</param>
 /// <param name="rows">Number of rows of the submatrix.</param>
 /// <param name="cols">Number of columns of the submatrix.</param>
 public SubMatrixROWrapper(IROMatrix <T> matrix, int rowOffset, int columnOffset, int rows, int cols)
 {
     _matrix       = matrix;
     _rowOffset    = rowOffset;
     _columnOffset = columnOffset;
     _rows         = rows;
     _cols         = cols;
 }
コード例 #26
0
 ///<summary>Constructor for SVD decomposition class.</summary>
 ///<param name="matrix">The matrix to decompose.</param>
 ///<exception cref="ArgumentNullException">matrix is null.</exception>
 public FloatSVDDecomp(IROMatrix <float> matrix)
 {
     if (matrix == null)
     {
         throw new System.ArgumentNullException("matrix cannot be null.");
     }
     this.matrix = new FloatMatrix(matrix);
 }
コード例 #27
0
ファイル: QRDecomposition.cs プロジェクト: olesar/Altaxo
        public DoubleVector GetSolution(IROMatrix <double> A, IReadOnlyList <double> B)
        {
            Decompose(A);
            var result = new DoubleVector(m);

            Solve(B, result);
            return(result);
        }
コード例 #28
0
ファイル: DoubleQRDecomp.cs プロジェクト: olesar/Altaxo
 ///<summary>Constructor for QR decomposition class. The constructor performs the factorization and the upper and
 ///lower matrices are accessible by the <c>Q</c> and <c>R</c> properties.</summary>
 ///<param name="matrix">The matrix to factor.</param>
 ///<exception cref="ArgumentNullException">matrix is null.</exception>
 public DoubleQRDecomp(IROMatrix <double> matrix)
 {
     if (matrix == null)
     {
         throw new System.ArgumentNullException("matrix cannot be null.");
     }
     this.matrix = new DoubleMatrix(matrix);
 }
コード例 #29
0
        ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
        ///<param name="B">RHS side of the system.</param>
        ///<returns>the solution matrix, X.</returns>
        ///<exception cref="ArgumentNullException">B is null.</exception>
        ///<exception cref="SingularMatrixException">A is singular.</exception>
        ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception>
        public DoubleMatrix Solve(IROMatrix <double> B)
        {
            if (B == null)
            {
                throw new System.ArgumentNullException("B cannot be null.");
            }
            Compute();
            if (singular)
            {
                throw new SingularMatrixException();
            }
            else
            {
                if (B.RowCount != order)
                {
                    throw new System.ArgumentException("Matrix row dimensions must agree.");
                }
#if MANAGED
                // Copy right hand side with pivoting
                int          nx = B.ColumnCount;
                DoubleMatrix X  = Pivot(B);

                // Solve L*Y = B(piv,:)
                for (int k = 0; k < order; k++)
                {
                    for (int i = k + 1; i < order; i++)
                    {
                        for (int j = 0; j < nx; j++)
                        {
                            X.data[i][j] -= X.data[k][j] * factor[i][k];
                        }
                    }
                }
                // Solve U*X = Y;
                for (int k = order - 1; k >= 0; k--)
                {
                    for (int j = 0; j < nx; j++)
                    {
                        X.data[k][j] /= factor[k][k];
                    }
                    for (int i = 0; i < k; i++)
                    {
                        for (int j = 0; j < nx; j++)
                        {
                            X.data[i][j] -= X.data[k][j] * factor[i][k];
                        }
                    }
                }
                return(X);
#else
                double[] rhs = DoubleMatrix.ToLinearArray(B);
                Lapack.Getrs.Compute(Lapack.Transpose.NoTrans, order, B.Columns, factor, order, pivots, rhs, B.Rows);
                DoubleMatrix ret = new DoubleMatrix(order, B.Columns);
                ret.data = rhs;
                return(ret);
#endif
            }
        }
コード例 #30
0
 public DenseJacobianEvaluator(int N, Action <double, double[], double[]> f)
 {
     variatedX   = new double[N];
     f_old       = new double[N];
     f_new       = new double[N];
     J           = new DoubleMatrix(N, N);
     J_ROWrapper = J.ToROMatrix();
     this.f      = f;
 }
コード例 #31
0
        public static void SetContentFromMatrix(DataTable destinationTable, IROMatrix <double> matrix, string columnBaseName)
        {
            var c = new MatrixToDataTableConverter(matrix, destinationTable)
            {
                ColumnBaseName = columnBaseName
            };

            c.Execute();
        }
コード例 #32
0
ファイル: QRDecomposition.cs プロジェクト: olesar/Altaxo
        public void Decompose(IROMatrix <double> A)
        {
            // Initialize.
            if (m == A.RowCount && n == A.ColumnCount)
            {
                MatrixMath.Copy(A, new JaggedArrayMatrix(QR, m, n));
                //JaggedArrayMath.Copy(A, QR);
            }
            else
            {
                QR    = JaggedArrayMath.GetMatrixCopy(A);
                m     = A.RowCount;
                n     = A.ColumnCount;
                Rdiag = new double[n];
            }

            // Main loop.
            for (int k = 0; k < n; k++)
            {
                // Compute 2-norm of k-th column without under/overflow.
                double nrm = 0;
                for (int i = k; i < m; i++)
                {
                    nrm = RMath.Hypot(nrm, QR[i][k]);
                }

                if (nrm != 0.0)
                {
                    // Form k-th Householder vector.
                    if (QR[k][k] < 0)
                    {
                        nrm = -nrm;
                    }
                    for (int i = k; i < m; i++)
                    {
                        QR[i][k] /= nrm;
                    }
                    QR[k][k] += 1.0;

                    // Apply transformation to remaining columns.
                    for (int j = k + 1; j < n; j++)
                    {
                        double s = 0.0;
                        for (int i = k; i < m; i++)
                        {
                            s += QR[i][k] * QR[i][j];
                        }
                        s = -s / QR[k][k];
                        for (int i = k; i < m; i++)
                        {
                            QR[i][j] += s * QR[i][k];
                        }
                    }
                }
                Rdiag[k] = -nrm;
            }
        }
コード例 #33
0
ファイル: QRDecomposition.cs プロジェクト: Altaxo/Altaxo
		public void Decompose(IROMatrix A)
		{
			// Initialize.
			if (m == A.Rows && n == A.Columns)
			{
				MatrixMath.Copy(A, new JaggedArrayMatrix(QR, m, n));
				//JaggedArrayMath.Copy(A, QR);
			}
			else
			{
				QR = JaggedArrayMath.GetMatrixCopy(A);
				m = A.Rows;
				n = A.Columns;
				Rdiag = new double[n];
			}

			// Main loop.
			for (int k = 0; k < n; k++)
			{
				// Compute 2-norm of k-th column without under/overflow.
				double nrm = 0;
				for (int i = k; i < m; i++)
				{
					nrm = RMath.Hypot(nrm, QR[i][k]);
				}

				if (nrm != 0.0)
				{
					// Form k-th Householder vector.
					if (QR[k][k] < 0)
					{
						nrm = -nrm;
					}
					for (int i = k; i < m; i++)
					{
						QR[i][k] /= nrm;
					}
					QR[k][k] += 1.0;

					// Apply transformation to remaining columns.
					for (int j = k + 1; j < n; j++)
					{
						double s = 0.0;
						for (int i = k; i < m; i++)
						{
							s += QR[i][k] * QR[i][j];
						}
						s = -s / QR[k][k];
						for (int i = k; i < m; i++)
						{
							QR[i][j] += s * QR[i][k];
						}
					}
				}
				Rdiag[k] = -nrm;
			}
		}
コード例 #34
0
 ///<summary>Constructor for SVD decomposition class.</summary>
 ///<param name="matrix">The matrix to decompose.</param>
 ///<param name="computeVectors">Whether to compute the singular vectors or not.</param>
 ///<exception cref="ArgumentNullException">matrix is null.</exception>
 public DoubleSVDDecomp(IROMatrix matrix, bool computeVectors)
 {
     if (matrix == null)
     {
         throw new System.ArgumentNullException("matrix cannot be null.");
     }
     this.matrix         = new DoubleMatrix(matrix);
     this.computeVectors = computeVectors;
 }
コード例 #35
0
        ///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary>
        ///<param name="B">RHS side of the system.</param>
        ///<returns>the solution matrix, X.</returns>
        ///<exception cref="ArgumentNullException">B is null.</exception>
        ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception>
        ///<exception cref="ArgumentException">The number of rows of A and B must be the same.</exception>
        public DoubleMatrix Solve(IROMatrix B)
        {
            if (B == null)
            {
                throw new System.ArgumentNullException("B cannot be null.");
            }
            Compute();
            if (!ispd)
            {
                throw new NotPositiveDefiniteException();
            }
            else
            {
                if (B.Rows != order)
                {
                    throw new System.ArgumentException("Matrix row dimensions must agree.");
                }
#if MANAGED
                // Copy right hand side.
                int          cols = B.Columns;
                DoubleMatrix X    = new DoubleMatrix(B);
                for (int c = 0; c < cols; c++)
                {
                    // Solve L*Y = B;
                    for (int i = 0; i < order; i++)
                    {
                        double sum = B[i, c];
                        for (int k = i - 1; k >= 0; k--)
                        {
                            sum -= l.data[i][k] * X.data[k][c];
                        }
                        X.data[i][c] = sum / l.data[i][i];
                    }

                    // Solve L'*X = Y;
                    for (int i = order - 1; i >= 0; i--)
                    {
                        double sum = X.data[i][c];
                        for (int k = i + 1; k < order; k++)
                        {
                            sum -= l.data[k][i] * X.data[k][c];
                        }
                        X.data[i][c] = sum / l.data[i][i];
                    }
                }

                return(X);
#else
                double[] rhs = DoubleMatrix.ToLinearArray(B);
                Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, B.Columns, l.data, order, rhs, B.Rows);
                DoubleMatrix ret = new DoubleMatrix(order, B.Columns);
                ret.data = rhs;
                return(ret);
#endif
            }
        }
コード例 #36
0
 /// <summary>
 /// Fits a data set linear to a given x base.
 /// </summary>
 /// <param name="xbase">The matrix of x values of the data set. Dimensions: numberOfData x numberOfParameters. The matrix is changed during calculation!</param>
 /// <param name="yarr">The array of y values of the data set.</param>
 /// <param name="stddev">The array of y standard deviations of the data set.</param>
 /// <param name="numberOfData">The number of data points (may be smaller than the array sizes of the data arrays).</param>
 /// <param name="numberOfParameter">The number of parameters to fit == size of the function base.</param>
 /// <param name="threshold">A treshold value (usually 1E-5) used to chop the unimportant singular values away.</param>
 public LinearFitBySvd(
     IROMatrix xbase, // NumberOfData, NumberOfParameters
     double[] yarr,
     double[] stddev,
     int numberOfData,
     int numberOfParameter,
     double threshold)
 {
     Calculate(xbase, yarr, stddev, numberOfData, numberOfParameter, threshold);
 }
コード例 #37
0
		public MatrixToDataTableConverter(IROMatrix sourceMatrix, DataTable destinationTable)
		{
			if (null == sourceMatrix)
				throw new ArgumentNullException("sourceMatrix");
			if (null == destinationTable)
				throw new ArgumentNullException("destinationTable");

			_sourceMatrix = sourceMatrix;
			_destinationTable = destinationTable;
		}
コード例 #38
0
ファイル: JaggedArrayMath.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Allocates an array of the same dimensions than the provided matrix a, and copies the element of a to the new array.
		/// </summary>
		/// <param name="a">The matrix to copy.</param>
		/// <returns>New jagged array with the same element values than matrix a.</returns>
		public static double[][] GetMatrixCopy(IROMatrix a)
		{
			int rows = a.Rows;
			int cols = a.Columns;
			double[][] result = new double[rows][];
			double[] row;
			for (int i = 0; i < rows; i++)
			{
				result[i] = row = new double[cols];
				for (int j = 0; j < cols; j++)
					row[j] = a[i, j];
			}
			return result;
		}
コード例 #39
0
ファイル: PCRRegression.cs プロジェクト: Altaxo/Altaxo
		public override IROVector GetPRESSFromPreprocessed(IROMatrix matrixX)
		{
			IROVector result;
			CalculatePRESS(
				matrixX,
				_calib.XLoads,
				_calib.YLoads,
				_calib.XScores,
				_calib.CrossProduct,
				_calib.NumberOfFactors,
				out result);

			return result;
		}
コード例 #40
0
    ///<summary>Constructor for Cholesky decomposition class. The constructor performs the factorization of a symmetric positive
    ///definite matrax and the Cholesky factored matrix is accessible by the <c>Factor</c> property. The factor is the lower 
    ///triangular factor.</summary>
    ///<param name="matrix">The matrix to factor.</param>
    ///<exception cref="ArgumentNullException">matrix is null.</exception>
    ///<exception cref="NotSquareMatrixException">matrix is not square.</exception>
    ///<remarks>This class only uses the lower triangle of the input matrix. It ignores the
    ///upper triangle.</remarks>
    public DoubleCholeskyDecomp(IROMatrix matrix)
    {
      if ( matrix == null ) 
      {
        throw new System.ArgumentNullException("matrix cannot be null.");
      }

      if ( matrix.Rows != matrix.Columns ) 
      {
        throw new NotSquareMatrixException("Matrix must be square.");
      }

      order = matrix.Columns;
      this.matrix = new DoubleMatrix(matrix);
    }
コード例 #41
0
    /// <summary>
    /// <see cref="ICrossValidationGroupingStrategy.Group" />
    /// </summary>
    /// <param name="Y"></param>
    /// <returns></returns>
    public int[][] Group(IROMatrix Y)
    {
      System.Collections.ArrayList groups = new System.Collections.ArrayList();

      // add the first y-row to the first group
      System.Collections.ArrayList newcoll = new System.Collections.ArrayList();
      newcoll.Add(0);
      groups.Add(newcoll);
      // now test all other rows of the y-matrix against the existing groups
      for(int i=1;i<Y.Rows;i++)
      {
        bool bNewGroup=true;
        for(int gr=0;gr<groups.Count;gr++)
        {
          int refrow = (int)(((System.Collections.ArrayList)groups[gr])[0]);
          bool match = true;
          for(int j=0;j<Y.Columns;j++)
          {
            if(Y[i,j]!= Y[refrow,j])
            {
              match=false;
              break;
            }
          }
            
          if(match)
          {
            bNewGroup=false;
            ((System.Collections.ArrayList)groups[gr]).Add(i);
            break;
          }
        }
        if(bNewGroup)
        {
          newcoll = new System.Collections.ArrayList();
          newcoll.Add(i);
          groups.Add(newcoll);
        }
      }

      int[][] result = new int[groups.Count][];
      for(int i=0;i<result.Length;i++)
        result[i] = (int[])((System.Collections.ArrayList)groups[i]).ToArray(typeof(int));
      return result;
    }
コード例 #42
0
ファイル: BivariateAkimaSpline.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Constructs an Akima bivariate spline.
		/// </summary>
		/// <param name="x">ARRAY OF DIMENSION LX STORING THE X COORDINATES OF INPUT GRID POINTS (IN ASCENDING ORDER)</param>
		/// <param name="y">ARRAY OF DIMENSION LY STORING THE Y COORDINATES OF INPUT GRID POINTS (IN ASCENDING ORDER)</param>
		/// <param name="z">DOUBLY-DIMENSIONED ARRAY OF DIMENSION (LX,LY) STORING THE VALUES OF THE FUNCTION (Z VALUES) AT INPUT GRID POINTS</param>
		/// <param name="copyDataLocally">If true, the data where cloned before stored here in this instance. If false, the data
		/// are stored directly. Make sure then, that the data are not changed outside.</param>
		public BivariateAkimaSpline(IROVector x, IROVector y, IROMatrix z, bool copyDataLocally)
		{
			if (copyDataLocally)
			{
				_myX = VectorMath.ToVector(new double[x.Length]);
				VectorMath.Copy(x, (IVector)_myX);

				_myY = VectorMath.ToVector(new double[y.Length]);
				VectorMath.Copy(y, (IVector)_myY);

				_myZ = new MatrixMath.BEMatrix(_myZ.Rows, _myZ.Columns);
				MatrixMath.Copy(z, (IMatrix)_myZ);
			}
			else
			{
				_myX = x;
				_myY = y;
				_myZ = z;
			}
		}
コード例 #43
0
    /// <summary>
    /// Calculates the spectral residuals obtained from cross validation.
    /// </summary>
    /// <param name="xOfX">The spectral wavelength values corresponding to the spectral bins.</param>
    /// <param name="X">Matrix of spectra (a spectrum = a row in the matrix).</param>
    /// <param name="Y">Matrix of y values (e.g. concentrations).</param>
    /// <param name="numFactors">Number of factors used for calculation.</param>
    /// <param name="groupingStrategy">The strategy how to group the spectra for cross prediction.</param>
    /// <param name="preprocessOptions">Information how to preprocess the data.</param>
    /// <param name="regress">The type of regression (e.g. PCR, PLS1, PLS2) provided as an empty regression object.</param>
    /// <param name="crossXResiduals">Returns the matrix of spectral residuals</param>
    /// <returns>Mean number of spectra used for prediction.</returns>
    public static double GetCrossXResiduals(
      IROVector xOfX,
      IROMatrix X, // matrix of spectra (a spectra is a row of this matrix)
      IROMatrix Y, // matrix of concentrations (a mixture is a row of this matrix)
      int numFactors,
      ICrossValidationGroupingStrategy groupingStrategy,
      SpectralPreprocessingOptions preprocessOptions,
      MultivariateRegression regress,

      out IROMatrix crossXResiduals
      )
    {
      return GetCrossXResiduals(
        SpectralPreprocessingOptions.IdentifyRegions(xOfX),
        X, // matrix of spectra (a spectra is a row of this matrix)
        Y, // matrix of concentrations (a mixture is a row of this matrix)
        numFactors,
        groupingStrategy,
        preprocessOptions,
        regress,

        out crossXResiduals);
    }
コード例 #44
0
    /// <summary>
    /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
    /// </summary>
    /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
    /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
    /// <param name="maxFactors">Maximum number of factors for analysis.</param>
    /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
    protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
    {
      int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);

      MatrixMath.BEMatrix _xLoads   = new MatrixMath.BEMatrix(0,0);
      MatrixMath.BEMatrix _yLoads   = new MatrixMath.BEMatrix(0,0);
      MatrixMath.BEMatrix _W       = new MatrixMath.BEMatrix(0,0);
      MatrixMath.REMatrix _V       = new MatrixMath.REMatrix(0,0);
      _PRESS   = VectorMath.CreateExtensibleVector(0);

      ExecuteAnalysis(matrixX, matrixY, ref numberOfFactors, _xLoads, _yLoads, _W, _V, _PRESS);
      _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors,numberOfFactors);
      _calib.XLoads = _xLoads;
      _calib.YLoads = _yLoads;
      _calib.XWeights = _W;
      _calib.CrossProduct = _V;
    }
コード例 #45
0
 /// <summary>
 /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
 /// </summary>
 /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
 /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
 /// <param name="maxFactors">Maximum number of factors for analysis.</param>
 /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
 public static PLS2Regression CreateFromPreprocessed(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
 {
   PLS2Regression result = new PLS2Regression();
   result.AnalyzeFromPreprocessed(matrixX,matrixY,maxFactors);
   return result;
 }
コード例 #46
0
    } // end partial-least-squares-predict


   
    public static void CalculateXLeverageFromPreprocessed(
      IROMatrix matrixX,
      IROMatrix W, // weighting matrix
      int numFactors, // number of factors to use for prediction
      IMatrix leverage, // Matrix of predicted y-values, must be same number of rows as spectra
      int leverageColumn
      )
    {

      // get the score matrix
      MatrixMath.BEMatrix weights = new MatrixMath.BEMatrix(numFactors,W.Columns);
      MatrixMath.Submatrix(W,weights,0,0);
      MatrixMath.BEMatrix scoresMatrix = new MatrixMath.BEMatrix(matrixX.Rows,weights.Rows);
      MatrixMath.MultiplySecondTransposed(matrixX,weights,scoresMatrix);
    
      MatrixMath.SingularValueDecomposition decomposition = MatrixMath.GetSingularValueDecomposition(scoresMatrix);


      for(int i=0;i<matrixX.Rows;i++)
        leverage[i,leverageColumn] = decomposition.HatDiagonal[i];
    }
コード例 #47
0
    /// <summary>
    /// Fits a data set linear to a given x base.
    /// </summary>
    /// <param name="xbase">The matrix of x values of the data set. Dimensions: numberOfData x numberOfParameters. The matrix is changed during calculation!</param>
    /// <param name="yarr">The array of y values of the data set.</param>
    /// <param name="stddev">The array of y standard deviations of the data set. Can be null if the standard deviation is unkown.</param>
    /// <param name="numberOfData">The number of data points (may be smaller than the array sizes of the data arrays).</param>
    /// <param name="numberOfParameter">The number of parameters to fit == size of the function base.</param>
    /// <param name="threshold">A treshold value (usually 1E-5) used to chop the unimportant singular values away.</param>
    public LinearFitBySvd Calculate(
      IROMatrix xbase, // NumberOfData, NumberOfParameters 
      double[] yarr,
      double[] stddev,
      int numberOfData,
      int numberOfParameter,
      double threshold)
    {
      _numberOfParameter = numberOfParameter;
      _numberOfFreeParameter = numberOfParameter;
      _numberOfData      = numberOfData;
      _parameter = new double[numberOfParameter];
      _residual = new double[numberOfData];
      _predicted = new double[numberOfData];
      _reducedPredictionVariance = new double[numberOfData];

      double[] scaledY      = new double[numberOfData];
      
      // Calculated some useful values
      _yMean = Mean(yarr,0,_numberOfData);
      _yCorrectedSumOfSquares = CorrectedSumOfSquares(yarr,_yMean,0,_numberOfData);

      MatrixMath.BEMatrix u = new MatrixMath.BEMatrix(numberOfData,numberOfParameter);
      // Fill the function base matrix (rows: numberOfData, columns: numberOfParameter)
      // and scale also y
      if (null == stddev)
      {
        for (int i = 0; i < numberOfData; i++)
        {
          for (int j = 0; j < numberOfParameter; j++)
            u[i, j] = xbase[i, j];

          scaledY[i] = yarr[i];
        }
      }
      else
      {
        for (int i = 0; i < numberOfData; i++)
        {
          double scale = 1 / stddev[i];

          for (int j = 0; j < numberOfParameter; j++)
            u[i, j] = scale * xbase[i, j];

          scaledY[i] = scale * yarr[i];
        }
      }
      _decomposition = MatrixMath.GetSingularValueDecomposition(u);

      // set singular values < thresholdLevel to zero
      // ChopSingularValues makes only sense if all columns of the x matrix have the same variance
      //decomposition.ChopSingularValues(1E-5);
      // recalculate the parameters with the chopped singular values
      _decomposition.Backsubstitution(scaledY,_parameter);

      _chiSquare = 0;
      for(int i=0;i<numberOfData;i++)
      {
        double ypredicted=0;
        for(int j=0;j<numberOfParameter;j++)
          ypredicted += _parameter[j]*xbase[i,j];
        double deviation = yarr[i]-ypredicted;
        _predicted[i] = ypredicted;
        _residual[i] = deviation;
        _chiSquare += deviation*deviation;
      }
    
      _covarianceMatrix = _decomposition.GetCovariances();


      //calculate the reduced prediction variance x'(X'X)^(-1)x
      for(int i=0;i<numberOfData;i++)
      {
        double total = 0;
        for(int j=0;j<numberOfParameter;j++)
        {
          double sum=0;
          for(int k=0;k<numberOfParameter;k++)
            sum += _covarianceMatrix[j][k]*u[i,k];

          total += u[i,j]*sum;
        }
        _reducedPredictionVariance[i] = total;
      }
 
      return this;
    }
コード例 #48
0
    /// <summary>
    /// Partial least squares (PLS) decomposition of the matrizes X and Y.
    /// </summary>
    /// <param name="_X">The X ("spectrum") matrix, centered and preprocessed.</param>
    /// <param name="_Y">The Y ("concentration") matrix (centered).</param>
    /// <param name="numFactors">Number of factors to calculate.</param>
    /// <param name="xLoads">Returns the matrix of eigenvectors of X. Should be initially empty.</param>
    /// <param name="yLoads">Returns the matrix of eigenvectors of Y. Should be initially empty. </param>
    /// <param name="W">Returns the matrix of weighting values. Should be initially empty.</param>
    /// <param name="V">Returns the vector of cross products. Should be initially empty.</param>
    /// <param name="PRESS">If not null, the PRESS value of each factor is stored (vertically) here. </param>
    public static void ExecuteAnalysis(
      IROMatrix _X, // matrix of spectra (a spectra is a row of this matrix)
      IROMatrix _Y, // matrix of concentrations (a mixture is a row of this matrix)
      ref int numFactors,
      IBottomExtensibleMatrix xLoads, // out: the loads of the X matrix
      IBottomExtensibleMatrix yLoads, // out: the loads of the Y matrix
      IBottomExtensibleMatrix W, // matrix of weighting values
      IRightExtensibleMatrix V,  // matrix of cross products
      IExtensibleVector PRESS //vector of Y PRESS values
      )
    {
      // used variables:
      // n: number of spectra (number of tests, number of experiments)
      // p: number of slots (frequencies, ..) in each spectrum
      // m: number of constitutents (number of y values in each measurement)
      
      // X : n-p matrix of spectra (each spectra is a horizontal row)
      // Y : n-m matrix of concentrations


      const int maxIterations = 1500; // max number of iterations in one factorization step
      const double accuracy = 1E-12; // accuracy that should be reached between subsequent calculations of the u-vector



      // use the mean spectrum as first row of the W matrix
      MatrixMath.HorizontalVector mean = new MatrixMath.HorizontalVector(_X.Columns);
      //  MatrixMath.ColumnsToZeroMean(X,mean);
      //W.AppendBottom(mean);

      IMatrix X = new MatrixMath.BEMatrix(_X.Rows,_X.Columns);
      MatrixMath.Copy(_X,X);
      IMatrix Y = new MatrixMath.BEMatrix(_Y.Rows,_Y.Columns);
      MatrixMath.Copy(_Y,Y);

      IMatrix u_prev = null;
      IMatrix w = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X (spectral) weighting
      IMatrix t = new MatrixMath.VerticalVector(X.Rows); // vertical vector of X  scores
      IMatrix u = new MatrixMath.VerticalVector(X.Rows); // vertical vector of Y scores
      IMatrix p = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X loads
      IMatrix q = new MatrixMath.HorizontalVector(Y.Columns); // horizontal vector of Y loads

      int maxFactors = Math.Min(X.Columns,X.Rows);
      numFactors = numFactors<=0 ? maxFactors : Math.Min(numFactors,maxFactors);

      if(PRESS!=null)
      {
        PRESS.Append(new MatrixMath.Scalar(MatrixMath.SumOfSquares(Y))); // Press value for not decomposed Y
      }

      for(int nFactor=0; nFactor<numFactors; nFactor++)
      {
        //Console.WriteLine("Factor_{0}:",nFactor);
        //Console.WriteLine("X:"+X.ToString());
        //Console.WriteLine("Y:"+Y.ToString());

  
        // 1. Use as start vector for the y score the first column of the 
        // y-matrix
        MatrixMath.Submatrix(Y,u); // u is now a vertical vector of concentrations of the first constituents

        for(int iter=0;iter<maxIterations;iter++)
        {
          // 2. Calculate the X (spectrum) weighting vector
          MatrixMath.MultiplyFirstTransposed(u,X,w); // w is a horizontal vector

          // 3. Normalize w to unit length
          MatrixMath.NormalizeRows(w); // w now has unit length

          // 4. Calculate X (spectral) scores
          MatrixMath.MultiplySecondTransposed(X,w,t); // t is a vertical vector of n numbers

          // 5. Calculate the Y (concentration) loading vector
          MatrixMath.MultiplyFirstTransposed(t,Y,q); // q is a horizontal vector of m (number of constitutents)

          // 5.1 Normalize q to unit length
          MatrixMath.NormalizeRows(q);

          // 6. Calculate the Y (concentration) score vector u
          MatrixMath.MultiplySecondTransposed(Y,q,u); // u is a vertical vector of n numbers

          // 6.1 Compare
          // Compare this with the previous one 
          if(u_prev!=null && MatrixMath.IsEqual(u_prev,u,accuracy))
            break;
          if(u_prev==null)
            u_prev = new MatrixMath.VerticalVector(X.Rows);
          MatrixMath.Copy(u,u_prev); // stores the content of u in u_prev
        } // for all iterations

        // Store the scores of X
        //factors.AppendRight(t);


        // 7. Calculate the inner scalar (cross product)
        double length_of_t = MatrixMath.LengthOf(t); 
        MatrixMath.Scalar v = new MatrixMath.Scalar(0);
        MatrixMath.MultiplyFirstTransposed(u,t,v);
        if(length_of_t!=0)
          v = v/MatrixMath.Square(length_of_t); 
      
        // 8. Calculate the new loads for the X (spectral) matrix
        MatrixMath.MultiplyFirstTransposed(t,X,p); // p is a horizontal vector of loads
        // Normalize p by the spectral scores

        if(length_of_t!=0)
          MatrixMath.MultiplyScalar(p,1/MatrixMath.Square(length_of_t),p);

        // 9. Calculate the new residua for the X (spectral) and Y (concentration) matrix
        //MatrixMath.MultiplyScalar(t,length_of_t*v,t); // original t times the cross product

        MatrixMath.SubtractProductFromSelf(t,p,X);
        
        MatrixMath.MultiplyScalar(t,v,t); // original t times the cross product
        MatrixMath.SubtractProductFromSelf(t,q,Y); // to calculate residual Y

        // Store the loads of X and Y in the output result matrix
        xLoads.AppendBottom(p);
        yLoads.AppendBottom(q);
        W.AppendBottom(w);
        V.AppendRight(v);
    
        if(PRESS!=null)
        {
          double pressValue=MatrixMath.SumOfSquares(Y);
          PRESS.Append(new MatrixMath.Scalar(pressValue));
        }
        // Calculate SEPcv. If SEPcv is greater than for the actual number of factors,
        // break since the optimal number of factors was found. If not, repeat the calculations
        // with the residual matrizes for the next factor.
      } // for all factors
    }
コード例 #49
0
 protected override void InternalGetXLeverageFromPreprocessed(IROMatrix matrixX, int numFactors, IMatrix xLeverage)
 {
   PLS2Regression.CalculateXLeverageFromPreprocessed(matrixX,_calib.XWeights,numFactors,xLeverage,0);
 }
コード例 #50
0
    /// <summary>
    /// This predicts concentrations of unknown spectra.
    /// </summary>
    /// <param name="XU">Matrix of unknown spectra (preprocessed the same way as the calibration spectra).</param>
    /// <param name="numFactors">Number of factors used for prediction.</param>
    /// <param name="predictedY">On return, holds the predicted y values. (They are centered).</param>
    /// <param name="spectralResiduals">On return, holds the spectral residual values.</param>
    public override void PredictedYAndSpectralResidualsFromPreprocessed(
      IROMatrix XU, // unknown spectrum or spectra,  horizontal oriented
      int numFactors, // number of factors to use for prediction
      IMatrix predictedY, // Matrix of predicted y-values, must be same number of rows as spectra
      IMatrix spectralResiduals // Matrix of spectral residuals, n rows x 1 column, can be zero
      )
    {
      if(numFactors>NumberOfFactors)
        throw new ArgumentOutOfRangeException(string.Format("Required numFactors (={0}) is higher than numFactors of analysis (={1})",numFactors,NumberOfFactors));

      Predict(
        XU, // unknown spectrum or spectra,  horizontal oriented
        _calib.XLoads, // x-loads matrix
        _calib.YLoads, // y-loads matrix
        _calib.XWeights, // weighting matrix
        _calib.CrossProduct,  // Cross product vector
        numFactors, // number of factors to use for prediction
        predictedY, // Matrix of predicted y-values, must be same number of rows as spectra
        spectralResiduals // Matrix of spectral residuals, n rows x 1 column, can be zero
        );
    }
コード例 #51
0
 /// <summary>
 /// Calculates the spectral leverage from preprocessed spectra.
 /// </summary>
 /// <param name="matrixX">Matrix of spectra (a spectrum = a row in the matrix).</param>
 /// <param name="numFactors">Number of factors used for calculation.</param>
 /// <returns>Matrix of spectral leverages. Normally, this is a (NumberOfPoints,1) matrix, with exception of PLS1, where it is a (NumberOfPoints,NumberOfY) matrix.</returns>
 public virtual IROMatrix GetXLeverageFromPreprocessed(IROMatrix matrixX, int numFactors)
 {
   IMatrix result = new MatrixMath.BEMatrix(matrixX.Rows,1);
   this.InternalGetXLeverageFromPreprocessed(matrixX,numFactors,result);
   return result;
 }
コード例 #52
0
ファイル: DoubleVector.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Returns the column of a <see cref="IROMatrix" /> as a new <c>double[]</c> array.
		/// </summary>
		/// <param name="mat">The matrix to copy the column from.</param>
		/// <param name="col">Index of the column to copy from the matrix.</param>
		/// <returns>A new array of <c>double</c> with the same elements as the column of the given matrix.</returns>
		public static double[] GetColumnAsArray(IROMatrix mat, int col)
		{
			double[] result = new double[mat.Rows];
			for (int i = 0; i < result.Length; ++i)
				result[i] = mat[i, col];

			return result;
		}
コード例 #53
0
ファイル: DoubleVector.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Returns the column of a <see cref="IROMatrix" /> as a new <c>DoubleVector.</c>
		/// </summary>
		/// <param name="mat">The matrix to copy the column from.</param>
		/// <param name="col">Number of column to copy from the matrix.</param>
		/// <returns>A new <c>DoubleVector</c> with the same elements as the column of the given matrix.</returns>
		public static DoubleVector GetColumn(IROMatrix mat, int col)
		{
			DoubleVector result = new DoubleVector(mat.Rows);
			for (int i = 0; i < result.data.Length; ++i)
				result.data[i] = mat[i, col];

			return result;
		}
コード例 #54
0
    /// <summary>
    /// Calculates the spectral residuals obtained from cross validation.
    /// </summary>
    /// <param name="spectralRegions">Array of ascending indices representing the starting indices of spectral regions.</param>
    /// <param name="X">Matrix of spectra (a spectrum = a row in the matrix).</param>
    /// <param name="Y">Matrix of y values (e.g. concentrations).</param>
    /// <param name="numFactors">Number of factors used for calculation.</param>
    /// <param name="groupingStrategy">The strategy how to group the spectra for cross prediction.</param>
    /// <param name="preprocessOptions">Information how to preprocess the data.</param>
    /// <param name="regress">The type of regression (e.g. PCR, PLS1, PLS2) provided as an empty regression object.</param>
    /// <param name="crossXResiduals">Returns the matrix of spectral residuals</param>
    /// <returns>Mean number of spectra used for prediction.</returns>
    public static double GetCrossXResiduals(
      int[] spectralRegions,
      IROMatrix X, // matrix of spectra (a spectra is a row of this matrix)
      IROMatrix Y, // matrix of concentrations (a mixture is a row of this matrix)
      int numFactors,
      ICrossValidationGroupingStrategy groupingStrategy,
      SpectralPreprocessingOptions preprocessOptions,
      MultivariateRegression regress,

      out IROMatrix crossXResiduals
      )
    {
      CrossPredictedXResidualsEvaluator worker = new CrossPredictedXResidualsEvaluator(X.Rows,spectralRegions,numFactors,groupingStrategy,preprocessOptions,regress);
      double result = CrossValidationIteration(X,Y,groupingStrategy,new CrossValidationIterationFunction(worker.EhCrossValidationWorker));
      crossXResiduals = worker.XCrossResiduals;
      return result;
    }
コード例 #55
0
 /// <summary>
 /// Fits a data set linear to a given x base.
 /// </summary>
 /// <param name="xbase">The matrix of x values of the data set. Dimensions: numberOfData x numberOfParameters. The matrix is changed during calculation!</param>
 /// <param name="yarr">The array of y values of the data set.</param>
 /// <param name="stddev">The array of y standard deviations of the data set.</param>
 /// <param name="numberOfData">The number of data points (may be smaller than the array sizes of the data arrays).</param>
 /// <param name="numberOfParameter">The number of parameters to fit == size of the function base.</param>
 /// <param name="threshold">A treshold value (usually 1E-5) used to chop the unimportant singular values away.</param>
 public LinearFitBySvd(
   IROMatrix xbase, // NumberOfData, NumberOfParameters 
   double[] yarr,
   double[] stddev,
   int numberOfData,
   int numberOfParameter,
   double threshold)
 {
   Calculate(xbase,yarr,stddev,numberOfData,numberOfParameter,threshold);
 }
コード例 #56
0
    public static void Predict(
      IROMatrix XU, // unknown spectrum or spectra,  horizontal oriented
      IROMatrix xLoads, // x-loads matrix
      IROMatrix yLoads, // y-loads matrix
      IROMatrix W, // weighting matrix
      IROMatrix V,  // Cross product vector
      int numFactors, // number of factors to use for prediction
      IMatrix predictedY, // Matrix of predicted y-values, must be same number of rows as spectra
      IMatrix spectralResiduals // Matrix of spectral residuals, n rows x 1 column, can be zero
      )
    {

      // now predicting a "unkown" spectra
      MatrixMath.Scalar si = new MatrixMath.Scalar(0);
      MatrixMath.HorizontalVector Cu = new MatrixMath.HorizontalVector(yLoads.Columns);

      MatrixMath.HorizontalVector wi = new MatrixMath.HorizontalVector(XU.Columns);
      MatrixMath.HorizontalVector cuadd = new MatrixMath.HorizontalVector(yLoads.Columns);
      
      // xu holds a single spectrum extracted out of XU
      MatrixMath.HorizontalVector xu = new MatrixMath.HorizontalVector(XU.Columns);

      // xl holds temporarily a row of the xLoads matrix+
      MatrixMath.HorizontalVector xl = new MatrixMath.HorizontalVector(xLoads.Columns);


      int maxFactors = Math.Min(yLoads.Rows,numFactors);
      

      for(int nSpectrum=0;nSpectrum<XU.Rows;nSpectrum++)
      {
        MatrixMath.Submatrix(XU,xu,nSpectrum,0); // extract one spectrum to predict
        MatrixMath.ZeroMatrix(Cu); // Set Cu=0
        for(int i=0;i<maxFactors;i++)
        {
          //1. Calculate the unknown spectral score for a weighting vector
          MatrixMath.Submatrix(W,wi,i,0);
          MatrixMath.MultiplySecondTransposed(wi,xu,si);
          // take the y loading vector
          MatrixMath.Submatrix(yLoads,cuadd,i,0);
          // and multiply it with the cross product and the score
          MatrixMath.MultiplyScalar(cuadd,si*V[0,i],cuadd);
          // Add it to the predicted y-values
          MatrixMath.Add(Cu,cuadd,Cu);
          // remove the spectral contribution of the factor from the spectrum
          // TODO this is quite ineffective: in every loop we extract the xl vector, we have to find a shortcut for this!
          MatrixMath.Submatrix(xLoads,xl,i,0);
          MatrixMath.SubtractProductFromSelf(xl,(double)si,xu);
        }
        // xu now contains the spectral residual,
        // Cu now contains the predicted y values
        if(null!=predictedY)
        {
          MatrixMath.SetRow(Cu,0,predictedY,nSpectrum);
        }

        if(null!=spectralResiduals)
        {
          spectralResiduals[nSpectrum,0] = MatrixMath.SumOfSquares(xu);
        }

      } // for each spectrum in XU
    } // end partial-least-squares-predict
コード例 #57
0
 public override IROVector GetPRESSFromPreprocessed(IROMatrix matrixX)  {  return this._PRESS; }
コード例 #58
0
    } // end partial-least-squares-predict


    /// <summary>
    /// Get the prediction score matrix. To get the predictions, you have to multiply
    /// the spectras to predict by this prediction score matrix (in case of a single y-variable), this is
    /// simply the dot product.
    /// </summary>
    /// <param name="xLoads">Matrix of spectral loads [factors,spectral bins].</param>
    /// <param name="yLoads">Matrix of concentration loads[factors, number of concentrations].</param>
    /// <param name="W">Matrix of spectral weightings [factors,spectral bins].</param>
    /// <param name="V">Cross product matrix[1,factors].</param>
    /// <param name="numFactors">Number of factors to use to calculate the score matrix.</param>
    /// <param name="predictionScores">Output: the resulting score matrix[ spectral bins, numberOfConcentrations]</param>
    public static void GetPredictionScoreMatrix(
      IROMatrix xLoads, // x-loads matrix
      IROMatrix yLoads, // y-loads matrix
      IROMatrix W, // weighting matrix
      IROMatrix V,  // Cross product vector
      int numFactors, // number of factors to use for prediction
      IMatrix predictionScores 
      )
    {

      Matrix bidiag = new Matrix(numFactors,numFactors);
      IROMatrix subweights = MatrixMath.ToROSubMatrix(W,0,0,numFactors,W.Columns);
      IROMatrix subxloads  = MatrixMath.ToROSubMatrix(xLoads,0,0,numFactors,xLoads.Columns);
      MatrixMath.MultiplySecondTransposed(subxloads,subweights,bidiag);
      IMatrix invbidiag = bidiag.Inverse;

      
      Matrix subyloads = new Matrix(numFactors,yLoads.Columns);
      MatrixMath.Submatrix(yLoads,subyloads,0,0);
      // multiply each row of the subyloads matrix by the appropriate weight
      for(int i=0;i<subyloads.Rows;i++)
        for(int j=0;j<subyloads.Columns;j++)
          subyloads[i,j] *= V[0,i];

      Matrix helper = new Matrix(numFactors,yLoads.Columns);
      MatrixMath.Multiply(invbidiag,subyloads,helper);

      //Matrix scores = new Matrix(yLoads.Columns,xLoads.Columns);
      //MatrixMath.MultiplyFirstTransposed(helper,subweights,predictionScores); // we calculate the transpose of scores (i.e. scores are horizontal oriented here)
      MatrixMath.MultiplyFirstTransposed(subweights,helper,predictionScores); // we calculate the transpose of scores (i.e. scores are horizontal oriented here)

      // now calculate the ys from the scores and the spectra

      //MultiplySecondTransposed(XU,scores,predictedY);
    } // end partial-least-squares-predict
コード例 #59
0
ファイル: DoubleVector.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Returns the row of a <see cref="IROMatrix" /> as a new <c>DoubleVector.</c>
		/// </summary>
		/// <param name="mat">The matrix to copy the column from.</param>
		/// <param name="row">Index of the row to copy from the matrix.</param>
		/// <returns>A new <c>DoubleVector</c> with the same elements as the row of the given matrix.</returns>
		public static DoubleVector GetRow(IROMatrix mat, int row)
		{
			DoubleVector result = new DoubleVector(mat.Columns);
			for (int i = 0; i < result.data.Length; ++i)
				result.data[i] = mat[row, i];

			return result;
		}
コード例 #60
-1
		/// <summary>
		/// Execution of the fast nonnegative least squares algorithm. The algorithm finds a vector x with all elements xi&gt;=0 which minimizes |X*x-y|.
		/// </summary>
		/// <param name="XtX">X transposed multiplied by X, thus a square matrix.</param>
		/// <param name="Xty">X transposed multiplied by Y, thus a matrix with one column and same number of rows as X.</param>
		/// <param name="isRestrictedToPositiveValues">Function that takes the parameter index as argument and returns true if the parameter at this index is restricted to positive values; otherwise the return value must be false.</param>
		/// <param name="tolerance">Used to decide if a solution element is less than or equal to zero. If this is null, a default tolerance of tolerance = MAX(SIZE(XtX)) * NORM(XtX,1) * EPS is used.</param>
		/// <param name="x">Output: solution vector (matrix with one column and number of rows according to dimension of X.</param>
		/// <param name="w">Output: Lagrange vector. Elements which take place in the fit are set to 0. Elements fixed to zero contain a negative number.</param>
		/// <remarks>
		/// <para>
		/// Literature: Rasmus Bro and Sijmen De Jong, 'A fast non-negativity-constrained least squares algorithm', Journal of Chemometrics, Vol. 11, 393-401 (1997)
		/// </para>
		/// <para>
		/// Algorithm modified by Dirk Lellinger 2015 to allow a mixture of restricted and unrestricted parameters.
		/// </para>
		/// </remarks>
		public static void Execution(IROMatrix XtX, IROMatrix Xty, Func<int, bool> isRestrictedToPositiveValues, double? tolerance, out IMatrix x, out IMatrix w)
		{
			if (null == XtX)
				throw new ArgumentNullException(nameof(XtX));
			if (null == Xty)
				throw new ArgumentNullException(nameof(Xty));
			if (null == isRestrictedToPositiveValues)
				throw new ArgumentNullException(nameof(isRestrictedToPositiveValues));

			if (XtX.Rows != XtX.Columns)
				throw new ArgumentException("Matrix should be a square matrix", nameof(XtX));
			if (Xty.Columns != 1)
				throw new ArgumentException(nameof(Xty) + " should be a column vector (number of columns should be equal to 1)", nameof(Xty));
			if (Xty.Rows != XtX.Columns)
				throw new ArgumentException("Number of rows in " + nameof(Xty) + " should match number of columns in " + nameof(XtX), nameof(Xty));

			var matrixGenerator = new Func<int, int, DoubleMatrix>((rows, cols) => new DoubleMatrix(rows, cols));

			// if nargin < 3
			//   tol = 10 * eps * norm(XtX, 1) * length(XtX);
			// end
			double tol = tolerance.HasValue ? tolerance.Value : 10 * DoubleConstants.DBL_EPSILON * MatrixMath.Norm(XtX, MatrixNorm.M1Norm) * Math.Max(XtX.Rows, XtX.Columns);

			//	[m, n] = size(XtX);
			int n = XtX.Columns;

			// P = zeros(1, n);
			// Z = 1:n;
			var P = new bool[n]; // POSITIVE SET: all indices which are currently not fixed are marked with TRUE (Negative set is simply this, but inverted)
			bool initializationOfSolutionRequired = false;
			for (int i = 0; i < n; ++i)
			{
				bool isNotRestricted = !isRestrictedToPositiveValues(i);
				P[i] = isNotRestricted;
				initializationOfSolutionRequired |= isNotRestricted;
			}

			// x = P';
			x = matrixGenerator(n, 1);

			// w = Xty-XtX*x;
			w = matrixGenerator(n, 1);
			MatrixMath.Copy(Xty, w);
			var helper_n_1 = matrixGenerator(n, 1);
			MatrixMath.Multiply(XtX, x, helper_n_1);
			MatrixMath.Subtract(w, helper_n_1, w);

			// set up iteration criterion
			int iter = 0;
			int itmax = 30 * n;

			// outer loop to put variables into set to hold positive coefficients
			// while any(Z) & any(w(ZZ) > tol)
			while (initializationOfSolutionRequired || (P.Any(ele => false == ele) && w.Any((r, c, ele) => false == P[r] && ele > tol)))
			{
				if (initializationOfSolutionRequired)
				{
					initializationOfSolutionRequired = false;
				}
				else
				{
					// [wt, t] = max(w(ZZ));
					// t = ZZ(t);
					int t = -1; // INDEX
					double wt = double.NegativeInfinity;
					for (int i = 0; i < n; ++i)
					{
						if (!P[i])
						{
							if (w[i, 0] > wt)
							{
								wt = w[i, 0];
								t = i;
							}
						}
					}

					// P(1, t) = t;
					// Z(t) = 0;
					P[t] = true;
				}

				// z(PP')=(Xty(PP)'/XtX(PP,PP)');
				var subXty = Xty.SubMatrix(P, 0, matrixGenerator); // Xty(PP)'
				var subXtX = XtX.SubMatrix(P, P, matrixGenerator);
				var solver = new DoubleLUDecomp(subXtX);
				var subSolution = solver.Solve(subXty);
				var z = matrixGenerator(n, 1);
				for (int i = 0, ii = 0; i < n; ++i)
					z[i, 0] = P[i] ? subSolution[ii++, 0] : 0;

				// C. Inner loop (to remove elements from the positive set which no longer belong to)
				while (z.Any((r, c, ele) => true == P[r] && ele <= tol && isRestrictedToPositiveValues(r)) && iter < itmax)
				{
					++iter;
					// QQ = find((z <= tol) & P');
					//alpha = min(x(QQ)./ (x(QQ) - z(QQ)));
					double alpha = double.PositiveInfinity;
					for (int i = 0; i < n; ++i)
					{
						if ((z[i, 0] <= tol && true == P[i] && isRestrictedToPositiveValues(i)))
						{
							alpha = Math.Min(alpha, x[i, 0] / (x[i, 0] - z[i, 0]));
						}
					}
					// x = x + alpha * (z - x);
					for (int i = 0; i < n; ++i)
						x[i, 0] += alpha * (z[i, 0] - x[i, 0]);

					// ij = find(abs(x) < tol & P' ~= 0);
					// Z(ij) = ij';
					// P(ij) = zeros(1, length(ij));

					for (int i = 0; i < n; ++i)
					{
						if (Math.Abs(x[i, 0]) < tol && P[i] == true && isRestrictedToPositiveValues(i))
						{
							P[i] = false;
						}
					}

					//PP = find(P);
					//ZZ = find(Z);
					//nzz = size(ZZ);
					//z(PP) = (Xty(PP)'/XtX(PP,PP)');

					subXty = Xty.SubMatrix(P, 0, matrixGenerator);
					subXtX = XtX.SubMatrix(P, P, matrixGenerator);
					solver = new DoubleLUDecomp(subXtX);
					subSolution = solver.Solve(subXty);

					for (int i = 0, ii = 0; i < n; ++i)
						z[i, 0] = P[i] ? subSolution[ii++, 0] : 0;
				} // end inner loop

				MatrixMath.Copy(z, x);
				MatrixMath.Copy(Xty, w);
				MatrixMath.Multiply(XtX, x, helper_n_1);
				MatrixMath.Subtract(w, helper_n_1, w);
			}
		}