javascriptbest-fit-curve

How do I create a best-fit polynomial curve in Javascript?


I'm trying to calculate a best-fit curve for data using a 3-6 order polynomial. I found this tutorial: Cubic Regression (best fit line) in JavaScript

First, I can't seem to get my outputs to remotely match the curve. jsbin here: http://jsbin.com/qukuqigobu/1/edit?html,js,console,output

var data_x = [500,1000,1500,2000,2500,3000,3500,4000,4500,5000,5500,6000,6500,7000];
var data_y = [50,80,100,160,210,265,340,390,440,470,500,500,495,460];

var cubic = function(params,x) {
  return params[0] * x*x*x +
    params[1] * x*x +
    params[2] * x +
    params[3];
};

var objective = function(params) {
  var total = 0.0;
  for(var i=0; i < data_x.length; ++i) {
    var resultThisDatum = cubic(params, data_x[i]);
    var delta = resultThisDatum - data_y[i];
    total += (delta*delta);
  }
  return total;
};

var initial = [1,1,1,1];
var minimiser = numeric.uncmin(objective,initial);

console.log("initial:");
for(var j=0; j<initial.length; ++j) {
  console.log(initial[j]);  
}

console.log("minimiser:");
for(var j=0; j<minimiser.solution.length; ++j) {
  console.log(minimiser.solution[j]);
}

My output coefficients are:

1
-17358.001260500238
80977844.06724495
-96625621220.328

However, using LINEST in excel, they are:

-4.68257E-09
4.26789E-05
-0.01
45.39760539

I calculated Y values from the Xs in Excel using this to confirm a good correlation. The minimizer results do not work.

This is the first step, but ideally I'd want to be able to do the same thing for 4th, 5th and 6th order polynomials as well.

Any help would be much appreciated. Thanks.


Solution

  • Figured it out using Matrix Algebra:

    var x = [500,1000,1500,2000,2500,3000,3500,4000,4500,5000,5500,6000,6500,7000];
    var y = [50,80,100,160,210,265,340,390,440,470,500,500,495,460];
    
    order = 3;
    
    var xMatrix = [];
    var xTemp = [];
    var yMatrix = numeric.transpose([y]);
    
    for (j=0;j<x.length;j++)
    {
        xTemp = [];
        for(i=0;i<=order;i++)
        {
            xTemp.push(1*Math.pow(x[j],i));
        }
        xMatrix.push(xTemp);
    }
    
    var xMatrixT = numeric.transpose(xMatrix);
    var dot1 = numeric.dot(xMatrixT,xMatrix);
    var dotInv = numeric.inv(dot1);
    var dot2 = numeric.dot(xMatrixT,yMatrix);
    var solution = numeric.dot(dotInv,dot2);
    console.log("Coefficients a + bx^1 + cx^2...")
    console.log(solution);
    

    jsbin: http://jsbin.com/yoqiqanofo/1/