public void Test02_4x3Matrix() { double[][] x = new double[4][] { new double[] { 1, 1, 1 }, new double[] { 1, 2, 4 }, new double[] { 1, 3, 9 }, new double[] { 1, 4, 16 } }; double[][] expectedU = new double[][] { new double[] { 0.06694942772363194830335878, -0.6496907508990609956156238, 0.7234775064393449793067184 }, new double[] { 0.2274012268163765838895085, -0.6075911990028880215461633, -0.3593349648122762034053743 }, new double[] { 0.4855667535109152389501883, -0.2675906812177502659847019, -0.4925648741133399561928825 }, new double[] { 0.8414460078072479134853980, 0.3703108024563522710687606, 0.3237877785361537209441937 } }; double[] expectedSingularValues = new double[] { 19.62136402366775701042283, 1.712069874450694805376275, 0.2662528792614848629364699 }; double[][] expectedV = new double[][] { new double[] { 0.08263255367478247093846163, -0.6743660675845837168765756, 0.7337589985572162375998953 }, new double[] { 0.2723682291746780408033352, -0.6929635293730795997776881, -0.6675455749947378000917574 }, new double[] { 0.9586383096921561352973747, 0.2550136346341303246410893, 0.1264145456079166187153824 } }; IMatrix X = MatrixMath.ToMatrix(x); MatrixMath.SingularValueDecomposition decomp = MatrixMath.GetSingularValueDecomposition(X); for (int i = 0; i < 3; i++) { Assert.AreEqual(expectedSingularValues[i], decomp.Diagonal[i], accuracy, "SingularValue_" + i.ToString()); } // Test the U Matrix for (int i = 0; i < expectedU.Length; i++) { for (int j = 0; j < expectedU[0].Length; j++) { Assert.AreEqual(Math.Abs(expectedU[i][j]), Math.Abs(decomp.U[i][j]), accuracy, string.Format("U[{0}][{1}]", i, j)); } } // Test the V Matrix for (int i = 0; i < expectedV.Length; i++) { for (int j = 0; j < expectedV[0].Length; j++) { Assert.AreEqual(Math.Abs(expectedV[i][j]), Math.Abs(decomp.V[i][j]), accuracy, string.Format("V[{0}][{1}]", i, j)); } } }
public void Test01_3x3Matrix() { double[][] x = new double[][] { new double[] { 1, 1, 1 }, new double[] { 1, 2, 4 }, new double[] { 1, 3, 9 } }; double[][] expectedU = new double[][] { new double[] { 0.1323855611751141383983336, -0.8014095371363918468296921, 0.5832810788798007027395599 }, new double[] { 0.4263811717635121943505712, -0.4851883520178218054139224, -0.7634077281713910856496549 }, new double[] { 0.8948034195050466074658404, 0.3497642303796436079288927, 0.2774740052491605347063156 } }; double[] expectedSingularValues = new double[] { 10.64956309214167630396485, 1.250703401814404251343328, 0.1501564090663296496197768 }; double[][] expectedV = new double[][] { new double[] { 0.1364910597615280451679478, -0.7490454230919167919488232, 0.6483063664273445542029725 }, new double[] { 0.3445735878052170177361156, -0.5776697728534024470814668, -0.7399774835213155452612752 }, new double[] { 0.9287837386562145112758128, 0.3243895616023268212207566, 0.1792545093748964368092940 } }; IMatrix X = MatrixMath.ToMatrix(x); MatrixMath.SingularValueDecomposition decomp = MatrixMath.GetSingularValueDecomposition(X); // Test singular values for (int i = 0; i < 3; i++) { Assert.AreEqual(expectedSingularValues[i], decomp.Diagonal[i], accuracy, "SingularValue_" + i.ToString()); } // Test the U Matrix for (int i = 0; i < expectedU.Length; i++) { for (int j = 0; j < expectedU[0].Length; j++) { Assert.AreEqual(expectedU[i][j], decomp.U[i][j], accuracy, string.Format("U[{0}][{1}]", i, j)); } } // Test the V Matrix for (int i = 0; i < expectedV.Length; i++) { for (int j = 0; j < expectedV[0].Length; j++) { Assert.AreEqual(expectedV[i][j], decomp.V[i][j], accuracy, string.Format("V[{0}][{1}]", i, j)); } } }
public void Test03_3x4Matrix() { double[][] x = new double[3][] { new double[] { 1, 1, 1, 1 }, new double[] { 1, 2, 4, 8 }, new double[] { 1, 3, 9, 27 } }; double[][] expectedU = new double[][] { new double[] { 0.04734386493551604995477145, -0.6298036597816627273392776, 0.7753102015184575401987200 }, new double[] { 0.3019315922550259026382404, -0.7308495124910898427130366, -0.6121244184721608492599749 }, new double[] { 0.9521532818046222520788651, 0.2630709794279101755469104, 0.1555563811983541387310737 } }; double[] expectedSingularValues = new double[] { 30.06856910125475242387046, 2.167597107698223914976808, 0.4274049388650818475368850, 0 }; double[][] expectedV = new double[][] { new double[] { 0.04328203096770760439694849, -0.5063589487856289461733263, 0.7457615372696186799476553 }, new double[] { 0.1166555975127217050621376, -0.6007988024412046764051820, 0.04148409753120615124080518 }, new double[] { 0.3267348618124714344785811, -0.5469479963247332138954797, -0.6391597680419712306939267 }, new double[] { 0.9368897840411354775696647, 0.2889451561910784800441657, 0.1832855425226170318735145 } }; IMatrix X = MatrixMath.ToMatrix(x); MatrixMath.SingularValueDecomposition decomp = MatrixMath.GetSingularValueDecomposition(X); double[] calculatedSingularValues = decomp.Diagonal; for (int i = 0; i < 4; i++) { Assert.AreEqual(expectedSingularValues[i], calculatedSingularValues[i], accuracy, "SingularValue_" + i.ToString()); } // Test the U Matrix for (int i = 0; i < expectedU.Length; i++) { for (int j = 0; j < expectedU[0].Length; j++) { Assert.AreEqual(Math.Abs(expectedU[i][j]), Math.Abs(decomp.U[i][j]), accuracy, string.Format("U[{0}][{1}]", i, j)); } } // Test the V Matrix for (int i = 0; i < expectedV.Length; i++) { for (int j = 0; j < expectedV[0].Length; j++) { Assert.AreEqual(Math.Abs(expectedV[i][j]), Math.Abs(decomp.V[i][j]), accuracy, string.Format("V[{0}][{1}]", i, j)); } } }
public static void CalculateXLeverageFromPreprocessed( IROMatrix <double> xScores, int numberOfFactors, IMatrix <double> leverage) { var subscores = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(xScores.RowCount, numberOfFactors); MatrixMath.Submatrix(xScores, subscores); var decompose = new MatrixMath.SingularValueDecomposition(subscores); for (int i = 0; i < xScores.RowCount; i++) { leverage[i, 0] = decompose.HatDiagonal[i]; } }
public static void CalculateXLeverageFromPreprocessed( IROMatrix xScores, int numberOfFactors, IMatrix leverage) { IMatrix subscores = new MatrixMath.BEMatrix(xScores.Rows, numberOfFactors); MatrixMath.Submatrix(xScores, subscores); MatrixMath.SingularValueDecomposition decompose = new MatrixMath.SingularValueDecomposition(subscores); for (int i = 0; i < xScores.Rows; i++) { leverage[i, 0] = decompose.HatDiagonal[i]; } }
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, out IROMatrix <double> xLoads, // out: the loads of the X matrix out IROMatrix <double> xScores, // matrix of weighting values out IROVector <double> V // vector of cross products ) { var matrixX = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(X.RowCount, X.ColumnCount); MatrixMath.Copy(X, matrixX); var decompose = new MatrixMath.SingularValueDecomposition(matrixX); numFactors = Math.Min(numFactors, matrixX.ColumnCount); numFactors = Math.Min(numFactors, matrixX.RowCount); xLoads = JaggedArrayMath.ToTransposedROMatrix(decompose.V, Y.RowCount, X.ColumnCount); xScores = JaggedArrayMath.ToMatrix(decompose.U, Y.RowCount, Y.RowCount); V = VectorMath.ToROVector(decompose.Diagonal, numFactors); }
} // 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]; } }
/// <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 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 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); }
public DynamicParameterEstimation Calculate(IROVector x, IROVector y, int numX, int numY, int backgroundOrder) { _numX = numX; _numY = numY; _backgroundOrderPlus1 = 1 + Math.Max(-1, backgroundOrder); // where to start the calculation (index of first y point that can be used) int start = Math.Max(_numX - 1, _numY); int numberOfData = 0; if (numX > 0) { numberOfData = Math.Min(x.Length, y.Length) - start; } else { numberOfData = y.Length - start; } int numberOfParameter = _numX + _numY + _backgroundOrderPlus1; MatrixMath.BEMatrix u = new MatrixMath.BEMatrix(numberOfData, numberOfParameter); // Fill the matrix for (int i = 0; i < numberOfData; i++) { int yIdx = i + start; // x for (int j = 0; j < _numX; j++) { u[i, j] = x[yIdx - j]; } // y for (int j = 0; j < _numY; j++) { u[i, j + _numX] = y[yIdx - 1 - j]; } // polynomial background component double background = 1; for (int j = 0; j < _backgroundOrderPlus1; j++) { u[i, j + _numX + _numY] = background; background *= yIdx; } } // Fill the y double[] scaledY = new double[numberOfData]; for (int i = 0; i < numberOfData; i++) { scaledY[i] = y[i + start]; } _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 _parameter = new double[numberOfParameter]; _decomposition.Backsubstitution(scaledY, _parameter); return(this); }