hi all
   I am using commons math to solve a linear equation. When I use
LUDecomposition, it throws a SingularMatrixException. If I switch it
to QRDecomposition, it's ok.
   The problem is a simple polynomial regression. it is taken from
Bishop's book "pattern recognition and machine learning", chapter 1.
   the data is generated by sin*2*pi*x + gaussian noise.
   x=[0,1/9,2/9,...,1]
   t=sin*2*pi*x + gaussian noise with starndard deviation of 0.3

   y(w,x)=w0 + w1 * x +w2 * x^2 + .. + wm * x^m
   loss function: E(w)=1/2 {t1-y(w,x1)}^2 + ....
   take differentiating with respect to wi
   we get coefficients w = {wi} that minimize this error function are
given by the solution to the following
set of linear equations:
   Aw=T
   Aij=(x1)^(i+j) + (x2)^(i+j) + .. + (xn)^(i+j), A is a (M+1)*(M+1)
symmetric matrix
   Ti=(x1)^i * t1 + (x2)^i * t2 + ... + (xn)^i * tn, T is a (M+1) vector
   w=(w0,w1,...wM)' is a (M+1) vector

   by solve w, we can find best w to minimize loss function.

   for n=10 and M=0 to 9, it's correct.
   But for n=10 and M=10, it throws an exception.

   what's wrong with it?

   Following is my codes:

PolynomialCurveFit .java

public class PolynomialCurveFit {

/**
* @param args
*/
public static void main(String[] args) {
SyntheticRegressionDataGenerator srd=new SyntheticRegressionDataGenerator();
Point2D[] trainingData=srd.generateDataXWithFixedInterval(10, 0.3);
Point2D[] testData=srd.generateData(10, 0.3);
PolynomialCurveFit pcf=new PolynomialCurveFit();
System.out.println("\nLU Decomposition\n");
for(int order=0;order<=12;order++){
System.out.println("order: "+order);
try{
double[] weights=pcf.solveByCommonMathLUDecomposition(trainingData, order);
double trainErr=pcf.calcRootMeanSquareError(trainingData, weights, true);
double testErr=pcf.calcRootMeanSquareError(testData, weights, false);
System.out.println("training error: "+trainErr);
System.out.println("test error: "+testErr);
System.out.println();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println("\nQR Decomposition\n");
for(int order=0;order<=12;order++){
System.out.println("order: "+order);
try{
double[] weights=pcf.solveByCommonMathQRDecomposition(trainingData, order);
// System.out.print("Weights:");
// for(double weight:weights){
// System.out.print("\t"+weight);
// }
// System.out.println();
double trainErr=pcf.calcRootMeanSquareError(trainingData, weights, true);
double testErr=pcf.calcRootMeanSquareError(testData, weights, false);
System.out.println("training error: "+trainErr);
System.out.println("test error: "+testErr);
System.out.println();
}catch(Exception e){
System.out.println("Fail");
}
}
}
public double calcRootMeanSquareError(Point2D[] array,double[]
weights,boolean isTraining){
double error=0;
for(Point2D point:array){
double x=point.getX();
double y=this.predictByPolynomial(x, weights);
double realY;
if(!isTraining){
realY=Math.sin(2*Math.PI*x);
}else{
realY=point.getY();
}
error+=(y-realY)*(y-realY);
}
error=Math.sqrt(error/array.length);
return error;
}
private double predictByPolynomial(double x,double[] weights){
double result=0;
for(int i=0;i<weights.length;i++){
result+=weights[i]*Math.pow(x, i);
}
return result;
}
public double[] solveByCommonMathLUDecomposition(Point2D[] array,int order){
Array2DRowRealMatrix coefficients =new Array2DRowRealMatrix(order+1, order+1);
ArrayRealVector constants=new ArrayRealVector(order+1);
for(int i=0;i<=order;i++){
double Ti=0;
for(Point2D point:array){
Ti+=point.getY()*Math.pow(point.getX(), i);
}
constants.setEntry(i, Ti);
}
for(int i=0;i<=order;i++){
for(int j=0;j<=order;j++){
double Aij=0;
for(Point2D point:array){
Aij+=Math.pow(point.getX(), i+j);
}
coefficients.setEntry(i, j, Aij);
}
}

DecompositionSolver solver = new LUDecomposition(coefficients).getSolver();
RealVector solution = solver.solve(constants);
return solution.toArray();
}
public double[] solveByCommonMathQRDecomposition(Point2D[] array,int order){
Array2DRowRealMatrix coefficients =new Array2DRowRealMatrix(order+1, order+1);
ArrayRealVector constants=new ArrayRealVector(order+1);
for(int i=0;i<=order;i++){
double Ti=0;
for(Point2D point:array){
Ti+=point.getY()*Math.pow(point.getX(), i);
}
constants.setEntry(i, Ti);
}
for(int i=0;i<=order;i++){
for(int j=0;j<=order;j++){
double Aij=0;
for(Point2D point:array){
Aij+=Math.pow(point.getX(), i+j);
}
coefficients.setEntry(i, j, Aij);
}
}
DecompositionSolver solver = new QRDecomposition(coefficients).getSolver();
RealVector solution = solver.solve(constants);
return solution.toArray();
}

}

SyntheticRegressionDataGenerator.java

public class SyntheticRegressionDataGenerator {
public Point2D[] generateDataXWithFixedInterval(int N,double
noiseStandardDeviation){
if(N<1){
throw new IllegalArgumentException("N must great than 0. N="+N);
}

RandomDataGenerator rdg=new RandomDataGenerator(new MersenneTwister());
Point2D[] array=new Point2D[N];
double interval=1.0/(N-1);
double x=0;
double y=0;
for(int i=0;i<N;i++){
y=Math.sin(2*Math.PI*x)+rdg.nextGaussian(0, noiseStandardDeviation);
array[i]=new Point2D(x, y);
x+=interval;
}
return array;
}
public Point2D[] generateData(int N,double noiseStandardDeviation){
if(N<1){
throw new IllegalArgumentException("N must great than 0. N="+N);
}
RandomDataGenerator rdg=new RandomDataGenerator(new MersenneTwister());
Point2D[] array=new Point2D[N];

double x=0;
double y=0;
for(int i=0;i<N;i++){
x=rdg.nextUniform(0, 1.0, true);
y=Math.sin(2*Math.PI*x)+rdg.nextGaussian(0, noiseStandardDeviation);
array[i]=new Point2D(x, y);

}
return array;
}

}

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@commons.apache.org
For additional commands, e-mail: user-h...@commons.apache.org

Reply via email to