/// <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); } }
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); } }
public CrossValidationResult(int numberOfPoints, int numberOfY, int numberOfFactors, bool multipleSpectralResiduals) { _predictedY = new IMatrix[numberOfFactors + 1]; _spectralResidual = new IMatrix[numberOfFactors + 1]; _crossPRESS = VectorMath.CreateExtensibleVector(numberOfFactors + 1); for (int i = 0; i <= numberOfFactors; i++) { _predictedY[i] = new MatrixMath.BEMatrix(numberOfPoints, numberOfY); _spectralResidual[i] = new MatrixMath.BEMatrix(numberOfPoints, multipleSpectralResiduals ? numberOfY : 1); } }
/// <summary> /// Processes the spectra in matrix xMatrix. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Output: On return, contains the ensemble mean of the spectra.</param> /// <param name="xScale">Not used.</param> /// <param name="regions">Vector of spectal regions. Each element is the index of the start of a new region.</param> public override void Process(IMatrix xMatrix, IVector xMean, IVector xScale, int[] regions) { // note: we have a light deviation here to the literature: // we repeat the multiple scattering correction until the xMean vector is self consistent, // in detail: after each MSC correction, we calculate the new xMean and compare with the xMean // of the step before. We repeat until the deviation of the xMean to the xMean_before is // reasonable small. // The reason for this deviation is that we don't want to store two separate xMean vectors: one used // for MSC (the x in linear regression) and another to center the MSC corrected spectra IVector xMeanBefore = null; double threshold = 1E-14 * MatrixMath.SumOfSquares(xMatrix) / xMatrix.Rows; for (int cycle = 0; cycle < 50; cycle++) { // 1.) Get the mean spectrum // we want to have the mean of each matrix column, but not center the matrix now, since this // is done later on int cols = xMatrix.Columns; int rows = xMatrix.Rows; for (int n = 0; n < cols; n++) { double sum = 0; for (int i = 0; i < rows; i++) { sum += xMatrix[i, n]; } xMean[n] = sum / rows; } // 2.) Process the spectras ProcessForPrediction(xMatrix, xMean, xScale, regions); // 3. Compare the xMean with the xMean_before if (xMeanBefore == null) { xMeanBefore = VectorMath.CreateExtensibleVector(xMean.Length); VectorMath.Copy(xMean, xMeanBefore); } else { double sumdiffsquare = VectorMath.SumOfSquaredDifferences(xMean, xMeanBefore); if (sumdiffsquare < threshold) { break; } else { VectorMath.Copy(xMean, xMeanBefore); } } } }
/// <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; }
/// <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 <double> matrixX, IROMatrix <double> matrixY, int maxFactors) { int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.ColumnCount, maxFactors); var _xLoads = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0); var _yLoads = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0); var _W = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0); var _V = new MatrixMath.TopSpineJaggedArrayMatrix <double>(0, 0); _PRESS = VectorMath.CreateExtensibleVector <double>(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; }
public static void CalculatePRESS( IROMatrix matrixX, IROMatrix xLoads, IROMatrix yLoads, IROMatrix xScores, IROVector crossProduct, int numberOfFactors, out IROVector PRESS) { IMatrix predictedY = new JaggedArrayMatrix(yLoads.Rows, yLoads.Columns); IVector press = VectorMath.CreateExtensibleVector(numberOfFactors + 1); PRESS = press; press[0] = MatrixMath.SumOfSquares(yLoads); for (int nf = 0; nf < numberOfFactors; nf++) { Predict(matrixX, xLoads, yLoads, xScores, crossProduct, nf, predictedY, null); press[nf + 1] = MatrixMath.SumOfSquaredDifferences(yLoads, predictedY); } }
public static void CalculatePRESS( IROMatrix <double> matrixX, IROMatrix <double> xLoads, IROMatrix <double> yLoads, IROMatrix <double> xScores, IReadOnlyList <double> crossProduct, int numberOfFactors, out IROVector <double> PRESS) { IMatrix <double> predictedY = new JaggedArrayMatrix(yLoads.RowCount, yLoads.ColumnCount); var press = VectorMath.CreateExtensibleVector <double>(numberOfFactors + 1); PRESS = press; press[0] = MatrixMath.SumOfSquares(yLoads); for (int nf = 0; nf < numberOfFactors; nf++) { Predict(matrixX, xLoads, yLoads, xScores, crossProduct, nf, predictedY, null); press[nf + 1] = MatrixMath.SumOfSquaredDifferences(yLoads, predictedY); } }