public double Interpolate(double x, double y) { var z = new MatrixMath.ScalarAsMatrix <double>(); itplbv_(_myX.Count, _myY.Count, _myX, _myY, _myZ, 1, new MatrixMath.ScalarAsMatrix <double>(x), new MatrixMath.ScalarAsMatrix <double>(y), z); return(z); }
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
/// <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 <double> _X, // matrix of spectra (a spectra is a row of this matrix) IROMatrix <double> _Y, // matrix of concentrations (a mixture is a row of this matrix) ref int numFactors, IBottomExtensibleMatrix <double> xLoads, // out: the loads of the X matrix IBottomExtensibleMatrix <double> yLoads, // out: the loads of the Y matrix IBottomExtensibleMatrix <double> W, // matrix of weighting values IRightExtensibleMatrix <double> V, // matrix of cross products IExtensibleVector <double> 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 var mean = new MatrixMath.MatrixWithOneRow <double>(_X.ColumnCount); // MatrixMath.ColumnsToZeroMean(X,mean); //W.AppendBottom(mean); var X = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(_X.RowCount, _X.ColumnCount); MatrixMath.Copy(_X, X); var Y = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(_Y.RowCount, _Y.ColumnCount); MatrixMath.Copy(_Y, Y); IMatrix <double> u_prev = null; var w = new MatrixMath.MatrixWithOneRow <double>(X.ColumnCount); // horizontal vector of X (spectral) weighting var t = new MatrixMath.MatrixWithOneColumn <double>(X.RowCount); // vertical vector of X scores var u = new MatrixMath.MatrixWithOneColumn <double>(X.RowCount); // vertical vector of Y scores var p = new MatrixMath.MatrixWithOneRow <double>(X.ColumnCount); // horizontal vector of X loads var q = new MatrixMath.MatrixWithOneRow <double>(Y.ColumnCount); // horizontal vector of Y loads int maxFactors = Math.Min(X.ColumnCount, X.RowCount); numFactors = numFactors <= 0 ? maxFactors : Math.Min(numFactors, maxFactors); if (PRESS != null) { PRESS.Append(new MatrixMath.ScalarAsMatrix <double>(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.MatrixWithOneColumn <double>(X.RowCount); } 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); var v = new MatrixMath.ScalarAsMatrix <double>(0); MatrixMath.MultiplyFirstTransposed(u, t, (IVector <double>)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.ScalarAsMatrix <double>(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 }